All journal notes
Agent security6 min read

SKILL.md Is an Executable Supply-Chain Dependency

A coding agent reads a skill as instruction and executes it with its own authority. Code review and static scanning see only half of that attack surface.

Читать на русском

Markdown now carries user privileges

Markdown does not execute anything on its own. A SKILL.md changes the behaviour of a program that may have a shell, a writable filesystem, a GitHub token, package registries, and sometimes production access. When the file says "run this preflight script before starting", a coding agent can treat that sentence as part of the job. The script then runs with the agent's authority.

That makes a skill awkward to classify. One package can contain natural-language procedure, shell commands, helper scripts, tool permissions, and routing rules. A code scanner inspects executable files. A prompt-injection detector reads prose. Neither can answer what matters operationally: what will the agent do after it combines the prose, code, current task, and permissions available in this session?

The authors of MalSkillBench tested 3,944 malicious skills with execution inside Docker, system-call monitoring, and an LLM judge. Their strongest skill-specific detector reached 98.4% recall on code injection, then degraded on prompt injection and attacks against the agent control plane. Conventional supply-chain scanners and prompt defenses each observed a different half of the package. Combining them did not recover the relationship between instruction and code.

A skill is neither documentation nor a conventional dependency. It has to be reviewed as a program whose control logic is partly written in natural language.

A plausible procedure rarely triggers resistance

Towards a Risk Assessment of Malicious Skill Files in Coding Agents did not rely on crude instructions such as "steal the SSH key". The attacks were presented as ordinary project setup.

The researchers took 471 real shell commands and used six models to turn them into 2,826 plausible skills spanning 11 MITRE ATT&CK tactics. Across 5,629 completed runs, Gemini CLI reached exploitability in 95.5-96.1% of cases and Qwen Code in 71.6-74.0%. Explicit recognition of the safety problem appeared in 1.99% of runs. The prompts, evaluation pipeline, and replication package are available in AgentJailbreak.

Those rates need the condition printed beside them: the agents ran with automatic approval. The study measures an autonomous execution loop. It does not measure how often a person would approve the same command after reading it. A setup that requires meaningful confirmation for every shell call should have a lower end-to-end exploitation rate.

Approval is still a weak boundary when the skill has already framed the action as "required diagnostics", "SDK initialization", or "environment verification". A reviewer sees the command through the explanation supplied by the untrusted package. After approving twenty legitimate calls, the next dialog easily becomes another button to clear.

The agent is not choosing between an obviously safe command and an obviously malicious one. It is following a locally coherent procedure that has been admitted into the project context.

Registry malware is already real

This attack surface is not confined to synthetic benchmarks. The USENIX Security 2026 paper "Do Not Mention This to the User" analysed 98,380 skills collected from two registries. Dynamic verification confirmed malicious behaviour in 157 packages, containing 632 vulnerabilities across 13 attack techniques.

A confirmed malicious skill contained 4.03 vulnerabilities on average and commonly crossed several stages of an attack chain. The researchers found two dominant strategies: credential theft through remote code execution, and manipulation of the agent through adversarial instructions embedded in documentation. More than half of the confirmed packages came from one actor using templated brand impersonation.

Registry maintainers removed all 157 reported skills after disclosure. That demonstrates useful incident response, not safety at install time. The packages were identified after collection and analysis. Until then, they travelled through a channel where installing an extension looks like normal tool configuration.

Package managers at least separate manifests from executable code and have accumulated lockfiles, signatures, SBOM tooling, and vulnerability databases. Skill registries often offer a one-line installer followed by Markdown that looks harmless during a quick review.

Static scanning evaluates appearance

An admission scanner can search for credential paths, suspicious URLs, dangerous commands, hooks, and instructions to conceal behaviour. It is a sensible first pass. It cannot certify runtime behaviour.

Cloak and Detonate tested eight scanners against 1,613 malicious skills collected in the wild. Self-extracting packing hid components during installation and reconstructed them at execution time. It bypassed every scanner in more than 90% of cases. Structural obfuscation bypassed most static scanners above 80% and reached 96% against one hybrid system.

The payload's purpose stayed the same. Only the representation visible to the scanner changed.

The paper's alternative, SkillDetonate, executes a skill in a sandbox and observes processes, files, network activity, and marked secret flows at the operating-system boundary. The authors report 97% detection at a 2% false-positive rate and 87% detection on real-world malicious skills.

These are author-reported results, not a production guarantee. A sandbox may miss a payload triggered only by a particular repository, date, domain, or credential. Detonation also costs more than static analysis. Its advantage is narrower and more useful: it measures behaviour rather than trusting the package's visible form.

Build an admission pipeline, not a perfect detector

An internal skill catalogue needs several independent boundaries.

Start with provenance: source, commit SHA, author, licence, and hashes for every file. A skill update is a new dependency and must repeat admission. Pulling latest automatically is incompatible with a reproducible agent.

The static stage should extract scripts and also commands, URLs, filesystem paths, credential references, hooks, and instructions that change agent policy. Observed capabilities can then be compared with a declared manifest. A Python formatting skill has no credible reason to read ~/.ssh or open arbitrary network connections.

Next, detonate the package in a disposable environment with seeded fake secrets and OS-level observation. Network access starts closed. Allowed endpoints are explicit. Reads of credentials, persistence attempts, agent-configuration changes, and outbound data flows become test events rather than prose for a reviewer to interpret.

Passing admission must not grant user privileges. Runtime capabilities should be issued per task. Read-only actions stay separate from side effects. Operations that mutate GitHub, cloud infrastructure, package registries, or production go through a second execution gate showing the command, arguments, source instruction, and expected state change.

The trace also needs causality. For each action, it should record whether the instruction came from the user, base policy, a specific skill revision, or a generated intermediate plan. Without that link, incident response sees a sequence of shell commands but cannot identify the authority that produced them.

Where the claim becomes weaker

A static Markdown skill without scripts or hooks has a much smaller blast radius when the agent has no shell, network, secrets, or write access. Mandatory approval also changes the risk when the reviewer sees the full command, real arguments, and source instruction instead of a generic confirmation dialog.

The controls can therefore be risk-based. As agent authority grows and human participation falls, skill admission should resemble software package review plus policy-code review. For a production coding agent running with automatic approval, installing an unverified SKILL.md is operationally close to running an unknown install script.

The install script looks dangerous immediately. Markdown asks for trust first.

Author / research leadDmitry / R&D Club

Bring us the problem with no obvious implementation path.

hello@rnd.club ↗