You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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).
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.
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
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).
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.
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.
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.
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.
<object> / <embed> with cross-origin data/src not queried by cross-origin-frame-redact. Fix complexity: S — extend selector.
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.
<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
ROT13 / Atbash / reverse / NATO phonetic / morse / leetspeak payloads not detected by encoded-payload-redact. Fix complexity: M.
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.
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.
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.
disguised-ad-flag label list closed. "Featured listing", "From our advertisers", "Marketing partner", "In partnership with", lowercase [ad] all pass. Fix complexity: XS.
disguised-ad-flag article-shape requires an <h*> element. A card with a <div class="headline"> escapes. Fix complexity: S.
Low
Countdown that resets to its start value, or <canvas>-rendered timer. parseTotalSeconds reads empty / currentSeconds >= initialSeconds. Fix complexity: M.
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:
2 (XS) — eliminates a one-character bypass for every regex rule.
5 (S) — closes the modern-CSS invisible-text class.
6 (S) — six CSS hide-path checks in one rule.
10 (S) — narrows two known-safe allowlists.
9 + 11 (S) — one rule, three new selectors.
15, 18, 19 — bundle XS/S additions.
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.
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
shadow-roots.ts:9–13); listing for completeness. Fix complexity: L (opt-inattachShadowpatch).unicode-invisibles-stripmisses 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.<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 ininline-text-redact.High
<template shadowrootmode="…">) never traverses the patchedattachShadow. Closed variant inherits Bump zod from 3.25.76 to 4.4.3 in /extension #1; open variant could be reached if the initialdiscoverShadowRootsInran earlier. Fix complexity: S (open) / L (closed).hidden-text-stripparses onlyrgb()/rgba(). Text inoklch(),lab(),color(),color-mix()reaches computed style unnormalized →parseColorreturns null → no color-match. Source already notes this at:386–389. Fix complexity: S — normalize via a 1×1 canvas paint +getImageData.-webkit-text-fill-color: transparent,filter: opacity(0),mask-image: linear-gradient(transparent…),transform: scale(0),content-visibility: hidden,max-height:0; overflow:hiddenon non-1×1 elements. Fix complexity: S — one check each indetectHiddenByCss.encoded-payload-redactlength floors + split-across-whitespace. Splitting an encoded payload across whitespace/punctuation drops each candidate belowMIN_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.<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.<object>/<embed>with cross-origindata/srcnot queried bycross-origin-frame-redact. Fix complexity: S — extend selector.<nav>/<aside>/<header>) andaria-hidden="true"subtree allowlists inhidden-text-strippreserve color-matched andvisibility:hiddenpayloads. Fix complexity: S — narrow the allowlist to the SR-only structural / class-allowlist branches only.<iframe srcdoc="…">skipped bycross-origin-frame-redact. Same agent-side threat model as a cross-origin frame even though it inherits origin. Fix complexity: S.Medium
encoded-payload-redact. Fix complexity: M.input.checked = trueaftercheckout-checkbox-sanitizeruns — no MutationRecord fires, sanitize never re-runs. Fix complexity: M — patch thecheckedsetter onHTMLInputElement.prototypefor checkout origins.display: none+role="status"/aria-livesmuggling — text is still intextContentand a11y announces live regions. Currentdisplay:noneexclusion exists for tab panels; could narrow. Fix complexity: S.schema-trust-sanitizeonly covers Organization-family types.Person/AuthorURL mismatch passes. Fix complexity: XS — add types.link-spoof-annotatesingle-script homograph and IDN visible text.MIXED_SCRIPT_REneeds adjacent letters from different scripts;DOMAIN_REis ASCII-only. Fix complexity: S — Unicode TR39confusables.txtskeleton comparison + IDN/punycode handling.[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.disguised-ad-flaglabel list closed. "Featured listing", "From our advertisers", "Marketing partner", "In partnership with", lowercase[ad]all pass. Fix complexity: XS.disguised-ad-flagarticle-shape requires an<h*>element. A card with a<div class="headline">escapes. Fix complexity: S.Low
<canvas>-rendered timer.parseTotalSecondsreads empty /currentSeconds >= initialSeconds. Fix complexity: M.confirmshame-sanitizenon-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:
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,
srcdociframe,oklchcolor-match card, soft-hyphen-in-verb review,display:none+role="status"block, post-hydrationinput.checked = true.