Skip to content

Chromium extension: reveal hidden Unicode on the page - #113

Merged
cursor[bot] merged 5 commits into
mainfrom
cursor/browser-extension-cdf8
Sep 2, 2026
Merged

cursor[bot] merged 5 commits into
mainfrom
cursor/browser-extension-cdf8

Conversation

@byte271

@byte271 byte271 commented Sep 2, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #112 so this diff is the Chromium extension only.

What this does

Adds editors/browser: an unpacked Manifest V3 extension that uses the same fuckmark-hidden-scan-v1 scan.js copy as VS Code (byte-identical; the freeze tests now include this copy).

  • Popup: paste or click Trojan Source / commenting-out / tag examples, copy security-clean text, fix Trojan Source (bidi only).
  • Scan this page / Reveal / Hide: counts hidden characters in visible text nodes and paints U+XXXX badges (CSS Custom Highlight when the browser supports it).
  • Paste-safe (off by default): strips hidden Unicode on paste into inputs, keeps real emoji ZWJ sequences (both neighbors emoji), and stopImmediatePropagation so page editors cannot insert the raw clipboard afterward.
  • Context menu and per-tab toolbar badge.
  • No clipboardRead, no remote code, nothing uploaded. Content script is http:// and https:// only.

Load unpacked from chrome://extensions → this folder.

Depends on

#112 (language-aware scan.js / UMD export). Merge that first, then this.

Review follow-up

Addressed the Codex notes: per-tab badges, ZWJ keep only for true emoji joins (grin+ZWJ+admin is stripped), and paste-safe blocks later page paste handlers.

Package version stays 0.4.1.

Open in Web Open in Cursor 

Ship editors/browser as an unpacked MV3 extension using the same
fuckmark-hidden-scan-v1 scan.js copy as VS Code. Popup scans pasted
text, optional paste-safe strips hidden characters on paste while
keeping emoji ZWJ sequences, and Reveal paints U+XXXX badges on the
current http(s) page. Nothing is uploaded.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: e50ed199-bf43-4b7d-bb2c-e602b0be1b51

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The popup can be opened as a plain page for the paste scanner. Do not
paint Scan this page as the primary action unless chrome.tabs is present.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@byte271
byte271 marked this pull request as ready for review September 2, 2026 01:47

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bd3353aa4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +215 to +216
event.preventDefault();
insertCleaned(event.target, result.cleaned);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Block page handlers from consuming the original paste

When paste-safe is enabled on a contenteditable or custom editor with its own paste listener, preventDefault() only cancels the browser's default insertion; the page listener still receives the unchanged event.clipboardData and can insert the hidden Unicode after this handler inserts the cleaned text. Thus paste-safe can be bypassed or produce duplicate content on common rich-text editors unless the raw event is prevented from reaching page handlers.

Useful? React with 👍 / 👎.

Comment thread editors/browser/page.js Outdated
Comment on lines +29 to +31
const security = new Set(scan.DEFAULT_SECURITY_CATEGORIES);
if (!finding || !security.has(finding.category)) return false;
return finding.severity !== "info";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip ZWJs that do not form an emoji sequence

The scanner labels a ZWJ as info when either neighbor is emoji-like, and this blanket severity check therefore preserves inputs such as 😀‍admin or admin‍😀. Those are not emoji ZWJ sequences, yet both paste-safe and “Copy security-clean text” leave the invisible character intact; preservation should require a valid emoji sequence rather than merely an info severity.

Useful? React with 👍 / 👎.

Comment thread editors/browser/background.js Outdated
Comment on lines +11 to +12
chrome.action.setBadgeBackgroundColor({ color: color });
chrome.action.setBadgeText({ text: text });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope the toolbar badge to the scanned tab

When multiple tabs are open, omitting tabId makes these badge settings global, so scanning tab A causes the same finding count to appear on unrelated tab B and remain there when the user switches tabs. Pass the originating tab ID through setBadge (including from the message sender) so the displayed count represents the current page.

Useful? React with 👍 / 👎.

cursoragent and others added 3 commits September 2, 2026 01:51
Trojan Source bidi in a comment or string stays on that role even when
the next glyph is emoji, so severity stays critical. Truncated Python
/api/scan results now keep counts, the truncated flag, and peak
severity across every hit, not only the first 256 listed findings.
Freeze record v3 binds the new vectors.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Co-authored-by: Byte271 <byte271@users.noreply.github.com>
Paste-safe now stopImmediatePropagation so page listeners cannot insert
the raw clipboard after a cleaned paste. ZWJ is kept only when both
neighbors are emoji (or a variation selector), so grin+ZWJ+admin is
stripped. Toolbar badges are scoped to the scanned tab.

Co-authored-by: Byte271 <byte271@users.noreply.github.com>
@cursor
cursor Bot changed the base branch from cursor/scan-page-trojan-source-cdf8 to main September 2, 2026 03:11
@cursor
cursor Bot merged commit d4ed5d1 into main Sep 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants