Skip to main content

Security scanning

Every upload is scanned before anyone decides on it, with SkillSpector, an open-source scanner for agent skills.

What it looks for​

CategoryExample
Prompt injection"Ignore all previous instructions…" in a skill
Credential accessReading ~/.ssh, ~/.aws or token files
Data exfiltrationSending data to an outside URL
Remote code executionDownloading a script and running it
Code that runs on its ownHooks that fire on Claude Code events
Supply chainRisky dependencies

Hooks​

A plugin's hooks run automatically — before or after a tool call, at session start, and so on. The scanner reads the hook configuration and follows it into the scripts the hooks call: a harmless-looking hooks.json that runs a malicious hooks/run.sh is reported against hooks/run.sh. Any plugin with hooks is flagged for review, whatever its contents.

Waxell's own checks​

SkillSpector reads what's in the upload. Two risks live outside it, so Waxell checks them itself and adds the findings to the same result. They can raise the verdict, never lower it.

MCP servers​

For every MCP server a plugin declares, Waxell checks how it's launched:

FindingSeverity
Downloads a script and pipes it to a shellCritical
Launches through a shell (sh -c …)High; Critical if it also downloads
Runs a package at whatever version is newest (npx -y pkg)High
Runs a pinned third-party packageMedium
Package name resembles a well-known oneMedium
Container image not pinned; privileged or host-sharing containerHigh / Critical
Connects over plain HTTPHigh
Connects to a server not in the MCP catalogMedium (Low if catalogued but not verified)
A credential written into the configurationHigh
Pointed at a home folder, the filesystem root, or credential foldersMedium / High

A remote server always gets a finding naming where it connects, even a verified one. Every query the model sends through it goes to that service, so you see who that is before you approve.

What a skill tells Claude to install​

A skill is instructions, and Claude follows them. If a SKILL.md says "run npm install some-package", that package installs on the user's machine when the skill runs, even though it was never part of the upload.

FindingSeverity
Tells Claude to download a script and pipe it to a shellCritical
Tells Claude to install packages without pinning a versionHigh
Tells Claude to install pinned packagesMedium

Covers npm, pnpm, yarn, bun, pip, uv, gem, cargo and go. Restoring a project's own dependencies (npm install with no package, pip install -r requirements.txt) isn't flagged.

Binary files​

The scanner reads text, so Waxell inspects every other file itself — by what its bytes are, not its name — and the file ships with the package as uploaded.

FindingSeverity
An Office file with macrosCritical
An Office file that loads remote content when opened (an attached template, a linked object or image, a data connection), or embeds other filesHigh
A PDF with scripts, embedded files or an open actionHigh
An executable, library or Java archiveHigh
An archive inside the package (its contents aren't scanned)High
A legacy .doc / .xls / .ppt, or a file type Waxell can't inspectMedium
Inspected, nothing found — a clean Office file, image, font or PDFInfo

Every binary file gets a finding, so you can see each one was looked at. Ordinary hyperlinks in a document aren't findings.

Reading a result​

PartMeaning
VerdictSafe, Caution, or Do not install. The scanner can rate a package as a whole with no individual finding; the drawer says so.
Risk score0–100.
Worst findingThe most severe finding, shown beside the verdict.
FindingsEach with severity, the file and line, the matched text, and how to fix it.
The verdict and the findings can disagree

The scanner can call a skill Safe while reporting a high finding. Waxell always shows the worst finding beside the verdict, and the auto-approval severity rule acts on the finding — so a "Safe" skill with a high finding still goes to a person.

What isn't scanned​

  • Inside a binary file beyond the checks above — an image's pixels, a compiled program's behaviour. Executables and archives are flagged for that reason.
  • Code fetched when a plugin runs — the package an MCP server downloads at start-up, or one a skill tells Claude to install. Waxell flags that it happens (above) but can't scan code that isn't in the upload. Plugins with MCP servers, hooks or scripts go to a person by default for this reason.

Scanning is static analysis. Tenant content is not sent to a language model.

Rescanning​

Rescan in the drawer runs the scan again. A submission still waiting for a decision is re-checked against your policy when the new result arrives.