SymJack: The Symlink Is the Host's Problem. The Payload Is a Detection Problem.
SymJack (Adversa AI, 2026-05-26) symlink-hijacks an approved file copy to overwrite an AI coding agent's .mcp.json or .claude/settings.json with a malicious MCP server. Most affected vendors declined to patch. The symlink is a filesystem problem the host must fix — but the payload it plants is one an open detection-rules layer already flags. Run it through ATR and 15 rules fire, reproducibly.
_SymJack is two attacks wearing one trench coat. The clever half — a symlink that turns 'copy this video file' into 'overwrite my agent config' — is a host and filesystem problem. The other half, what gets planted, is a malicious MCP server, and that is a detection problem the rules layer already solves._
What SymJack does
Adversa AI (Rony Utevsky) disclosed SymJack on 2026-05-26. A malicious repo ships an instruction file (CLAUDE.md / AGENTS.md) plus a symlink whose innocuous name (docs/vid-settings.mp4) points at .claude/settings.json or .mcp.json. The agent asks the user to approve a benign-looking cp media/vid0.mp4 docs/vid-settings.mp4; the kernel follows the symlink and overwrites the real config with a planted MCP server that inline-executes a child process on the next restart. Claude Code was only partially patched (v2.1.129); Cursor, Gemini, Antigravity, and OpenAI Codex CLI declined; GitHub Copilot and Grok Build are still deciding.
Delivery versus payload
The symlink and approval-prompt deception is a host control — the agent and the OS must stop an approved file operation from following a symlink into a config path. A content-detection layer cannot see that, and should not pretend to. But what the attack plants — an MCP server whose command is node with an inline -e flag that calls child_process.exec — is exactly the malicious MCP-server shape a rules layer is built to catch, no matter how it reached disk.
What ATR already catches
We ran the payload SymJack plants through the open Agent Threat Rules engine, against the current rule set, with no SymJack-specific rule added. Importing scan from pyatr and printing the rule_id of each match for that payload returns 15 hits against the 450-rule corpus — including ATR-2026-00010 (critical), ATR-2026-00415 (critical), ATR-2026-00419 (cursor-mcp-zero-click-config, critical), and ATR-2026-00541 (high). The malicious MCP-server shape was already covered. The delivery vector is new; the payload shape is not.
Where each layer sits
| Layer | Sees the symlink trick? | Sees the planted MCP server? |
|---|
|---|---|---|
| Host / filesystem / approval UI | Yes — the fix belongs here | — |
|---|
| Runtime LLM-output guardrail | No | No, it runs on the output |
|---|
| MCP / skill-content scanner | No | Yes — ATR rules fire here |
|---|
| Process / EDR | Partial (config write, child process) | Partial |
|---|
What we are not claiming
ATR does not detect the symlink or the approval deception — that is a host control, and the affected vendors, not a rules layer, own that fix. The detection layer complements the host patch; it does not replace it. The payload coverage above is real and reproducible, and it is also not a guarantee against every future obfuscation of an MCP-server payload. Honest layering, not a silver bullet.
What to do this week
Host side: treat agent config paths (.mcp.json, .claude/settings.json, .cursor/mcp.json, .gemini/settings.json) as integrity-sensitive — block approved file operations from resolving symlinks into them, and review config provenance after pulling an untrusted repo. Detection side: scan MCP server definitions for interpreter commands with inline-exec flags (node -e, python -c) before initializing them — the ATR MCP-poisoning rules do this in any runner that accepts ATR format (npm, MISP, Cisco AI Defense).
_Adam Lin maintains Agent Threat Rules, an open MIT-licensed detection corpus for AI agent threats. ATR rules are in production at Microsoft, Cisco, and MISP. Founder of Panguard AI, building the commercial product around the ATR standard. Reach: [email protected]_