Add disguised-ad-flag rule for native advertorials#116
Merged
Conversation
EasyList catches infrastructure-level ads via network selectors; native
advertorials rendered by the publisher's own CMS share DOM shape with
editorial articles and slip through. This rule detects them by the
visible disclosure label ("Sponsored", "Promoted", "Advertorial",
"Paid Post", "Partner Content", bracket forms like "[Ad]", and suffix
forms like "Paid for and presented by X") combined with an
article-shape check (heading + image-or-link + prose body) and replaces
matching cards with a click-to-reveal placeholder.
False-positive guards: whole-string regex on a leaf-ish label element
keeps editorial prose mentioning sponsorship from matching; an
interactive-ancestor walk excludes filter chips and nav links;
ads-hide-marked ancestors are skipped to avoid double-flagging.
Includes catalog wiring (Context pollution group, default on), docs
under rules.md, a new AdvertorialCard demo fixture with three label
variants plus an editorial negative fixture on the home page, and 25
unit tests covering positive matches and FP cases.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
2 issues found.
About Unblocked
Unblocked has been set up to automatically review your team's pull requests to identify genuine bugs and issues.
📖 Documentation — Learn more in our docs.
💬 Ask questions — Mention @unblocked to request a review or summary, or ask follow-up questions.
👍 Give feedback — React to comments with 👍 or 👎 to help us improve.
⚙️ Customize — Adjust settings in your preferences.
Pre-commit hooks reflow the rules.md paragraph break differently than my local editor; biome's `check` (vs `lint`) flags two test-file expect() lines as too long. Also updates the rule count in rules.md from 32 to 33. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- isArticleShaped's prose-length tally used to walk every <p>/<span>/<div>/<li> descendant and count the same characters at each ancestor level. A nested <div><p><span>X</span></p></div> would count X three times and let cards with ~30 chars of actual prose slip past the 80-char minimum. Now skip candidates that contain another selector-matched descendant (leaf-ish only). Adds a regression test that fails on the old code. - Register disguised-ad-flag in skills/agent-browser-shield-config/SKILL.md's Rule IDs list per CONTRIBUTING.md and AGENTS.md. - Document the disguised-ad-flag placeholder copy in skills/agent-browser-shield/SKILL.md so agents reading a revealed advertorial treat it as advertising rather than editorial. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
disguised-ad-flagrule (Context pollution group, default on) that hides article-shaped blocks carrying a visible "Sponsored" / "Promoted" / "Advertorial" / "Paid Post" / "Partner Content" disclosure label. Fills the gap left byads-hide: EasyList catches infrastructure-level ads via network selectors, but native advertorials rendered by the publisher's own CMS share DOM shape with editorial articles and slip through.data-abs-hidden="ads-hide"ancestors are skipped to avoid double-flagging; bracket form[Ad]is case-sensitive on theAso Latin "[ad hoc]" doesn't trigger.irrelevant-sections-redact). Subtree-watched so lazy-injected advertorials (Outbrain/Taboola native, infinite scroll feeds) get caught after document_idle..com Disclosuresrationale, and the Kohlschütter/Readability prior art.AdvertorialCarddemo fixture with three label variants (Sponsored,[Ad],Paid for and presented by Acme) interleaved with real product cards, plus an editorial negative fixture whose body contains "sponsored by Adidas" as prose. Lets a reviewer toggle the rule in the popup and watch the advertorials collapse while the editorial card stays put.Test plan
bun --filter extension run test— 960 tests pass (25 new indisguised-ad-flag.test.ts)bun --filter extension run lintcleanbun --filter extension run typecheckcleanbun --filter demo-site run checkcleanbun --filter demo-site run buildcleanbun --filter docs run buildclean (8 pages built)disguised-ad-flagon in the popup, and visually confirm: the three advertorial cards in "From Our Partners" collapse to placeholders; the editorial article mentioning "sponsored by Adidas" stays visible; existing product cards are untouched.🤖 Generated with Claude Code