* Tighten UNSAFE_PATH_PATTERN against encoded path-traversal terminators
Fixes#48978
Extends the regex to cover encoded forms that previously bypassed
detection:
- %3B / %3b (encoded semicolon)
- %09, %0A, %0D, %00 (control characters)
- %252E (double-encoded dot)
These encodings do not produce actual path traversal on conformant
servers per RFC 3986 (percent-encoded characters are literals, not
delimiters), but are semantically close enough to the patterns the
regex was designed to block to warrant defense-in-depth coverage.
The end-of-input anchor ($) is moved into the terminator class to
collapse the two pattern alternatives into one, keeping the diff
minimal.
Test changes:
- 8 new assertions covering encoded semicolons, control character
terminators, and double-encoded dots.
- 3 prior assertEquals flipped to assertNull (lines that previously
asserted %252E%252E/, %252E%252E/#fragment, and ..%3Bsomething/
were allowed are now expected to be blocked).
- 1 new negative test confirming %3B as legitimate path content (not
following a parent-folder sequence) still resolves.
Triple-encoded variants (e.g., %25252E) remain allowed; out of scope
for this issue.
Signed-off-by: Michał Kosiorek <michal.kosiorek@arklink.co>
* Update OAuthRedirectUriTest expectations for double-encoded dots
Follow-up to 36b0b10dd2 — Base IT (6) CI run for #49000 caught a
cross-module integration test that needed updating alongside the
regex change. Local verification of the previous commit covered the
services module (RedirectUtilsTest); testsuite/integration-arquillian
was outside that scope, so the existing OAuthRedirectUriTest.testWildcard
expectations for %252E%252E variants didn't flip with the regex.
Four assertions in testWildcard flipped from true → false to match the
Option A semantic introduced in 36b0b10dd2 (double-encoded dots are
now blocked by UNSAFE_PATH_PATTERN):
http://example.com/foo/%252E%252E/http://example.com/foo/%252E%252E/?some_query_param=some_valuehttp://example.com/foo/%252E%252E/?encodeTest=a%3Cbhttp://example.com/foo/%252E%252E/#encodeTest=a%3Cb
Triple-encoded (%25252E) and septuple-encoded variants remain
expected:true — recursive decoding is explicitly out of scope for
#48978.
Verified locally:
- mvn -pl services -Dtest=RedirectUtilsTest test → 11/11 green.
- Direct regex match against the four flipped URIs confirms
UNSAFE_PATH_PATTERN matches each rawPath, mechanically equivalent
to the verifyRedirectUri code path exercised by the arquillian test.
Refs #48978
Signed-off-by: Michał Kosiorek <michal.kosiorek@arklink.co>
---------
Signed-off-by: Michał Kosiorek <michal.kosiorek@arklink.co>
* Move the rest of TestingResource methods to a utils-shared helper class (1/2)
Closes: #48708
Signed-off-by: Simon Vacek <simonvacky@email.cz>
* rename runOnServer field
Signed-off-by: Simon Vacek <simonvacky@email.cz>
* remove realm name from method input
Signed-off-by: Simon Vacek <simonvacky@email.cz>
---------
Signed-off-by: Simon Vacek <simonvacky@email.cz>
OrganizationGroupMembershipMapper.resolveFromRequestedScopes() calls
OrganizationScope.valueOfScope() which returns null when the request does
not include an organization scope. The method then calls
resolveOrganizations() on the null reference, causing a NullPointerException.
This mirrors the null guard already present in OrganizationMembershipMapper.
Closes#48834
Signed-off-by: Umberto Toniolo <amountainram@gmail.com>
Enforce RFC 6749 Section 3.1.2 redirect URI rules (no fragments, no wildcards) via a new "OAuth 2.0 Compliant" client policy flag. This is less strict than the existing OAuth 2.1 flag, which additionally bans localhost and requires HTTPS.
Also fixes the "complient" typo in the existing OAuth 2.1 field and method names.
Closes#41164
Signed-off-by: Jon Koops <jonkoops@gmail.com>
* Make OrganizationGroupMembershipMapper claim name configurable
The OrganizationGroupMembershipMapper introduced in 26.6.0 hardcoded
the token claim name to "organization", unlike OrganizationMembershipMapper
which already exposes the claim name as a configurable property.
- Add TOKEN_CLAIM_NAME config property to OrganizationGroupMembershipMapper
via OIDCAttributeMapperHelper.addTokenClaimNameConfig()
- Override getEffectiveModel() to default the claim name to
OAuth2Constants.ORGANIZATION when not set, preserving backward
compatibility for existing mapper configurations
- Set TOKEN_CLAIM_NAME default in the static create() factory method
- Refactor OIDCAttributeMapperHelper.getOrInitializeOrganizationClaimAsMap()
to accept a ProtocolMapperModel instead of a raw String, delegating
to mapClaim() for correct claim placement (including nested path support)
Closes#47851
Signed-off-by: Sven-Torben Janus <sven-torben.janus@conciso.de>
* Fix nested claim path read and add custom claim name tests
The read side of getOrInitializeOrganizationClaimAsMap was doing a flat
Map.get() on the dotted claim name, while the write side (mapClaim) already
creates a nested structure by splitting on dots. This caused the group mapper
to find nothing when the claim name contained a dot, overwriting the
membership data written by OrganizationMembershipMapper.
Fix by splitting the claim path via splitClaimPath() and traversing the
nested map with a new private getNestedClaimValue() helper in
OIDCAttributeMapperHelper. The helper belongs there rather than in JsonUtils
because it operates on Map<String,Object>, not JsonNode.
Also add integration tests covering:
- Custom flat claim name ("my_orgs") for both OrganizationMembershipMapper
and OrganizationGroupMembershipMapper, verifying the claim appears at the
configured name and not at "organization"
- Dotted claim name ("custom.org") for OrganizationGroupMembershipMapper,
verifying the token contains nested otherClaims["custom"]["org"] and that
group composition is preserved
Signed-off-by: Sven-Torben Janus <sven-torben.janus@conciso.de>
---------
Signed-off-by: Sven-Torben Janus <sven-torben.janus@conciso.de>