|
| 1 | +Confusable / Homoglyph Detection |
| 2 | +================================ |
| 3 | + |
| 4 | +``secrets_scan`` finds secret-shaped tokens and ``guardrail`` screens text for |
| 5 | +prompt injection, but nothing catches *visual* spoofing: a Cyrillic ``"а"`` |
| 6 | +(U+0430) is pixel-for-pixel a Latin ``"a"`` (U+0061), so ``"pаypal"`` (with a |
| 7 | +Cyrillic ``а``) reads as ``"paypal"`` to a human yet compares unequal — the basis |
| 8 | +of IDN-homograph phishing and lookalike UI labels. |
| 9 | + |
| 10 | +Following the idea of Unicode TR39, this folds confusable characters to a |
| 11 | +prototype *skeleton* (two strings are confusable when their skeletons match) and |
| 12 | +flags strings that mix scripts. Pure standard library (``unicodedata``); imports |
| 13 | +no ``PySide6``. Every function is pure, so it is fully deterministic in CI. |
| 14 | + |
| 15 | +Headless API |
| 16 | +------------ |
| 17 | + |
| 18 | +.. code-block:: python |
| 19 | +
|
| 20 | + from je_auto_control import ( |
| 21 | + confusable_skeleton, is_confusable, detect_homoglyphs, |
| 22 | + is_mixed_script, scripts_of, |
| 23 | + ) |
| 24 | +
|
| 25 | + confusable_skeleton("pаypal") # 'paypal' (Cyrillic а -> a) |
| 26 | + is_confusable("pаypal", "paypal") # True |
| 27 | + detect_homoglyphs("pаypal") # [{'index': 1, 'char': 'а', 'prototype': 'a'}] |
| 28 | + is_mixed_script("pаypal") # True (Latin + Cyrillic) |
| 29 | + scripts_of("pаypal") # {'LATIN', 'CYRILLIC'} |
| 30 | +
|
| 31 | +``confusable_skeleton`` NFKC-normalises (folding fullwidth, ligatures and math |
| 32 | +alphanumerics) then maps each remaining cross-script lookalike to its Latin |
| 33 | +prototype. ``is_confusable`` is true only for *distinct* strings with equal |
| 34 | +skeletons. ``detect_homoglyphs`` returns the offending characters with their |
| 35 | +position and prototype. ``scripts_of`` / ``is_mixed_script`` classify characters |
| 36 | +by Unicode block (ignoring digits, punctuation and spaces) so a single mixed- |
| 37 | +script token can be flagged on its own. |
| 38 | + |
| 39 | +Executor commands |
| 40 | +----------------- |
| 41 | + |
| 42 | +``AC_confusable_scan`` returns ``{skeleton, homoglyphs, mixed_script, scripts}`` |
| 43 | +for one string; ``AC_confusable_compare`` returns ``{confusable}`` for a pair. |
| 44 | +Both are exposed as MCP tools (``ac_confusable_scan`` / ``ac_confusable_compare``) |
| 45 | +and as Script Builder commands under **Data**. |
0 commit comments