[Medium] Intel identifier sanitizer corrupts Unicode names and IPv6 addresses before lookup
Severity: Medium (correctness defect in a security control) Confidence: Confirmed by executed route-handler observations against the actual sanitizer. Audited commit: bd4057567de8ee18d49a8b2744c9746bcd67f3e0 (master, 2026-09-13 audit).
The shared identifier sanitizer used across every entity-resolution type strips all characters outside ASCII letters/digits/space/hyphen/dot/underscore before any lookup. This silently corrupts accented/non-Latin names and IPv6 addresses, producing false no-match results, cross-identity collisions, and lookups against the wrong address — even though the sanitizer correctly does prevent the SPARQL string injection it was written to stop (this report does not dispute that).
Evidence and mechanism
- intel/server.js:171-173:
sanitizeId()removes every character outside[A-Za-z0-9 ._-]. - Lines 732-742: this sanitizer is applied to identifiers for every entity type (person, company, IP, aircraft, vessel, country).
- Lines 435-438, 466: the corrupted name drives both the Wikidata lookup and sanctions-list matching.
- Lines 480, 538, 559, 578: the corrupted string is sent to IP-intelligence providers even for IP-type entities.
- src/app/api/entity/expand/route.ts:31-54: the public proxy forwards the original, uncorrupted identifier through to this sanitizer, so ordinary API requests reach the bug.
Reproduction and observed result
Executed the actual route handler:
type=person&id=José Álvarez→ resolved entity id becomesJos lvarez; the stripped name is what's queried upstream.type=ip&id=2001:4860:4860::8888→ resolved entity id becomes2001486048608888; the IP-intelligence provider is called with/json/2001486048608888— not a valid IPv6 address.
{"unicodeEntity":{"type":"person","id":"Jos lvarez"},"ipv6Entity":{"type":"ip","id":"2001486048608888"},"sentCorruptedIpv6":true}Impact
Legitimate accented, non-Latin, or IPv6 identifiers are silently mangled before any lookup happens, causing false negatives (a real sanctioned entity or malicious IP goes unmatched because its identifier no longer resembles the real one), and distinct names can collide once punctuation/diacritics are stripped.
Smallest correction and acceptance criteria
- Validate and normalize by entity type instead of blanket ASCII-stripping: preserve Unicode names for person/company lookups and use correct SPARQL literal escaping instead of character removal; validate IPv4/IPv6 syntax properly for IP-type entities (or explicitly reject unsupported formats rather than mangling them).
- Apply the corrected representation consistently to cache keys and graph node IDs.
- Acceptance: the exact accented-name and IPv6 fixtures above must reach lookup/sanctions-matching unchanged (aside from documented normalization); quotes, backslashes, and control characters must still be unable to escape the SPARQL literal after the fix.
Prior-issue check: #242 (closed) explicitly considered and rejected SPARQL injection in this same sanitizer — this report agrees injection is blocked and instead reports the separate, reproduced semantic-corruption defect. #25 concerns permissive IPv4 regexes elsewhere. No existing issue covers this.
Source: simplifaisoul/osiris