T09 · Insecure Skill Coding Practices
- Location
scripts/id_validator.py:19- Finding
Malformed 15-Digit Identity Numbers Accepted Due to Incomplete Character Validation
- Content
View full analysis
Vulnerability Details
File Location:
scripts/id_validator.py, lines 19–27
Vulnerability Type: Incomplete input validation
Risk Level: Mediumpython def validate_id15(id15): if len(id15) != 15: return False try: from datetime import datetime y, m, d = int("19" + id15[6:8]), int(id15[8:10]), int(id15[10:12]) datetime(y, m, d) return True except: return FalseTechnical Analysis
The validator only checks that the input contains exactly 15 characters and that characters at positions 7–12 represent a valid date. It does not require the entire identifier to consist of digits. Consequently, the region and sequence fields may contain arbitrary nonnumeric characters.
For example,
ABCDEF900307AA1contains 15 characters, a valid encoded date (1990-03-07), and a numeric final gender digit. It therefore passesvalidate_id15()despite not being a valid 15-digit Chinese identity number.The implementation also returns the first six characters as a region without validating their numeric format or checking them against administrative region codes. This conflicts with the documented validation rules that identity numbers must contain digits and that region codes are valid.
Attack Path
- An application uses this utility to validate identity numbers during registration, age verification, or another business process.
- An attacker constructs a 15-character value with:
- Arbitrary characters in the six-character region field.
- A valid date in positions 7–12.
- Arbitrary characters in the first two sequence positions.
- A numeric character in the final position.
- The attacker submits a value such as
ABCDEF900307AA1. - The length check succeeds.
- The date fields decode to the valid date
1990-03-07. validate_id15()returnsTrue, andparse_id()produces trusted-looking region, birthday, and ge ...[truncated 684 chars]
- Remediation
View remediation
Remediation Suggestions
Require all 15 characters to be ASCII decimal digits before parsing individual fields:
python def validate_id15(id15): if len(id15) != 15 or not id15.isascii() or not id15.isdigit(): return False try: from datetime import datetime year = int("19" + id15[6:8]) month = int(id15[8:10]) day = int(id15[10:12]) datetime(year, month, day) except (TypeError, ValueError): return False return validate_region_code(id15[:6])Additional hardening should include:
- Validate the first six characters against a maintained, authoritative administrative-region dataset when region validity is claimed.
- Use explicit exception types such as
TypeErrorandValueErrorinstead of a bareexcept. - Apply equivalent explicit character validation to the 18-character format, allowing digits in the first 17 positions and only a digit or
Xin the checksum position. - Add negative tests for alphabetic region fields, alphabetic sequence fields, Unicode numeric characters, invalid dates, and unknown region codes.
- Clearly document whether validation covers only syntax and checksum rules or also verifies current administrative-region assignments.
