Skip to content

Add ASCII-only character validation for enhanced security#167

Merged
hajk1 merged 1 commit intoarturmkrtchyan:masterfrom
RedSlowpoke:ibans-only-latin-and-common-digits
Sep 28, 2025
Merged

Add ASCII-only character validation for enhanced security#167
hajk1 merged 1 commit intoarturmkrtchyan:masterfrom
RedSlowpoke:ibans-only-latin-and-common-digits

Conversation

@RedSlowpoke
Copy link
Contributor

@RedSlowpoke RedSlowpoke commented Sep 13, 2025

Rationale

IBANs and BICs should only contain ASCII digits (0-9) and Latin uppercase letters (A-Z). The current implementation uses Java's Character.isDigit() and Character.isUpperCase() methods, which accept a much wider range of Unicode characters than necessary.

This creates potential security vulnerabilities in real-world scenarios. For example:

  • Photo recognition systems may substitute Arabic-Indic digit (០) instead of ASCII digit (0)
  • Cyrillic letters (А, В, С) can be mistaken for Latin letters (A, B, C)
  • Other Unicode lookalike characters could bypass validation

Solution

Created a new CharacterUtil class with strict ASCII-only validation methods:

  • isAsciiDigit(char) - validates only ASCII digits 0-9
  • isAsciiUppercaseLetter(char) - validates only ASCII uppercase letters A-Z
  • isValidAlphanumeric(char) - validates IBAN-compliant alphanumeric characters

Replaced existing Character.* method calls in:

  • BbanStructure.java - digit and letter validation
  • IbanUtil.java - check digit validation
  • BicUtil.java - check digit and letter validation. Additionnaly change in validateCountryCode logic to not use magic values and make the check correspond with the thrown exception.

Benefits

  • Performance: Direct range checks are faster than Unicode-aware methods
  • Clarity: Explicit ASCII-only validation makes intent clear
  • Compatibility: All existing tests pass and no changes in them. New tests are added.

The solution is simple, transparent, and maintains performance

@RedSlowpoke
Copy link
Contributor Author

Hi @hajk1 — sorry to ping you out of the blue. You appear to be among the most recent active contributors (based on PRs). Could you advise on whether the PR aligns with the project’s direction and if there’s a path to merge or close it? Happy to adjust per your guidance. Thanks!

- Created CharacterUtil with strict ASCII validation methods
- Replaced Character.isDigit() with IbanCharacterUtil.isAsciiDigit()
- Replaced Character.isUpperCase() with IbanCharacterUtil.isAsciiUppercaseLetter()
- Replaced Character.isLetterOrDigit() with IbanCharacterUtil.isValidIbanAlphanuc)
- Improves performance with direct range checks vs Unicode lookups
- Added comprehensive tests for new validation methods
- All existing tests continue to pass
@RedSlowpoke RedSlowpoke force-pushed the ibans-only-latin-and-common-digits branch from 92fe553 to 5b14c70 Compare September 14, 2025 17:34
Comment on lines -110 to +116
if (countryCode.trim().length() < COUNTRY_CODE_LENGTH
|| !countryCode.equals(countryCode.toUpperCase())
|| !Character.isLetter(countryCode.charAt(0))
|| !Character.isLetter(countryCode.charAt(1))) {
throw new BicFormatException(
COUNTRY_CODE_ONLY_UPPER_CASE_LETTERS,
countryCode,
"Bic country code must contain upper case letters");
for (int i = 0; i < COUNTRY_CODE_LENGTH; i++) {
if (!CharacterUtil.isAsciiUppercaseLetter(countryCode.charAt(i))) {
throw new BicFormatException(
COUNTRY_CODE_ONLY_UPPER_CASE_LETTERS,
countryCode,
"Bic country code must contain upper case letters");
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use of magic indexes removed — validation now uses a loop for the expected lenght.
The length check removed, since it doesn't correspond with the exception in this check.
Country code lenght/validity effectively is ensured by the check against known country list check below.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@RedSlowpoke It seems good to me.

@hajk1 hajk1 merged commit 94e878f into arturmkrtchyan:master Sep 28, 2025
1 check passed
@RedSlowpoke RedSlowpoke deleted the ibans-only-latin-and-common-digits branch September 30, 2025 20:44
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.

2 participants