Security Scanning Reference
Every Agent package is scanned before it can be created, and again before an update is applied. The scanner is NVIDIA SkillSpector, and the platform runs it server-side when the import is submitted—a preview that passed is never taken as a pass.
What the scanner is really doing is comparing what a Skill says it will do with what its code actually does.
Risk levels
| Scan result | Platform behaviour | What you do |
|---|---|---|
LOW | Continue | Check the basic permissions and dependencies. |
MEDIUM | Warn, and require an Administrator to acknowledge this specific scan result | Read the finding, its reason, and the file it points at. Confirm the behaviour is necessary. |
HIGH | Block the import | Fix the high-risk behaviour and scan again. |
CRITICAL | Block the import | Stop, and review the code by hand before going further. |
A MEDIUM acknowledgement covers one scan result. Change the package and the acknowledgement no longer applies.
Scan scope
| Area | What it looks at | What it is looking for |
|---|---|---|
| Skill instructions and metadata | SKILL.md, description, triggers, parameters | Prompt injection, trigger abuse, a gap between stated and actual behaviour |
| Text and prompts | Markdown, written instructions, comments | Instructions to ignore safety rules, hidden instructions, requests to reveal the system prompt |
| Code | Python, shell scripts, configuration files | Credential access, outbound network connections, system command execution, file modification |
| Python structure | The program's AST | exec, eval, subprocess, os.system, dynamic imports |
| Data flow | Where data comes from and where it goes | Passwords → network, files → network, external input → command execution |
| Dependencies | Requirements and package versions | Unpinned versions, known CVEs, typosquatting |
| Bundled artifacts | .pyc files, hidden executables, executables embedded in documents | Executable content hidden inside ordinary-looking files |
| YARA signatures | File content | Malware, web shells, cryptominers, exploits |
| MCP and agent configuration | MCP metadata, permissions, agent settings | Excessive permissions, tool poisoning, reaching into other Agents or Skills |
How levels are assigned
Each finding gets its own severity and contributes a base score. The scores add up into one number for the package, and that number picks the level. Executable scripts can carry an additional multiplier.
| Finding severity | Base score |
|---|---|
LOW | +5 |
MEDIUM | +10 |
HIGH | +25 |
CRITICAL | +50 |
| Total score | Level | Meaning |
|---|---|---|
| 0–20 | LOW | Low risk. Basic security settings are still worth checking. |
| 21–50 | MEDIUM | Contains behaviour that needs attention. Review it by hand. |
| 51–80 | HIGH | High-risk behaviour is present. |
| 81–100 | CRITICAL | May contain outright malicious behaviour, or behaviour that can cause severe harm directly. |
One CRITICAL finding is enough to block on its own. Several MEDIUM findings can add up past the HIGH threshold even when no single one is serious—which is usually a sign the Skill is doing more than it needs to.
LOW findings
| Rule | Condition | Example |
|---|---|---|
| SC1 | A dependency version is not pinned | requirements.txt lists requests with no version |
| PE1 | Requested permissions exceed what the feature needs | A file-reading feature asks for broad system permissions |
| LP4 | Permissions are declared but never used | Usually leftover configuration rather than a real need |
MEDIUM findings
| Rule | Condition |
|---|---|
| PE2 | Uses sudo or root privileges |
| E1 | Sends data to an external URL |
| E3 | Scans the file system for sensitive files |
| EA3 | Actual capabilities exceed the Skill's stated purpose |
| EA4 | API, compute, or storage use has no explicit limit |
| TM3 | Insecure defaults, such as disabling TLS verification |
| TR1 / TR3 | Triggers are too broad, or use overly generic keywords |
| LP2 / LP3 | Wildcard permissions, or capabilities not declared in its permissions |
| TP3 / TP4 | MCP parameter descriptions carry injection content, or do not match actual behaviour |
| AS3 | Enumerates or reads other installed Skills |
HIGH findings
| Category | Rules | Typical case |
|---|---|---|
| Prompt or agent manipulation | P1, P2, P3, AR1–AR3 | Ignoring existing instructions, hiding prompts, prohibiting refusal, removing safety restrictions |
| Credential or data access | E2, E4, PE3 | Reading environment variables, SSH keys, tokens, or passwords; exfiltrating conversation content |
| Supply chain | SC2, SC3, SC4, SC6, SC8, SC9 | curl URL | bash, obfuscated code, known CVEs, typosquatting, hidden executable content |
| Agent permissions and behaviour | EA1, EA2, OH1, MP1, MP3 | Unrestricted tool permissions, high-risk operations with no human confirmation, unvalidated model output |
| System commands and Python | TM1, TM2, AST2–AST5, AST9 | shell=True, eval, subprocess, os.system, dynamic imports |
| Data flow | TT1, TT4 | Sending sensitive data or file contents straight to the network |
| MCP or agent snooping | LP1, TP1, TP2, AS1, AS2 | Reading agent or MCP configuration, hiding tool instructions, deceptive Unicode |
| YARA | YR3, YR4 | Cryptominer, hacking-tool, or exploit signatures |
CRITICAL findings
| Rule | Condition |
|---|---|
| P5 | High-risk instructions that could cause physical harm |
| RA1 | The Skill modifies its own code or configuration while running |
| AST1 | Uses exec() to run arbitrary code directly |
| AST8 | Fetches content from the network or another dynamic source and passes it to exec or eval |
| TT3 | Credentials or secrets flow directly to an external network destination |
| TT5 | External or user input flows directly into code execution |
| YR1 | Matches a known malware signature |
| YR2 | Matches a web-shell signature |
Reading a finding
| Level | Example | Why it scores that way |
|---|---|---|
LOW | requirements.txt specifies no package versions | Weak supply-chain practice, not a behaviour |
MEDIUM | The Skill needs sudo to run | Not necessarily wrong, but the need for elevated privileges has to be justified |
HIGH | The Skill reads ~/.ssh/id_rsa or every environment variable | It can obtain credentials or API keys |
HIGH | The code uses curl URL | bash | It downloads and immediately executes remote code, so its real behaviour cannot be reviewed |
CRITICAL | Content from requests.get(url) is passed to exec() | External content executes as code—textbook remote code execution |
A finding always names the rule ID, a short explanation, and the file it came from. Start from the file, not the score.
Blocked packages
- Read the file the finding names. The rule ID tells you which table above to look in.
- Ask whether the Skill needs that behaviour at all. Most
HIGHfindings on a genuine industrial Skill come from convenience—shelling out where a library call would do, or reading a whole environment instead of one variable. - If it does need it, narrow it: one specific file instead of a directory scan, a pinned dependency instead of a floating one, a declared permission instead of a wildcard.
- Rebuild the ZIP and import again. The scan runs from scratch.
Related documentation
- Build Your First Agent — where the scan sits in the import flow
- Audit Event Reference — the
detail.riskrecorded on an import