Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Audit: rule-bypass findings (red-team pass) #203

Description

@twschiller

Category

Tracking issue / red-team audit

Summary

Audit of the current rule set against bypass attempts that a malicious page could use to evade detection. Each finding lists severity (impact on the threat model) and rough complexity of fix. Filed as one tracking issue so the per-fix PRs can link back; individual items are small enough that breaking each out as its own issue would be churn.

Some of these are already-known design tradeoffs (closed shadow roots, display:none, landmark allowlist) and are listed for completeness rather than as actionable items — the rest are straightforward to close.

Phrasing of adversarial payloads is abstracted; PRs that add fixtures keep concrete strings out of public docs per repo convention.


Critical

  1. Closed shadow root content is invisible. Carries any payload past every text-walking and selector rule. Already a known tradeoff (shadow-roots.ts:9–13); listing for completeness. Fix complexity: L (opt-in attachShadow patch).
  2. unicode-invisibles-strip misses U+00AD, U+034F, U+FE00–FE0F, U+3164, U+2800. A single soft-hyphen inside a trigger verb defeats every regex-based rule (prompt-injection-redact, secrets-redact, pii-redact, confirmshame-sanitize, disguised-ad-flag). Fix complexity: XS — add codepoints to the regex.
  3. PII split across sibling text nodes (React <span>-per-group renders of a card number) — the contiguous-digits regex never sees the full number. Fix complexity: M — windowed concatenation across sibling text nodes, breaks the single-node assumption in inline-text-redact.

High

  1. Declarative shadow DOM (<template shadowrootmode="…">) never traverses the patched attachShadow. Closed variant inherits Bump zod from 3.25.76 to 4.4.3 in /extension #1; open variant could be reached if the initial discoverShadowRootsIn ran earlier. Fix complexity: S (open) / L (closed).
  2. hidden-text-strip parses only rgb()/rgba(). Text in oklch(), lab(), color(), color-mix() reaches computed style unnormalized → parseColor returns null → no color-match. Source already notes this at :386–389. Fix complexity: S — normalize via a 1×1 canvas paint + getImageData.
  3. CSS hide paths not checked: -webkit-text-fill-color: transparent, filter: opacity(0), mask-image: linear-gradient(transparent…), transform: scale(0), content-visibility: hidden, max-height:0; overflow:hidden on non-1×1 elements. Fix complexity: S — one check each in detectHiddenByCss.
  4. encoded-payload-redact length floors + split-across-whitespace. Splitting an encoded payload across whitespace/punctuation drops each candidate below MIN_BASE64_LENGTH=120 / MIN_HEX_LENGTH=160 / MIN_PERCENT_TRIPLETS=20. Fix complexity: M — second pass that concatenates adjacent encoded runs separated by \s/punctuation before re-deciding.
  5. Injection pattern set is closed. Tool-use shapes (<tool_call>, function_call:), Human:/Assistant: turn markers, non-DAN personas, non-listed modes, and "task hand-off" framings all sit outside the regex set. Fix complexity: M — pattern additions are XS each but coverage is editorial and unbounded; long-term path is the ML classifier referenced in the v1 source comment.
  6. <object> / <embed> with cross-origin data/src not queried by cross-origin-frame-redact. Fix complexity: S — extend selector.
  7. Landmark (<nav> / <aside> / <header>) and aria-hidden="true" subtree allowlists in hidden-text-strip preserve color-matched and visibility:hidden payloads. Fix complexity: S — narrow the allowlist to the SR-only structural / class-allowlist branches only.
  8. <iframe srcdoc="…"> skipped by cross-origin-frame-redact. Same agent-side threat model as a cross-origin frame even though it inherits origin. Fix complexity: S.

Medium

  1. ROT13 / Atbash / reverse / NATO phonetic / morse / leetspeak payloads not detected by encoded-payload-redact. Fix complexity: M.
  2. Programmatic input.checked = true after checkout-checkbox-sanitize runs — no MutationRecord fires, sanitize never re-runs. Fix complexity: M — patch the checked setter on HTMLInputElement.prototype for checkout origins.
  3. display: none + role="status" / aria-live smuggling — text is still in textContent and a11y announces live regions. Current display:none exclusion exists for tab panels; could narrow. Fix complexity: S.
  4. schema-trust-sanitize only covers Organization-family types. Person / Author URL mismatch passes. Fix complexity: XS — add types.
  5. link-spoof-annotate single-script homograph and IDN visible text. MIXED_SCRIPT_RE needs adjacent letters from different scripts; DOMAIN_RE is ASCII-only. Fix complexity: S — Unicode TR39 confusables.txt skeleton comparison + IDN/punycode handling.
  6. Bot detector fingerprinting the extension itself ([abs-revealed], .abs-placeholder, floating button) and cloaking content. Out of scope for a content-script-only defense; tracked at Rule proposal: bot-cloaking-annotate — detect/annotate AI-targeted cloaking #122. Fix complexity: XL.
  7. disguised-ad-flag label list closed. "Featured listing", "From our advertisers", "Marketing partner", "In partnership with", lowercase [ad] all pass. Fix complexity: XS.
  8. disguised-ad-flag article-shape requires an <h*> element. A card with a <div class="headline"> escapes. Fix complexity: S.

Low

  1. Countdown that resets to its start value, or <canvas>-rendered timer. parseTotalSeconds reads empty / currentSeconds >= initialSeconds. Fix complexity: M.
  2. Scarcity / countdown synonym evasion. Fix complexity: XS.
  3. confirmshame-sanitize non-English copy or icon-only buttons. Fix complexity: L (multilingual).

Suggested order

If we want to ship the biggest threat reduction per engineering hour first:

  1. 2 (XS) — eliminates a one-character bypass for every regex rule.
  2. 5 (S) — closes the modern-CSS invisible-text class.
  3. 6 (S) — six CSS hide-path checks in one rule.
  4. 10 (S) — narrows two known-safe allowlists.
  5. 9 + 11 (S) — one rule, three new selectors.
  6. 15, 18, 19 — bundle XS/S additions.
  7. 3 (M) — only Critical that needs real engineering.

Demo-site complement

A separate PR will add fixtures exercising each gap so the before/after screenshot diff shows the rule's blind spot. Highest-value additions: closed-shadow + declarative-shadow embeds, srcdoc iframe, oklch color-match card, soft-hyphen-in-verb review, display:none + role="status" block, post-hydration input.checked = true.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions