GitHub Security Advisory: GHSA-jqfc-gwj5-3w63
Package: github.com/free5gc/udr (GO)
Severity: MODERATE (CVSS 6.5)
CWE: CWE-704: Incorrect Type Conversion or Cast, CWE-754: Improper Check for Unusual or Exceptional Conditions
Vulnerable versions: < 1.4.3
Patched in: 1.4.3

Summary: free5GC's UDR nudr-dr DELETE amf-subscriptions panics on missing UE state via nil interface type assertion (single authenticated request)

Details:
### Summary
free5GC's UDR `nudr-dr` `DELETE /subscription-data/{ueId}/{servingPlmnId}/ee-subscriptions/{subsId}/amf-subscriptions` handler panics on a single authenticated request against a fresh UDR instance when the supplied `ueId` does not exist in `UESubsCollection`. The processor checks `value, ok := udrSelf.UESubsCollection.Load(ueId)` and sets a `404 USER_NOT_FOUND` problem-details on the miss path, but execution continues and immediately runs `value.(*udr_context.UESubsData)` -- a Go type assertion on a nil interface, which panics with `interface conversion: interface {} is nil, not *context.UESubsData`. Gin recovery converts the panic into `HTTP 500`, but the endpoint remains repeatedly panicable.

This is the no-precondition sibling of free5gc/free5gc#919: same handler, same bug pattern (set `pd`, do not return, then dereference), but the panic site is the nil-interface type assertion at line 61 instead of the nil-pointer deref at line 69. No earlier EE-subscription create is required.

This endpoint requires a valid `nudr-dr` OAuth2 access token (PR:L, NOT PR:N), so this is scored as an authenticated panic-DoS, not as an unauth-bypass finding.

### Details
Validated against the UDR container in the official Docker compose lab.
- Source repo tag: `v4.2.1`
- Running Docker image: `free5gc/udr:v4.2.1`
- Runtime UDR commit: `754d23b0`
- Docker validation date: 2026-03-22
- UDR endpoint: `http://10.100.200.11:8000`

Vulnerable handler (the `ok` miss path sets `pd` but does not return; the next line type-asserts the nil interface):
```go
subsId := c.Params.ByName("subsId")
s.Processor().RemoveAmfSubscriptionsInfoProcedure(c, subsId, ueId)
```
In the processor:
```go
value, ok := udrSelf.UESubsCollection.Load(ueId)
if !ok {
    pd = util.ProblemDetailsNotFound("USER_NOT_FOUND")
}

UESubsData := value.(*udr_context.UESubsData)   // panics: nil interface
```
When `ueId` is absent from `UESubsCollection`, `value` is the nil `interface{}` returned by `sync.Map.Load`, and `value.(*udr_context.UESubsData)` panics with:
```
panic: interface conversion: interface {} is nil, not *context.UESubsData
```

Code evidence (paths in `free5gc/udr`):
- Route exposure + handler dispatch:
  - `NFs/udr/internal/sbi/api_datarepository.go:2161`
  - `NFs/udr/internal/sbi/api_datarepository.go:2170`
  - `NFs/udr/internal/sbi/api_datarepository.go:2172`
- Panic root cause (nil interface type assertion):
  - `NFs/udr/internal/sbi/processor/event_amf_subscription_info_document.go:53`
  - `NFs/udr/internal/sbi/processor/event_amf_subscription_info_document.go:56`
  - `NFs/udr/internal/sbi/processor/event_amf_subscription_info_document.go:61`

### PoC
Reproduced end-to-end against the running UDR at `http://10.100.200.11:8000` -- single authenticated request, no preconditions.

1. Restart UDR (clean state -- proves no precondition is needed):
```
docker restart udr
```

2. Obtain a valid `nudr-dr` token from NRF:
```
curl -sS -X POST 'http://10.100.200.3:8000/oauth2/toke