FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(finance): isin() actually validates the check digit by Jordan-Bourillot · Pull Request #468 · python-validators/validators · GitHub

Repository navigation

fix(finance): isin() actually validates the check digit - #468

Closed
Jordan-Bourillot wants to merge 1 commit into
python-validators:masterfrom
Jordan-Bourillot:fix/isin-checksum
Closed

Jordan-Bourillot wants to merge 1 commit into
python-validators:masterfrom
Jordan-Bourillot:fix/isin-checksum

Conversation

Copy link
Copy Markdown
Contributor

Summary

isin() accepted any 12-character string — the check digit was never actually verified.

Root cause

_isin_checksum initialised check = 0 and then never updated it inside the loop (the check += (val // 10) + (val % 10) line that exists in _cusip_checksum was missing). It also reused the per-character CUSIP scheme, which is not the ISIN algorithm. So check stayed 0 and (check % 10) == 0 was always true.

>>> import validators
>>> validators.isin('US0378331004')   # wrong check digit
True                                   # should be invalid
>>> validators.isin('XX0000000000')
True                                   # should be invalid

Fix

Reimplement with the documented ISIN scheme: expand letters to digits (A=10 … Z=35) and run the Luhn algorithm over the result. Verified against real ISINs (US0378331005, AU0000XVGZA3, GB0002634946, …).

Tests

  • One existing "valid" fixture, JP000K0VF054, was itself invalid — its correct check digit is 5, and only the broken checksum let it pass. Corrected to JP000K0VF055.
  • Added a wrong-check-digit case (US0378331004) to the invalid fixtures, plus a valid example in the docstring.

The full test suite passes and ruff is clean.

_isin_checksum never accumulated into `check` (the accumulation line
present in _cusip_checksum was missing), and the per-character loop it
copied is not the ISIN scheme anyway. `check` stayed 0, so isin()
returned True for every 12-character string -- e.g. isin('US0378331004')
(wrong check digit) and isin('XX0000000000').

Reimplement with the documented ISIN algorithm: expand letters to digits
(A=10..Z=35) and run Luhn over the result. Verified against real ISINs
(US0378331005, AU0000XVGZA3, GB0002634946).

The existing 'valid' fixture 'JP000K0VF054' was itself invalid (its
correct check digit is 5) -- corrected to 'JP000K0VF055'. Added a
wrong-check-digit case to the invalid fixtures and a valid example to
the docstring.

Copy link
Copy Markdown
Collaborator

Thank you for the contribution! The ISIN check-digit fix landed through #464, so I'm closing this as a duplicate.

nandgator closed this Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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


Back | FazBrowse Home | New Git URL