Skip to content

fix: refuse a stranger TPP reading a consent's status or SCA status - #71

Merged
hongwei1 merged 1 commit into
develop-obpfrom
fix/bg-consent-read-ownership
Aug 9, 2026
Merged

fix: refuse a stranger TPP reading a consent's status or SCA status#71
hongwei1 merged 1 commit into
develop-obpfrom
fix/bg-consent-read-ownership

Conversation

@hongwei1

@hongwei1 hongwei1 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Four endpoints read a Berlin Group consent by id. Two compared the consent’s lodging Consumer against the caller’s; two did not.

Endpoint Ownership check before After
GET /consents/{id} yes yes
GET /consents/{id}/authorisations yes yes
GET /consents/{id}/status no yes
GET /consents/{id}/authorisations/{authorisationId} no yes

Both unguarded routes were already fetching the consent — to prove it exists — and then simply did not look at who was asking. The consent id alone therefore confirmed a consent existed and let its progress through authorisation be watched from outside. The PUT that answers an authorisation is guarded, so this disclosed state rather than granting access.

Verified against a running instance

Two TPPs: A lodges the consent, B is a stranger holding valid AISP credentials.

Before:

TPP B -> GET /consents/{id}                 403  refused
TPP B -> GET /consents/{id}/authorisations  403  refused
TPP B -> GET /consents/{id}/status          200  LEAKED consentStatus
TPP B -> GET /consents/{id}/auth/{aid}      200  LEAKED scaStatus

After — all four refuse the stranger and all four still serve the lodging TPP:

GET /consents/{id}                  stranger=403  owner=200
GET /consents/{id}/authorisations   stranger=403  owner=200
GET /consents/{id}/status           stranger=403  owner=200
GET /consents/{id}/auth/{aid}       stranger=403  owner=200

code.api.berlin.group 183/183. Full local probe matrix 101/101.

Why it was missed

The probe added when the first of these was fixed asserted only the endpoint that had been noticed, so the other three were never examined. It now walks the whole family — which is what surfaced the two that were still open.

Four endpoints read a Berlin Group consent by id. Two compared the consent's
lodging Consumer against the caller's; two did not, and answered any AISP that
knew the consent id:

  GET /consents/{id}/status                      -> consentStatus
  GET /consents/{id}/authorisations/{id}         -> scaStatus

Both were already fetching the consent, to prove it exists, and then simply
did not look at who was asking. So the id alone confirmed a consent existed
and let its progress through authorisation be watched from outside. The PUT
that answers an authorisation is guarded, so this disclosed state rather than
granting access.

Guarded the same way as the two that were already right. Verified with two
TPPs against a running instance: the stranger now gets 403 on all four while
the lodging TPP still gets 200 on all four.

The probe covering this was the direct cause of the gap -- it asserted the one
endpoint that had been noticed, so the other three went unexamined. It now
walks the whole family, which is why the two that were open showed up at all.
@sonarqubecloud

sonarqubecloud Bot commented Aug 8, 2026

Copy link
Copy Markdown

@hongwei1
hongwei1 merged commit da41561 into develop-obp Aug 9, 2026
35 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant