NL Portal documenten-api CVE-2026-54683
MEDIUMSeverity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Network-accessible endpoints require only a valid user session (PR:L); UUID guessing difficulty is a practical barrier, not a CVSS complexity factor, as no cryptographic or race-condition prerequisite exists once an ID is known.
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
Lifecycle Timeline
2Blast Radius
ecosystem impact- 7 maven packages depend on nl.nl-portal:documenten-api (3 direct, 4 indirect)
Ecosystem-wide dependent count for version 3.0.3.
DescriptionGitHub Advisory
Summary
A previous advisory (CVE-2026-49463 / GHSA-qpm9-h556-mwxm) reported that any logged-in user could download any document by its identifier, and stated this was fixed in 3.0.1. For the document-content part that fix was incomplete: documents remained downloadable by any authenticated user in 3.0.1 and 3.0.2, and the issue was only fully resolved in 3.0.3.
Relationship to CVE-2026-49463
This advisory is a follow-up to CVE-2026-49463. That advisory described the problem on the GraphQL getDocumentContent query and listed nl.nl-portal:documenten-api as fixed in 3.0.1. In practice:
- The 3.0.1 change added an authentication parameter to the GraphQL query but never used it, so the query kept returning any document regardless of ownership.
- The same flaw also existed on a REST endpoint that the original advisory did not cover, and that endpoint was not changed in 3.0.1 or 3.0.2.
Both were removed in 3.0.3, which is the first release where the document-content issue is actually fixed.
What was wrong
A document's contents could be fetched in two ways, and neither verified the caller's relationship to the document:
- a REST endpoint:
GET /api/documentapi/{documentapi}/document/{documentId}/content - a GraphQL query:
getDocumentContent
Being logged in was required, but that was the *only* check - there was no per-document authorization. (A security rule meant to guard the REST endpoint also pointed at the wrong URL and never took effect; even if it had, it would only have required a login, not ownership.)
Proof of concept
While logged in as any portal user, request a document that belongs to someone else:
GET /api/documentapi/openzaak/document/<another-users-document-id>/contentThe server returns the document contents (HTTP 200), even though the caller has no relationship to that document. The getDocumentContent GraphQL query behaves the same way.
Impact
A logged-in user could read the contents of documents belonging to other people. In a citizen or business portal these documents can contain sensitive personal information. To exploit this, an attacker needs a valid login and a target document's identifier. Document identifiers are random and hard to guess, which limits - but does not prevent - abuse, since identifiers can leak through other channels.
Patches
Fixed in 3.0.3. Both the REST endpoint and the GraphQL query were removed entirely. Document contents can now only be downloaded through endpoints that first confirm the caller is allowed to see the document:
- one that requires the caller to have a role on the related case (*zaak*);
- one that requires the caller to own the message (*bericht*) the document is attached to.
If your application relied on the removed endpoints, switch to one of these case- or message-scoped download endpoints.
Workarounds
If you cannot upgrade immediately, block the path GET /api/documentapi/*/document/*/content and the getDocumentContent GraphQL query at your gateway or reverse proxy, and remove any client code that calls them. There is no setting that adds the missing per-document check in affected versions; upgrading (or removing the endpoints) is the only complete fix.
References
- Related advisory: GHSA-qpm9-h556-mwxm (CVE-2026-49463)
- Fix commits: 6e738a87 (GraphQL query removed, PR #690), e326e6db (REST endpoint removed)
- Affected module:
nl.nl-portal:documenten-api
Credits
Reported by Ray Sabee, https://whitehatsecurity.nl/ (independent security researcher). Github handle: raysabee
AnalysisAI
Improper authorization in nl.nl-portal:documenten-api (NL Portal Backend Libraries) exposes document contents to any authenticated portal user, regardless of document ownership. The flaw persisted across versions 3.0.1 and 3.0.2 despite a prior fix attempt for CVE-2026-49463: the GraphQL fix added an authentication parameter that was never passed to the service layer, and a parallel REST endpoint was left entirely unaddressed and protected only by a misconfigured security rule pointing at the wrong URL. No public exploit in CISA KEV, but a functional proof-of-concept is documented in the vendor advisory, and the CVSS 6.5 (PR:L/C:H) score reflects meaningful real-world impact for citizen and business portal deployments handling sensitive personal documents.
Technical ContextAI
The affected component is the Maven artifact nl.nl-portal:documenten-api, part of NL Portal Backend Libraries - a Kotlin/Spring Boot framework used to build Dutch government citizen and business portals. The root cause is CWE-285 (Improper Authorization): two distinct document-content retrieval surfaces - a REST endpoint (GET /api/documentapi/{documentapi}/document/{documentId}/content) and a GraphQL query (getDocumentContent) - enforced session authentication but performed no per-document ownership or relationship check. The 3.0.1 patch for CVE-2026-49463 wired a CommonGroundAuthentication parameter into the GraphQL controller signature but never forwarded it to the service method (DocumentenApiService.getDocumentContent), meaning the authorization object was received and silently ignored. A Spring Security rule intended to guard the REST endpoint was bound to an incorrect URL pattern and never fired. The fix in 3.0.3 removes both surfaces entirely rather than patching them, replacing them with endpoints that require callers to hold a role on a related case (zaak) or own the message (bericht) the document is attached to.
RemediationAI
Upgrade nl.nl-portal:documenten-api to version 3.0.3 or later; this is the first release where both the REST and GraphQL document-content surfaces are fully removed and replaced with ownership-scoped alternatives. The fix commits are 6e738a87 (GraphQL query removed via PR #690) and e326e6db (REST endpoint removed), available at https://github.com/nl-portal/nl-portal-backend-libraries/pull/690. Applications that relied on the removed endpoints must migrate to the case-scoped endpoint (requiring a caller role on the related zaak) or the message-scoped endpoint (requiring caller ownership of the bericht the document is attached to). If an immediate upgrade is not feasible, block the path pattern GET /api/documentapi/*/document/*/content and the GraphQL operation getDocumentContent at your API gateway or reverse proxy; note that this workaround prevents legitimate use of these endpoints entirely and does not add per-document authorization to affected versions - it only removes access. There is no configuration setting in versions prior to 3.0.3 that restores the missing ownership check.
Same weakness CWE-285 – Improper Authorization
View allSame technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-jr45-52cw-69h5