Browser extension that automatically flags unsolicited LinkedIn messages — recruiter spam, crypto scams, cold AI/SaaS pitches, MLM, phishing and more — directly in your conversation list. Privacy-first, 100% local, no servers, no tracking.
Available for Firefox and Chrome (Manifest V3).
- 14 built-in keyword lists covering common LinkedIn spam categories (recruiter outreach, crypto, MLM, marketing agency pitches, SaaS cold emails, phishing, etc.)
- Visual flagging only (red sender name + ⚠ badge + red ring on avatar). Auto-archive is planned for a future release.
- Hover tooltip shows which list and which keyword triggered the flag.
- Custom lists — add your own categories and keywords from the options page.
- Per-list action override — disable individual lists or override the global behavior.
- Activity log — last 50 flagged conversations with sender, preview, matched keyword and timestamp.
- Live updates — toggle protection or change keywords without reloading the LinkedIn tab.
- Cross-browser — same codebase, separate manifests for Chrome (
service_worker) and Firefox (scriptsevent page). - Shadow DOM aware — works with LinkedIn's new
interop-outletshadow DOM messaging panel. - No external dependencies — pure vanilla JavaScript, no bundler, no tracking, no telemetry.
- The content script runs on
https://www.linkedin.com/*(top frame and iframes, including LinkedIn's shadow DOM). - A
MutationObserverwatches the conversation list. New conversation cards are scanned for keyword matches in the visible preview text. - Each conversation is uniquely identified by its thread ID extracted from
/messaging/thread/<id>/links — multiple<a>tags pointing to the same thread are collapsed to a single card. - The first message preview is checked against all enabled keyword lists (case-insensitive by default; word-boundary matching for short keywords like "ia" to avoid false positives).
- On match, the sender's name is restyled in red, a small ⚠ badge with hover tooltip is appended, and the avatar gets a red outline.
- Results are cached in
sessionStorage(per thread ID, invalidated when keyword fingerprint changes) so flags survive React re-renders without re-running the matcher.
| ID | Name | Default state |
|---|---|---|
recruitment-spam |
Recruitment Spam | enabled |
crypto-scam |
Crypto & Financial Scams | enabled |
mlm-spam |
MLM / Network Marketing | enabled |
generic-spam |
Generic Spam | disabled |
ai-prospection |
AI & Prospection Pitches | enabled |
agency-pitch |
Marketing Agency Pitches | enabled |
seo-spam |
SEO & Backlinks | enabled |
coaching-pitch |
Coaching & Mentorship Pitches | enabled |
course-sales |
Course & Training Sales | enabled |
outsourcing-pitch |
Outsourcing & Offshore Dev | enabled |
saas-pitch |
SaaS Cold Outreach | enabled |
phishing |
Phishing & Account Threats | enabled |
romance-bot |
Romance / Bot Greetings | disabled |
investment-pitch |
Investment Opportunities | enabled |
Around 180 keywords in total. Disabled lists are kept in storage so users can opt in without losing their custom changes.
node build.jsThis produces:
dist/chrome/— Chrome MV3 bundle (manifest.jsonwithservice_worker)dist/firefox/— Firefox MV3 bundle (manifest.jsonwithscriptsevent page +browser_specific_settings)
- Open
chrome://extensions. - Enable Developer mode.
- Click Load unpacked and select the
dist/chrome/directory.
- Open
about:debugging#/runtime/this-firefox. - Click Load Temporary Add-on… and pick
dist/firefox/manifest.json. - The extension stays loaded until Firefox is restarted (Mozilla signing is required for permanent install).
- Popup (toolbar icon) — toggle protection on/off, see archived/flagged stats, enable/disable lists, jump to settings or activity log.
- Options page — three tabs: Filter Lists (manage keywords), Settings (global default action, case sensitivity, export/import, reset), Activity Log (last 50 events).
- On LinkedIn — open your messaging list (full page
/messaging/or the floating overlay on/feed/). Matched conversations are highlighted automatically.
LinkedGuard/
├── manifest.json # Chrome MV3
├── manifest.firefox.json # Firefox MV3 overrides (browser_specific_settings + scripts)
├── build.js # Generates dist/chrome/ and dist/firefox/
├── src/
│ ├── background/
│ │ └── service-worker.js # First-install seeding + LOG_ACTION handler + badge counter
│ ├── content/
│ │ ├── content.js # Entry point — loads config, starts observers, listens to storage changes
│ │ ├── observer.js # MutationObserver — debounced scan of the conversation list (incl. shadow roots)
│ │ ├── detector.js # DOM querying, thread-ID dedup, keyword matching
│ │ ├── flagger.js # Visual flagging (sender name + avatar outline + tooltip badge)
│ │ ├── archiver.js # (Planned) auto-archive via DOM interaction
│ │ ├── dispatcher.js # Routes a match to flag (always, while archive is "coming soon")
│ │ ├── thread-scanner.js # Scans the open conversation panel — full message text, not just preview
│ │ └── cache.js # sessionStorage cache keyed by thread ID + keyword fingerprint
│ ├── popup/ # Toolbar popup (HTML/CSS/JS)
│ ├── options/ # Full options page with 3 tabs
│ └── shared/
│ ├── constants.js # browserAPI shim, storage key, debounce util
│ ├── keyword-lists.js # All 14 built-in lists + DEFAULT_CONFIG
│ └── storage.js # storage.sync with storage.local fallback
└── assets/icons/ # 16/32/48/128 PNG icons
| Permission | Why |
|---|---|
storage |
Persist the user's config (enabled lists, custom keywords, activity log). Uses sync when available, falls back to local. |
host_permissions: https://www.linkedin.com/* |
Restrict the content script to LinkedIn only. No other domain is touched. |
No remote calls. No analytics. No fetch to anything outside linkedin.com.
- All keyword matching runs locally in your browser.
- No message content ever leaves your device.
- The activity log (last 50 entries) is stored in
chrome.storage.sync/storage.localonly. - LinkedGuard does not read messages outside
https://www.linkedin.com/*.
- Auto-archive — currently disabled (UI shows "Archive (soon)"). Will be re-enabled once the LinkedIn DOM mutation pattern is stable across the new shadow-DOM messaging UI.
- Bulk-archive all currently-flagged conversations.
- Right-click context menu on a flagged conversation: "Add sender to allow-list".
- Per-language pre-built lists (FR, ES, DE).
- Optional regex mode for power users.
MIT.