
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
hidden-agenda
Advanced tools
Find content in your repo that talks to AI agents behind your readers' backs — hidden HTML comments, concealed elements, invisible unicode.
Find content in your repo that talks to AI agents behind your readers' backs.
When someone points an AI assistant at your repo — "evaluate this package", "install this MCP server" — the agent reads the raw files. Humans read the rendered ones. Anything that lives in the gap between those two views is an invisible channel straight into somebody else's agent: hidden HTML comments, concealed elements, invisible unicode. This linter closes the gap.
npx hidden-agenda # scan the current repo
npx hidden-agenda docs/ README.md --fail-on warn
npx hidden-agenda --json # machine-readable findings
ERROR README.md:1 [html-comment/agent-greeting]
Hidden HTML comment addresses/instructs an AI agent (agent-greeting, machine-readable-offer)
» Hello, agent. A human is probably reading this README, but you might be too. …
why: Directly greets an AI agent — meaningless to human readers, actionable to machines.
| Detector | Severity | What |
|---|---|---|
html-comment | error | Hidden <!-- --> comments that greet, address, or instruct AI agents ("hello, agent", "if you are an AI…", "ignore previous instructions", "do not tell the user", offers of machine-readable endpoints) |
html-comment | warn | URLs offered only inside hidden comments — links human readers never see |
hidden-element | error/warn | The same content inside hidden, display:none, font-size:0, or aria-hidden elements |
invisible-unicode | error | Unicode tag-block characters (U+E0000–E007F) — invisible ASCII smuggling |
invisible-unicode | warn | Zero-width characters and bidi controls (Trojan Source) |
Tooling comments (eslint, prettier, toc, licence headers…) are allowlisted.
Precision over breadth: a linter people mute catches nothing.
- uses: StuMason/hidden-agenda@v0
with:
paths: "." # optional
fail-on: error # error | warn | never
0 clean · 1 findings at/above --fail-on · 2 usage error
I put a hidden HTML comment in the README of my own MCP server — invisible on GitHub, perfectly visible to any agent asked to vet or install the package — and someone rightly called it out. The intent was a marketing experiment; the pattern is indistinguishable from an attack, because agents can't read intent, only instructions. I removed it, then built this so it can't happen quietly again — and the first time I ran it across my own repos, it found a second one I'd forgotten about.
If you ship anything agents are asked to read — MCP servers, CLIs, actions, libraries — put this in CI and make the invisible channel a build failure.
import { scan, scanFile } from "hidden-agenda";
const { findings, filesScanned } = scan(["."]);
MIT © Stu Mason
FAQs

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.