SW-REG-003: Agent content the private registry cannot judge
Last updated 7 November 2026
| Fact | Value |
|---|---|
| Severity | High |
| Checks | Private registry, in a connected run |
| Malicious indicator | No |
| OWASP Agentic Top 10 | ASI04 |
| OWASP MCP Top 10 | None mapped |
| NIST SP 800-53 | SR-3 (provisional mapping to SP 800-53 base controls) |
| First shipped in | Scanner 1.2.0 |
What it detects
Like the other registry rules, this one has no detector in the scanner's rule code and is raised only by a connected run with the registry check on, which needs an organisation on the Enterprise plan. It is raised for an item in scope that could not be given an identity, and it is raised without any call to the registry: the command cannot ask about what it cannot name. The evidence is the item's name and the reason, and the severity is high. The reason is one of seven:
- unhashable: a skill package cannot be hashed the way the registry hashes a forge archive of it. A
node_modules,.venv,venvor__pycache__folder is under it, the scan skipped such a folder,includeorexcludedrops one of its files, a link could not be followed, or a file has the git attributeexport-ignoreorexport-subst. - unresolved: the address or command holds a
${...}reference, the address cannot be read (a port out of range, control characters), or an option before the package or image is one the launcher is not known to take. - insecure: the address starts with
http://. This is also SW-CFG-001. - unpinned: a package is given as a range, a tag,
latestor with no version, or a plugin or marketplace is not pinned to a full commit. - unknown_launcher: the command is not a recognised launcher, such as
node server.js,python -m xor a path to a program. - launch_override: the launch changes what the launcher runs or where it fetches from, for example
docker run --entrypoint,--userconfigand--node-optionsof the Node launchers,--config-fileof uvx,--pip-argsof pipx, or anenventry such asNODE_OPTIONS,PYTHONPATH,LD_PRELOADorPATH. - resolver_override: a file of the repository redirects package resolution for the launcher's family, such as a registry line in
.npmrc,.yarnrc.ymlorbunfig.toml, or an index entry inuv.toml,pip.conforpyproject.toml.
Why it matters
What the registry cannot identify it cannot admit. If the check let such items through, the easiest way around the registry would be a launch it cannot read: a floating tag, a variable that is filled in somewhere else, a script, or a redirected package source. So an item that cannot be judged is a finding, not a pass. The scanner maps this rule to OWASP ASI04, Agentic Supply Chain Vulnerabilities, and to NIST SP 800-53 control SR-3, Supply Chain Controls and Processes.
The rule needs the Enterprise plan and a connected run. The check is described in the registry check of the CI guide, and what the registry can admit in the private registry guide.
Example
The server below is started with node and a script. The registry can admit only a launch that it can pin, so a connected run cannot identify this one:
This example is an illustration. It cannot be checked offline with spellwarden scan, for the reason given below it.
The rule is applied by a connected run before it asks the private registry anything (spellwarden_scan/rules/registry.py has no detector), so an offline scan of this file reports nothing for it.
.mcp.json
{
"mcpServers": {
"tools": {
"command": "node",
"args": [
"server.js"
]
}
}
}The finding sits on the server's line, and its evidence reads tools: unknown_launcher: the name and the reason.
How to fix
- For an unpinned or unknown launch, start the server through a pinned
npx,uvxordocker runform with every package at an exact version or an image at a digest. - For unresolved, write the address or command out instead of using a
${...}reference, and remove an option the launcher is not known to take. - For insecure, switch the address to
https://. - For launch_override and resolver_override, remove the option, the environment entry or the redirect from the repository.
- For unhashable, remove the folder or the git attribute and keep every file of the skill in the scan.
If it is a false positive
A server of your own that is started by a script is reported by design: the registry can admit only what it can pin. Package and pin it, or accept the finding with a note that names who maintains the script. A registry finding can be accepted in the baseline file for 90 days at most, and a pull or merge request is held to the base revision's baseline.
A resolver file on a developer's own machine is not seen by the scan, so a clean result here says nothing about it.
If the finding is not a problem in your case, accept it with a note: in the dashboard a manager or owner can accept a finding and the note is kept with it; with the scanner on its own, add it to the baseline file with a reason and an expiry date.