Abstract descriptions of malicious agent skills are useful, but a concrete example makes the pattern click. This is a walkthrough of a package from our own research dataset that positioned itself as a legitimate security auditing tool while its actual code quietly harvested and transmitted sensitive configuration files.
The pitch versus the payload
On its face, the skill described itself as a security-auditing helper, the kind of tool a developer would install specifically because they care about security. Its real behavior did something very different: a function collected the contents of a small, predictable set of sensitive files, .env, .bashrc, .zshrc, .gitconfig, and secrets.yaml, encoded the collected data, and sent it over a raw socket connection to a hardcoded external domain. Read errors were silently swallowed with a bare except: pass, so the skill would keep running smoothly even where individual files weren't accessible, never raising a visible error that might tip off the person running it.
What the static layer caught
Running the package through our static layer surfaced the obvious red flags immediately: suspicious imports like socket and base64, file-access patterns targeting known-sensitive paths, and an explicit keyword match on the word "exfiltrate" sitting in a code comment. That combination was enough to assign a maximum severity score on its own. This is exactly the kind of case where static analysis works well: the evidence was sitting in plain, unobfuscated text.
What the sandbox layer added
Executing the skill inside an isolated sandbox showed the same story from a completely different angle, one that would have caught this package even if the source code had been obfuscated. The runtime trace showed repeated open() calls succeeding against .env and .zshrc, followed by a connect() call establishing an unauthorized outbound connection to the external domain. That sequence, successful sensitive file access immediately followed by an unfamiliar outbound connection, is precisely the correlation dynamic analysis is built to catch.
The reasoning layer's assessment didn't stop at the technical indicators. It flagged the contradiction directly: a module docstring that openly described stealing sensitive data and sending it to external servers, sitting inside a package marketed as a security auditor. Deceptive packaging combined with silently suppressed error handling was treated as sophisticated evasion, not an isolated coincidence.
Why all three signals mattered together
Any one of these three layers would likely have caught this particular package on its own, which is part of what makes it a useful teaching example rather than an edge case. The value of running all three isn't that this specific skill needed all three to be caught. It's that the next one might only show its true nature at exactly one of these layers, and you don't know in advance which one that will be.
FAQ
Why would an attacker name a skill after a security-related function? Because a security-branded name lowers a developer's guard rather than raising it. A tool that claims to audit for security issues is, ironically, one of the more effective disguises for a tool that's actually causing them.
Would this skill have passed a review that only checked the SKILL.md description? Almost certainly. The documentation described a plausible, benign function. The malicious behavior lived entirely in the implementation, which is exactly why documentation review alone is not a sufficient security control.
What made the bare except clause significant? It wasn't just sloppy error handling. Suppressing every possible exception silently is a common evasion technique, since it prevents a failed file read or blocked action from ever surfacing an error that might alert the user something unusual was happening.
Related reading: "Shadow Features: The Malicious Capability Your Skill Scanner Never Sees," "Data Thieves in Disguise: How Malicious Agent Skills Harvest Credentials"











