Skip to content

fix(spiffeid): normalize trust domain case with ASCII-only lowercasing - #498

Merged
maxlambrecht merged 1 commit into
spiffe:mainfrom
NopeCharon:fix/spiffeid-ascii-case-normalization
Nov 5, 2026
Merged

maxlambrecht merged 1 commit into
spiffe:mainfrom
NopeCharon:fix/spiffeid-ascii-case-normalization

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

What

Trust domain case normalization in SpiffeId.parse and TrustDomain.parse now only maps ASCII A-Z to a-z. A new package-private helper, TrustDomain.toLowerAscii, replaces String.toLowerCase() and Character.toLowerCase(char). Mixed-case ASCII trust domains are normalized as before. Any other character is rejected with the existing Trust domain characters are limited to ... error.

Fixes #496

Why

  • String.toLowerCase() uses the JVM default locale. In a Turkish or Azerbaijani locale I becomes the dotless ı. Then TrustDomain.parse("EXAMPLE.IO") threw, and SpiffeId.parse("spiffe://INFO.ORG/service") returned trust domain ınfo.org. That ID did not equal spiffe://info.org/service, matched no bundle, and its toString() was not a valid SPIFFE ID.
  • Character.toLowerCase and String.toLowerCase map some non-ASCII characters to ASCII letters (Kelvin sign U+212A → k, U+0130 → i). Those characters passed the trust domain check, so Kexample.org was accepted as kexample.org. The SPIFFE ID spec only allows ASCII letters, digits, ., - and _.

Compatibility: no public API change. The only inputs that behave differently are trust domains containing non-ASCII characters with an ASCII lowercase form, which are now rejected, and upper-case I under tr/az locales, which now parses correctly.

How tested

  • TrustDomainTest.testParseMixedCase_turkishDefaultLocale_normalizesToAsciiLowercase and SpiffeIdTest.parseMixedCaseTrustDomain_turkishDefaultLocale_normalizesToAsciiLowercase parse upper-case trust domains with the default locale set to tr-TR, then restore the locale.
  • TrustDomainTest.testParseNonAsciiCharWithAsciiLowercase_throwsInvalidTrustDomain and SpiffeIdTest.parseTrustDomainWithNonAsciiCharWithAsciiLowercase_throwsInvalidSpiffeIdException check that U+212A and U+0130 are rejected, both in bare trust domain names and in SPIFFE IDs.
  • Without the change, 7 of these cases fail. Two examples: expected: <info.org> but was: <ınfo.org>, and no exception for Kexample.org.
  • ./gradlew :java-spiffe-core:check :java-spiffe-core:japicmp :java-spiffe-core:javadoc :java-spiffe-provider:test :java-spiffe-helper:test on JDK 17.

@maxlambrecht maxlambrecht left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

SpiffeId.parse and TrustDomain.parse lowercased the trust domain with
String.toLowerCase() and Character.toLowerCase(char).

String.toLowerCase() uses the JVM default locale. In a Turkish or
Azerbaijani locale 'I' becomes the dotless 'ı' (U+0131), so
TrustDomain.parse("EXAMPLE.IO") threw InvalidSpiffeIdException and
SpiffeId.parse("spiffe://INFO.ORG/service") produced the trust domain
"ınfo.org". That ID did not equal spiffe://info.org/service, matched no
bundle, and its toString() was not a valid SPIFFE ID.

Both methods also map some non-ASCII characters to ASCII letters, e.g.
the Kelvin sign U+212A to 'k' and U+0130 to 'i'. Those characters passed
the trust domain check, so "Kexample.org" was accepted as
"kexample.org", although the SPIFFE ID spec only allows ASCII letters,
digits, '.', '-' and '_' in a trust domain.

Add TrustDomain.toLowerAscii, which only maps 'A'-'Z' to 'a'-'z' and
leaves every other character unchanged, and use it in both parsers.
Mixed-case ASCII trust domains are still normalized as before. Any other
character now fails with the existing "Trust domain characters are
limited to ..." error.

Fixes spiffe#496

Signed-off-by: NopeCharon <115794254+NopeCharon@users.noreply.github.com>
@maxlambrecht
maxlambrecht force-pushed the fix/spiffeid-ascii-case-normalization branch from d5f684c to ae0139e Compare November 5, 2026 20:58
@maxlambrecht
maxlambrecht merged commit d3d91c5 into spiffe:main Nov 5, 2026
8 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.

SPIFFE ID trust domain normalization depends on the default locale and accepts non-ASCII characters

2 participants