fix: judge the symbol a user sees, not the bytes a contract returns (closes #260)
All checks were successful
check / check (push) Successful in 35s
All checks were successful
check / check (push) Successful in 35s
A token whose symbol is " ETH " missed KNOWN_SYMBOLS on all three surfaces
while HTML collapsed the padding and painted it as ETH next to the user's
real ETH. isSpoofedSymbol() now normalizes before the lookup: NFKC, then
every character that paints nothing removed wherever it sits, then trimmed,
then uppercased. All three surfaces inherit it unchanged.
The strip is "renders as nothing", spelled as \p{Cf} plus
\p{Default_Ignorable_Code_Point} plus U+007F. The classes are the spelling
and not the rule, which is why U+007F is named on its own: it is a control
rather than a default-ignorable character, so no class reaches it, yet it
measures 32.00px in the repo's pinned e2e Chromium at 16px sans-serif --
exactly a plain ETH -- so it paints nothing and would otherwise be a live
bypass. The remaining C0/C1 controls measure 48.00px, a visible box, and are
left alone; both directions are pinned by tests, and widening the strip to
\p{Cc} fails the visible-controls test.
Covered: ASCII and Unicode whitespace padding, zero-width and other
invisible characters, and compatibility variants such as fullwidth letters.
Knowingly left open, and asserted as open in the suite: confusables that are
distinct letters (Cyrillic capital Ie), bidi reordering, the visible
controls, and interior whitespace, which renders differently and so is not
the confusion.
No symbol in KNOWN_SYMBOLS or the bundled token list contains whitespace or
a non-ASCII character, so nothing legitimate is newly filtered; a test walks
the whole table and asserts it.
The balance list's token-type gate is now case-insensitive. It compared
exactly, so an explorer writing "erc-20" would silently drop a real holding
before any filter ran. Which types are admitted is unchanged.
This commit is contained in:
14
TODO.md
14
TODO.md
@@ -45,6 +45,20 @@ undefined identifiers, which is how
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-08-12: The known-symbol spoof rule now judges the symbol a user actually
|
||||
sees. `isSpoofedSymbol()` normalizes before the lookup — NFKC, then every
|
||||
character that paints nothing removed (the format and default-ignorable
|
||||
characters, plus U+007F), then trimmed — so `" ETH "`, a no-break space, a
|
||||
zero-width space, a Hangul filler, a variation selector, a DELETE and a
|
||||
fullwidth `ETH` are all caught on the balance list, the history and the
|
||||
send selector at once. Confusables that are distinct letters (Cyrillic `Е`),
|
||||
bidi reordering and the visible C0/C1 controls — which measure 48.00px, a box,
|
||||
in the pinned e2e Chromium where an invisible prefix measures 32.00px — stay
|
||||
knowingly open and are asserted as open in the suite. No bundled symbol
|
||||
contains whitespace or a non-ASCII character, so nothing legitimate is newly
|
||||
filtered; the balance list's token-type gate also became case-insensitive,
|
||||
which no longer drops a real holding if an explorer writes `erc-20`
|
||||
([#260](https://git.eeqj.de/sneak/AutistMask/issues/260)).
|
||||
- 2026-08-12: A containerized Firefox end-to-end harness
|
||||
(`make test-e2e-firefox`) drives the real popup in a real Firefox with the MV2
|
||||
build installed as a temporary add-on. Zero npm dependencies — a WebDriver
|
||||
|
||||
Reference in New Issue
Block a user