Voltar às atualizações
New releaseAug 6, 2026

SecureAI-Scan v0.8.0

SecureAI-Scan é uma ferramenta CLI que analisa bases de código TypeScript e JavaScript em busca de problemas de segurança específicos de aplicativos com tecnologia de IA — injeção de prompt, abuso de ferramentas MCP, envenenamento de dados RAG, violações de confiança de agentes e muito mais.

Compartilhar

SecureAI-Scan

npm version npm downloads CI CodeQL OpenSSF Scorecard license Node OWASP

CLI offline que analisa TypeScript, JavaScript e Python em busca de riscos de LLM, MCP, Agent Skill e RAG — evidência de fluxo de dados resolvida por importação, zero falsos positivos por padrão, mapeada para OWASP LLM/ASI/MCP Top 10.

A maioria dos scanners neste espaço faz correspondência de padrões com uma palavra-chave e chama isso de descoberta. O SecureAI-Scan rastreia o caminho real de origem → fluxo → destino através de código real, resolvido por importação — e uma varredura padrão mostra apenas o que ele pode comprovar. Sem conta, sem upload para a nuvem, nada sai da sua máquina.

Cobre o OWASP Top 10 para Aplicações LLM 2026 oficial, o Top 10 para Aplicações Agênticas (2026) e o MCP Top 10 desde a semana de lançamento.

Comece em 30 segundos```bash

npx --yes [email protected] scan .

Sem conta, upload para a nuvem, interpretador Python ou configuração necessários. TypeScript, JavaScript, Python, configs MCP e pacotes de Agent Skill são detetados automaticamente.

**Candidato a lançamento `0.9.0` medido:** 136/136 testes · 88,08% de cobertura de declarações · 12.676 ficheiros em 9 repositórios públicos · 0 novas impressões digitais de nível predefinido face à linha de base revista. [Evidência](https://github.com/akanthed/secureai-scan/blob/main/docs/benchmarks/v0.9.0.json) · [metodologia e limites](https://github.com/akanthed/secureai-scan/blob/main/docs/ReleaseAssurance.md)```
  ▌ HIGH  AI001  Prompt injection via user input
    PROVEN  LLM01:2026 Prompt Injection

    source src/chat.ts:8   request data `req.body.input`
    flow   src/chat.ts:13  passed as `systemPrompt`
    sink   src/chat.ts:10  openai.chat.completions.create — system role (OpenAI)

    fix    Keep system prompts static; pass user input as a user-role message.

Isto é para você? O SecureAI-Scan é deliberadamente escopado para riscos de LLM, MCP e RAG/agentes — injeção de prompt, envenenamento de ferramentas, tratamento inseguro de saída, controle de acesso a vector stores, envenenamento de habilidades de agentes. Não é um scanner SAST geral ou de segredos, e não tenta ser um; um pacote conhecidamente malicioso sem payload em formato LLM (por exemplo, um endereço de exfiltração hardcoded em uma chamada de API de e-mail) é capturado pela lista de avisos offline (DEP003), não por uma regra de padrão. Se seu código fala com um LLM, um servidor MCP, um vector store ou envia Agent Skills, isto foi feito para você.

Novo: varredura estática de configuração para LiteLLM Proxy (config.yaml) — segredos hardcoded, endpoints de provedor em texto puro, guardrails ausentes. Veja Regras (LLC001–LLC003).

Conteúdo

Por que este scanner é diferente

  • Níveis de evidência, não ruído. Cada achado é provado (dataflow rastreado ou fato de configuração analisado), provável (sink resolvido, um salto heurístico) ou heurístico. Uma varredura padrão mostra apenas provado + provável. Heurísticas são opcionais via --paranoid.
  • Detecção resolvida por importação. Uma chamada só é uma "chamada de LLM" se resolver para uma importação real de SDK (openai, @anthropic-ai/sdk, ai, @google/genai, LangChain, Bedrock, …). Seu cliente do Google Maps nunca mais será sinalizado como LLM.
  • Limitado por precisão e avaliado contra repositórios reais. A suíte de testes afirma que cada fixture vulnerável dispara e que cada fixture segura permanece limpa — um falso positivo no corpus seguro quebra o build. Além disso, npm run regression varre repositórios públicos reais (OpenAI/Anthropic/Vercel AI SDKs, servidores MCP oficiais, LlamaIndex) contra uma baseline commitada e revisada manualmente e falha em qualquer novo achado provado/provável. Veja Testes e benchmarking para os números reais de antes/depois, ou O que encontramos varrendo repositórios reais para a história por trás deles — uma taxa de captura de 6/6 em um corpus rotulado de skills maliciosas, e por que não estamos chamando llama_index de "vulnerável" por um achado honesto em nível de biblioteca. Write-up da discussão →
  • SARIF para code scanning do GitHub. --output report.sarif coloca achados inline em pull requests e na aba Security.
  • AI-BOM. secureai-scan bom . constrói um inventário derivado de sintaxe de SDKs, IDs de modelo, vector stores, frameworks de agentes e servidores MCP, mapeado para as necessidades de documentação do OWASP LLM Top 10 / EU AI Act.
  • Varredura de configuração MCP. Analisa .mcp.json, claude_desktop_config.json, .cursor/mcp.json: servidores npx -y sem pin, segredos inline, transportes HTTP em texto puro.
  • Detecção de envenenamento de ferramentas MCP. Captura o padrão por trás do rug-pull do WhatsApp MCP e do backdoor do postmark-mcp — Unicode invisível, frases de injeção direcionadas a agentes e shadowing entre ferramentas em nomes/descrições, estaticamente, antes de você sequer executar o servidor.
  • Detecção de injeção de comando MCP. Sinaliza command/args do transporte stdio MCP construídos a partir de dados de requisição — o padrão por trás da divulgação de RCE no MCP STDIO de 2026.
  • Detecção de envenenamento de Agent Skills. As mesmas verificações de Unicode invisível, frases de injeção e shadowing aplicadas a arquivos SKILL.md — Agent Skills são carregados integralmente no contexto, então uma skill envenenada é uma descrição de ferramenta envenenada por outro nome.
  • Varredura de skills resistente a evasão. Bundles de skills são varridos como diretórios, não apenas seu SKILL.md, e cada verificação de conteúdo roda contra variantes deofuscadas do texto. Isso visa as técnicas publicadas — homóglifos, divisão por zero-width, payloads armazenados em .git/ ou build/, exfiltração escondida em um arquivo *.test.ts — que contornaram >90% dos nove scanners pesquisados em Cloak and Detonate (arXiv:2607.02357). Veja Resistência a evasão.
  • Avisos de pacotes conhecidamente vulneráveis e maliciosos, cientes de versão. Verifica cada dependência e cada pacote lançado via MCP contra um snapshot de avisos embutido — uma lista curada manualmente de backdoors documentados in-the-wild, além de avisos OSV HIGH/CRITICAL para uma watchlist de pacotes LLM/MCP/RAG, regenerada por scripts/sync-advisories.js. Roda offline em cada varredura, sem necessidade de flag. Um CVE só dispara quando sua versão fixada está provadamente dentro do intervalo afetado; um pacote documentado como malicioso dispara mesmo em um intervalo ambíguo, porque instalar um backdoor é irrecuperável.
  • Local-first. Nada sai da sua máquina.

Como ele se compara

O SecureAI-Scan não é um substituto para uma ferramenta SAST geral ou um scanner de contêiner/IaC — execute-o junto com uma, não no lugar de uma. Ele é feito sob medida para a superfície de ataque LLM/MCP/RAG e enfatiza evidência de dataflow em vez de achados planos por palavra-chave.

SecureAI-ScanSemgrep (regras OSS)TrivyGitHub Advanced Security
Injeção de prompt (source→sink rastreado)✅ dataflow resolvido por importação⚠️ apenas regras de padrão, mantidas pela comunidade⚠️ CodeQL pode, mas sem ruleset específico de IA
Envenenamento de ferramentas MCP / risco de configuração✅ MCP007–010, scanner de configuração
Envenenamento de Agent Skills (SKILL.md)✅ resistente a evasão, ciente de bundle
Configuração incorreta de RAG / vector-store✅ VEC001–004
Avisos de pacotes de IA conhecidamente maliciosos✅ DEP003, offline, ciente de versão⚠️ feed CVE geral, não específico de IA⚠️ Dependabot, feed CVE geral
SAST geral (SQLi, XSS, path traversal)❌ fora do escopo por design
Varredura de contêiner / IaC⚠️ via CodeQL/Actions
Níveis de evidência (provado/provável/heurístico)❌ achados são planos⚠️ CodeQL tem alguns, não ajustados para IA
Saída SARIF (code scanning do GitHub)nativo
Roda offline, sem conta✅ (regras OSS)❌ requer GitHub

Se você já roda Semgrep ou GHAS, mantenha-os — adicione o SecureAI-Scan para a superfície de risco que eles não modelam de forma alguma.

Prefere fazer perguntas primeiro? Experimente o SecureAI-Scan AI Security Advisor no ChatGPT gratuito.

Prestes a executar um servidor MCP que encontrou no GitHub ou Twitter? Cole a descrição da ferramenta no MCP X-Ray primeiro — verifica Unicode oculto, instruções injetadas e pacotes conhecidamente maliciosos no seu navegador, sem instalação.

Veja funcionando

secureai-scan scan . de ponta a ponta, saída real contra um arquivo real (pequeno, deliberadamente vulnerável) — fonte:

Gravação de terminal do secureai-scan scan . encontrando uma vulnerabilidade de injeção de prompt rastreada

Formatos de ataque que o scanner rastreia de ponta a ponta:

Dataflow de envenenamento de ferramentas MCPDataflow de injeção de contexto RAG
Rastreio de ataque MCPRastreio de envenenamento RAG

Comandos

O que você precisa 95% das vezes:```bash secureai-scan scan .

Tudo o resto está lá quando precisar. `secureai-scan scan . --help` mostra tudo isto no terminal, agrupado da mesma forma:

**Uso diário**

| Flag | O que faz |
|------|---------------|
| *(nenhuma)* | resultados `proven` + `likely` — o padrão, sem necessidade de flags |
| `--paranoid` | inclui também resultados de nível `heuristic` |
| `-s, --severity <level>` | mostra apenas resultados em/abaixo de `low`\|`medium`\|`high`\|`critical` |
| `--output <file>` | escreve um relatório completo — `.sarif` (code scanning do GitHub), `.json`, `.md` ou `.html` |

**Âmbito das regras que são executadas**

| Flag | O que faz |
|------|---------------|
| `-r, --rules <list>` | executa apenas estes IDs de regras, ex.: `AI001,MCP007` |
| `--only-ai` / `--only-mcp` / `--only-vec` / `--only-skl` | executa apenas uma categoria de regras |
| `--check-dependencies` | verifica também `package.json`/`requirements.txt` contra o registo npm/PyPI para erros de digitação e pacotes alucinados (`DEP001`/`DEP002`). Ativado automaticamente se selecionar essas regras diretamente via `-r` — nunca precisa de se lembrar de passar ambas. Não é necessário para `DEP003` (pacotes conhecidos como maliciosos), que é sempre executado offline |

**CI / fluxo de trabalho**

| Flag | O que faz |
|------|---------------|
| `--fail-on <severity>` | sai com código `1` se existirem resultados em/abaixo desta gravidade |
| `--baseline <file>` | monitoriza apenas problemas novos/alterados em relação a uma baseline guardada |
| `--policy <file>` | carrega limites, caminhos ignorados e regras bloqueadas de um `.secureai-policy.json` (deteção automática se presente — `secureai-scan init` cria um) |

**Avançado**

| Flag | O que faz |
|------|---------------|
| `--min-confidence <0-1>` | mais granular que `--paranoid`: oculta resultados abaixo de uma pontuação de confiança exata (`0.9` proven / `0.65` likely / `0.35` heuristic) |
| `--limit <n>` | número máximo de grupos de regras mostrados no terminal (padrão `10`) — o detalhe completo vai sempre para `--output` |
| `--debug` | imprime cada ficheiro analisado e quais regras foram executadas |

**Analise antes de instalar — sem clone, sem configuração:**```bash
secureai-scan skill anthropics/skills          # a GitHub "owner/repo" shorthand
secureai-scan skill https://github.com/…       # or a full git URL
secureai-scan skill ./some/local/skill-dir     # or a local path
secureai-scan mcp some-mcp-server-package      # a bare npm package name
secureai-scan mcp owner/mcp-server-repo        # or git, same as `skill`

skill e mcp buscam o alvo e o analisam, depois eliminam a cópia obtida (--keep para inspecioná-la em vez disso). Nada do que é obtido é alguma vez executado: um alvo npm é descarregado com npm pack — apenas o tarball, sem install, sem scripts de ciclo de vida — e um alvo git é um simples git clone --depth 1. Este é o momento que mais importa: antes de uma skill chegar a ~/.claude/skills/ ou de um servidor chegar a .mcp.json, não depois.

Outros comandos:```bash secureai-scan bom . --output AI_BOM.md # AI Bill of Materials secureai-scan explain AI001 # why + exploit + fix example, for any rule secureai-scan threat-model . # THREAT_MODEL.md with the OWASP coverage matrix — example: docs/examples/THREAT_MODEL.example.md secureai-scan init # policy file + CI workflow, one-time setup

Suprimir uma descoberta revisada no código:```ts
// secureai-ignore AI001: reviewed, input sanitized via allowlist

GitHub Action```yaml

name: SecureAI-Scan on: [pull_request] permissions: contents: read security-events: write jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: akanthed/[email protected] with: scanner-version: 0.10.0 fail-on: high

As descobertas aparecem como anotações inline no PR e na aba de Segurança do repositório. (`secureai-scan init` gera um workflow equivalente usando a CLI diretamente.)

A varredura está limpa? Adicione o badge ao seu próprio README:```md
[![secureai-scan](https://img.shields.io/badge/secureai--scan-passing-brightgreen)](https://github.com/akanthed/SecureAI-Scan)

Pre-commit hook

Prefere capturar descobertas antes de serem enviadas? Adicione este repositório como fonte de hook do pre-commit em vez de, ou juntamente com, a GitHub Action:```yaml repos:

O hook verifica todo o projeto a cada commit (não apenas os arquivos alterados — um rastreamento de fluxo de dados no arquivo A pode depender do arquivo B, o que uma verificação parcial deixaria passar) e bloqueia o commit em descobertas de severidade `high`+ por padrão. Substitua o limite na sua própria configuração:```yaml
      - id: secureai-scan
        args: ["--fail-on", "critical"]

Regras

42 regras, mapeadas para o OWASP Top 10 oficial para Aplicações de LLM (2026) — além, quando aplicável, do OWASP Top 10 para Aplicações de Agentes (2026, ASI), do OWASP MCP Top 10 (2025) e de um artigo da Lei de IA da UE. Consulte a cobertura e limites da versão 2026; threat-model renderiza a matriz para cada projeto verificado.

RegraO que ela comprovaOWASP
AI001Entrada do usuário flui para um prompt de sistema/desenvolvedor (fonte rastreada → sumidouro, inclusive entre limites de arquivo/função)LLM01
AI002Conteúdo do prompt ou segredos gravados em logs (em arquivos que usam um SDK de LLM)LLM02
AI003Chamada de LLM em um manipulador de requisição sem verificação de autenticação antes delaLLM06
AI004Objeto inteiro de usuário/sessão serializado em um prompt (a seleção de campos não é sinalizada)LLM02
AI005Saída do LLM alcança sumidouros de eval/exec/SQL/HTMLLLM10
AI006Ferramentas de alto impacto (delete, pay, deploy, …) expostas sem uma etapa de aprovaçãoLLM03
AI007Conteúdo de RAG recuperado interpolado em prompts privilegiadosLLM01
AI008Segredos incorporados no texto do prompt de sistemaLLM08
AI009Entrada de usuário sem limites / limites de token ausentesLLM06
AI010Conteúdo externo buscado flui para promptsLLM01
AI011Saída do agente elevada ao papel de sistema em chamadas posterioresLLM03
AI012Saída do LLM analisada sem validação de esquemaLLM10
MCP001Metadados de ferramenta MCP alcançam o prompt de sistema sem validaçãoLLM01
MCP002URL do servidor MCP construída a partir de entrada do usuárioLLM04
MCP003Resultados de ferramenta MCP elevados ao papel de sistemaLLM10
MCP004Servidor MCP iniciado como um pacote npx -y sem fixação de versãoLLM04
MCP005Segredo embutido em uma configuração MCP versionadaLLM02
MCP006Servidor MCP sobre HTTP sem criptografiaLLM04
MCP007Unicode invisível/bidi oculto em nomes ou descrições de ferramentas MCPLLM01 · MCP03
MCP008Frases de injeção direcionadas a agentes em descrições de ferramentas MCPLLM01 · MCP03
MCP009Uma descrição de ferramenta que direciona chamadas para uma ferramenta diferente (sombreamento)LLM01 · MCP03
MCP010Comando/argumentos do servidor MCP stdio construídos a partir de entrada do usuário (RCE)LLM04 · MCP05
SKL001Unicode invisível/bidi em qualquer lugar em um pacote de Skill de AgenteLLM01
SKL002Fraseado de injeção direcionado a agentes na descrição ou no corpo de uma skill (correspondido por meio de ofuscação)LLM01
SKL003O conteúdo de uma skill direciona quando/como uma skill diferente é usada (sombreamento)LLM01
SKL004Payload encenado/autoextraível: blob opaco + instruções para decodificá-lo e executá-loLLM04 · MCP04
SKL005Leitura de credenciais + egresso externo codificado em um arquivo complementar do pacoteLLM02 · MCP04
SKL006Execução de comando em tempo de carregamento via sintaxe de injeção de contexto dinâmico do Claude Code (!`cmd`/```!), antes de qualquer etapa de permissão de ferramentaLLM04 · MCP05
SKL007Concessão de Bash sem escopo no frontmatter allowed-tools de uma skillLLM03
SKL008Skill busca instruções de uma URL externa e direciona o agente a segui-las ("Circus of Skills")LLM04
SKL009Skill persiste uma backdoor gravando em outro arquivo de contexto (MEMORY.md/SOUL.md/AGENTS.md/CLAUDE.md)LLM05
SKL010Tag insegura de desserialização YAML/JSON no frontmatter de uma skill ou em um arquivo de configuração empacotadoLLM04
VEC001Busca vetorial sem filtro de locatário/usuárioLLM09
VEC002Limite de busca sem limites ou controlado pelo usuárioLLM06
VEC003Conteúdo do usuário ingerido em um armazenamento vetorial compartilhadoLLM05
VEC004Ingestão sem marcação de locatário/namespaceLLM09
DEP001Nome de dependência não encontrado no registro (opt-in --check-dependencies)LLM04
DEP002Nome de dependência a uma edição de distância de um pacote popular (opt-in)LLM04
DEP003Dependência com lançamento malicioso documentado ou CVE crítico — verificado offline em cada varredura, ciente de faixa de versão (postmark-mcp, mcp-remote CVE-2025-6514, …)LLM04 · MCP04
LLC001Segredo codificado em um config.yaml do proxy LiteLLMLLM02
LLC002api_base do proxy LiteLLM acessível sobre HTTP sem criptografiaLLM04
LLC003Configuração do proxy LiteLLM sem seção guardrails: (heurística, somente --paranoid)LLM03

secureai-scan explain <RULE_ID> fornece o passo a passo da exploração e um exemplo de código antes/depois para qualquer regra.

Arquitetura

Três superfícies de varredura independentes alimentam uma única lista de achados mesclada e deduplicada:``` ┌─────────────────────┐ *.ts / *.js ───▶ │ ts-morph AST rules │───┐ │ (import-resolved │ │ │ sinks + dataflow) │ │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ ┌──────────────┐ ┌─────────────────┐ *.py ───▶ │ tree-sitter AST + │───┼───▶ │ scan.ts │───▶ │ evidence filter │ │ local taint flow │ │ │ merge/dedupe│ │ → confidence │ └─────────────────────┘ │ │ + suppress │ │ → severity │ │ │ (// secure- │ │ → baseline diff │ .mcp.json, ┌─────────────────────┐ │ │ ai-ignore) │ │ → report │ SKILL.md ───▶ │ Config/bundle scan │──┘ └──────────────┘ └─────────────────┘ │ (off-disk, evasion- │ │ │ resistant) │ ▼ └─────────────────────┘ terminal · sarif · json · md · html

package.json, requirements.txt ─▶ dependency-guard.ts (advisories.ts, offline, version-aware)

Every AST rule only calls a function an "LLM call" if it resolves through real imports to a known SDK — never by name-matching alone. See [`docs/Architecture.md`](https://github.com/akanthed/secureai-scan/blob/main/docs/Architecture.md) for the full breakdown of each surface, and [`docs/DetectionEngine.md`](https://github.com/akanthed/secureai-scan/blob/main/docs/DetectionEngine.md) for how the evidence-tier contract works.

## Servidor MCP (use-o a partir do Claude)

O pacote inclui um servidor MCP que expõe `scan_repository`, `explain_rule`, `generate_bom` e `scan_untrusted_target` (busca e analisa uma skill ou servidor MCP antes de o Claude recomendar a instalação — o mesmo comportamento de busca-sem-execução dos comandos CLI `skill`/`mcp`):```json
{
  "mcpServers": {
    "secureai-scan": {
      "command": "node",
      "args": ["/path/to/secureai-scan/mcp-server/index.js"]
    }
  }
}

Claude Skill

Para utilizadores de Claude Code / Claude.ai, o skills/secureai-scan/SKILL.md ensina o Claude quando executar uma análise (ao rever código de IA/LLM, ou ao verificar um servidor MCP/Skill de Agente antes de o instalar) e como ler os resultados — sem necessidade de um processo separado, ao contrário do servidor MCP acima. Copie o diretório skills/secureai-scan/ para o seu .claude/skills/ para o utilizar.

Resistência a evasão

Em julho de 2026, duas investigações públicas demonstraram que os scanners de Skills de Agente são trivialmente contornados.

Cloak and Detonate (Ji, Xu, Li, Gao, Wei, Wang & Cheung — HKUST, arXiv:2607.02357) realizou um estudo adversarial contra nove scanners de skills publicados, utilizando 1.613 skills maliciosas recolhidas em ambiente real. Duas famílias de ataques, ambas preservando exatamente o payload:

  • Reify — reescreve os bytes que uma regra corresponde, enquanto o agente ainda remonta o original em tempo de execução. >80% de evasão na maioria dos scanners estáticos.
  • Disperse / empacotamento SFS — move o payload para fora do âmbito da regra: para um diretório que o scanner ignora, atrás de uma extensão renomeada, ou arquivado e codificado em .git/, com um SKILL.md de cobertura benigno que o reconstrói na primeira execução. ≥90% de evasão em todos os scanners testados, ≥96% na maioria. A taxa de deteção de um scanner híbrido caiu de ~99% para ~10%.

Separadamente, a Gecko Security (VentureBeat) distribuiu um payload num ficheiro *.test.ts. Todos os scanners públicos o ignoraram — mas o Jest e o Vitest detetam e executam automaticamente esses ficheiros no próximo npm test.

O SecureAI-Scan trata cada técnica publicada. Cada linha abaixo tem um teste correspondente em test/deobfuscate.test.js ou uma fixture em test-fixtures/vulnerable/skills/:

Técnica (nome do artigo)ExemploComo é tratada
Inserção de largura zeroIgn‍ore all pre‍vious…O texto é comparado com variantes sem caracteres invisíveis
Glifos confundíveisсurl (с cirílico)Dobragem de homóglifos para ASCII antes da correspondência
Inversão de maiúsculasEvAlTodos os padrões de conteúdo são insensíveis a maiúsculas/minúsculas
Divisão de variáveis'cu' + 'rl'Literais de string adjacentes são unidos antes da correspondência
Divisão por linhaeval(x)Quebras de linha intra-palavra unidas como variante extra
Extração por ficheiropayload num helper importadoTodo o pacote é analisado, não apenas SKILL.md
Relocalização de diretórioscripts/x.shbuild/x.shSem lista de exclusão de diretórios dentro de um pacote
Renomeação de extensãox.shx.txtOs ficheiros são analisados por conteúdo, não por extensão
Preenchimento de tamanhopreencher além do limite do scannerFicheiros sobredimensionados são lidos no início, nunca ignorados
Empacotamento SFSpayload em .git/skillpack.datQualquer ficheiro não-git sob o .git/ de um pacote é provado (SKL004)
Encenação em ficheiros de testepayload em *.test.tsA análise de pacotes deliberadamente não rebaixa caminhos de teste (SKL005)

Isto não enfraquece o contrato de precisão

A desofuscação é normalmente um risco de precisão — mais correspondências, mais ruído. Aqui a lógica é invertida: uma correspondência que só aparece após a desofuscação é promovida a provado, não rebaixada. Documentação comum não contém um unidor de largura zero dentro de "ignore previous instructions", nem um с cirílico dentro de curl. A ocultação é, por si só, evidência afirmativa de intenção.

A comparação é feita contra o conjunto de correspondências brutas, não apenas "a correspondência bruta existiu ou não" — caso contrário, um atacante poderia mascarar o sinal deixando uma frase inócua em texto claro.

As duas novas regras de pacote disparam apenas em conjunções, nunca numa palavra-chave isolada:

  • SKL004 requer um blob opaco e uma diretiva de desempacotamento que referencie esse blob pelo nome — um README que menciona tar -x ao lado de um ativo binário não relacionado não é suficiente. Arquivos reais (gzip/zip/png/pdf/wasm — verificados por magic bytes, não por extensão) nunca são "opacos" em primeiro lugar, independentemente de como são comprimidos.
  • SKL005 requer um sinal concreto de credencial — um caminho (~/.aws/credentials, não a palavra "token") ou enumeração em massa de variáveis de ambiente (os.environ.items(), não os.environ["API_KEY"]) — e egresso para um host não-local codificado, dentro de 25 linhas um do outro no mesmo ficheiro, ou uma obtenção remota que é executada após ser reatribuída através de uma ou mais renomeações. Um helper de publicação que lê ~/.npmrc numa função e chama um registo quarenta linhas depois permanece limpo, e ler uma variável de ambiente nomeada para uma chamada de API nunca é sinalizado — ambas as formas estão fixadas como fixtures seguras.

Validado contra dois corpora do mundo real, não apenas fixtures que escrevemos nós próprios: 0 descobertas em todos os 18 pacotes de skills reais em anthropics/skills e todos os 14 em vercel/ai, e 6/6 corretos no corpus de avaliação rotulado de cisco-ai-defense/skill-scanner (20 skills, cada uma com um veredito _expected.json) com zero falsos positivos em qualquer coisa rotulada como segura. Consulte Testes e benchmarking.

O que isto não é

Limitação honesta: a conclusão do artigo é que a detonação em tempo de execução supera a análise estática, e isso está correto. Um adversário adaptativo que conhece estas regras pode escrever uma transformação que elas não cobrem. O que muda aqui é o custo da evasão — as técnicas publicadas e atualmente em circulação deixam de funcionar, e a ofuscação necessária para as derrotar agora eleva ela própria a gravidade da descoberta. A análise estática é um filtro, não uma fronteira de segurança. Trate uma skill não confiável como código não confiável, independentemente do que qualquer scanner diga.

Garantia de confiança e lançamento

  • O CI é executado em Linux, Windows e macOS em todas as versões suportadas do Node.
  • CodeQL, auditoria de dependências de produção, OpenSSF Scorecard, Dependabot e a auto-análise bloqueante deste próprio scanner fornecem verificações independentes.
  • Cada publicação manual no npm invoca testes, limites mínimos de cobertura, o portão de regressão do repositório real revisto e inspeção do tarball através de prepublishOnly.
  • O GitHub Actions não recebe palavra-passe ou token do npm e não pode publicar o pacote.
  • Garantia de lançamento, governação de mantenedor único, comunicação de segurança e evidência de benchmark versionada são públicas.

Este é um projeto de mantenedor único, sem SLA contratual ou certificação independente. Os controlos acima reduzem o risco; não transformam uma análise estática em prova de segurança.

O contrato de precisão

Falsos positivos matam scanners. O motor de regras do SecureAI-Scan segue três regras rígidas:

  1. Os sinks são resolvidos através de imports. Se um identificador resolve para um módulo que não é um SDK de LLM, definitivamente não é uma chamada de LLM — independentemente do seu nome.
  2. A evidência é rotulada, nunca misturada. Um fluxo de dados rastreado e uma correspondência por proximidade de palavras não são a mesma coisa, por isso nunca partilham um nível.
  3. O corpus seguro bloqueia todos os lançamentos. test-fixtures/safe/ contém os padrões que costumavam causar falsos positivos (payloads de PII redigidos, clientes do Google Maps, chaves de API em variáveis de ambiente junto a clientes de LLM, registo de respostas comum, campos de metadados OAuth, chunks de respostas em streaming, texto de prompt de ficção/narrativa). Qualquer descoberta aí falha a suíte.

Testes e benchmarking

Três camadas, porque uma só não é suficiente para confiar nas afirmações de um scanner — precisão e recall são modos de falha diferentes, e ambos são verificados.

1. Corpus de fixtures — precisão + recall, executado em cada build.```bash npm test

[`test-fixtures/vulnerable/`](https://github.com/akanthed/secureai-scan/blob/main/test-fixtures/vulnerable) e [`test-fixtures/safe/`](https://github.com/akanthed/secureai-scan/blob/main/test-fixtures/safe) são analisados em conjunto: cada fixture vulnerável deve acionar a regra esperada com evidência `proven`/`likely` (recall), cada fixture seguro deve produzir **zero** achados `proven`/`likely` (precisão). Rápido e determinístico — mas apenas prova que o scanner se comporta em código escrito especificamente para testá-lo.

**2. Benchmark de regressão no mundo real — contra repositórios públicos que não escrevemos.**```bash
npm run regression                          # scan the full curated repo set
npm run regression -- --fresh               # re-clone everything first
npm run regression -- openai-node           # scan just one repo by name
npm run regression -- --update-baseline     # accept the current findings

scripts/regression-scan.js clona um conjunto curado e diversificado de repositórios públicos reais (OpenAI/Anthropic/Vercel AI SDKs, os servidores MCP oficiais e o TypeScript SDK, LlamaIndex, além de anthropics/skills e cisco-ai-defense/skill-scanner para cobertura de pacotes de skills — abrangendo TS e Python, código de exemplo de consumidores de SDK e código-fonte de autores de SDK) e escaneia cada um com o CLI compilado.

Ele sai com código não-zero em qualquer achado proven/likely que já não esteja em test/regression-baseline.json — um registro revisado manualmente de achados já lidos em relação à sua linha de origem. As impressões digitais são repo|rule|file, não números de linha, então mudanças comuns a montante não geram ruído. Uma nova impressão digital é uma afirmação que o scanner precisa justificar: se não for um problema genuíno, é um bug de regra, corrigido na causa raiz e travado como um novo fixture test-fixtures/safe/. Incluir na baseline um achado que você não leu anula todo o mecanismo.

A cobertura de pacotes de skills tem sua própria linha porque o corpus evals/ do cisco-ai-defense/skill-scanner é rotulado — cada um de seus 20 fixtures vem com um veredito _expected.json e fica sob um diretório literalmente chamado malicious/ ou safe/, então ele funciona também como uma verificação de recall, não apenas de precisão: 6/6 fixtures maliciosos no escopo disparam, 0 achados em qualquer coisa rotulada como safe, e 0 achados em todos os 18 pacotes reais em anthropics/skills e todos os 14 em vercel/ai. (As categorias restantes da Cisco — injeção de SQL, path traversal, exaustão de recursos, eval() genérico de um argumento de função, um payload deliberadamente dividido entre quatro arquivos — estão fora do escopo documentado de LLM/MCP/RAG ou além da análise de conjunção em arquivo único; veja a entrada do changelog 0.6.0 para o raciocínio específico de cada uma.)

Antes/depois histórico da execução que motivou as correções originais de precisão (achados no nível de evidência padrão, sem --paranoid):

RepoAntesDepoisO que estava errado
vercel/ai7731examples/, tests/ de nível superior e diretórios com hífen no estilo ecosystem-tests/ não eram reconhecidos como caminhos de menor confiança; chunks (uma variável comum de resposta em streaming) era tratado como evidência inequívoca de RAG
openai/openai-node470Mesma lacuna de detecção de caminho, aplicada aos próprios examples//ecosystem-tests/ do SDK
anthropics/anthropic-sdk-typescript20Mesma lacuna de detecção de caminho em um diretório tests/ de nível superior
modelcontextprotocol/typescript-sdk30Campos de metadados OAuth no estilo token_endpoint/tokenType sinalizados como segredos vazados
run-llama/llama_index1815Uma verificação em Python sinalizava qualquer campo description= contendo "system prompt" como envenenamento proven de ferramenta MCP, independentemente do contexto. Os 15 restantes são hits VEC001 nas definições genéricas de retriever da própria biblioteca — escanear o código-fonte de um SDK de banco vetorial, não código de aplicação, então um filtro não pode existir para ser verificado; um limite honesto e inerente, não um bug

Execução atual (2026-08-06) — evidência versionada está registrada em docs/benchmarks/v0.9.0.json:

RepoAchadosRegrasStatus
openai-node, anthropic-sdk-typescript, anthropic-sdk-python, modelcontextprotocol/typescript-sdk, modelcontextprotocol/servers0limpo
anthropics/skills (18 pacotes de skills reais)0limpo — verificação pura de precisão para SKL001–005
vercel/ai (5.691 arquivos)0era 40 (AI001, AI003, AI005, AI010, MCP002) antes da triagem — cada um revisado manualmente contra a fonte e confirmado como falso positivo, rastreado até 3 bugs independentes de causa raiz (veja abaixo), corrigido e re-confirmado limpo em um re-escaneamento completo
run-llama/llama_index46VEC001limite inerente, não um bug — as definições genéricas de retriever da própria biblioteca, onde nenhum filtro de tenant pode existir para ser encontrado
cisco-ai-defense/skill-scanner7SKL001, SKL002, SKL005todos em fixtures rotulados como malicious/ — 6/6 no escopo, 0 em qualquer coisa rotulada como safe/

A triagem do vercel/ai encontrou três bugs reais com causa raiz identificada — nenhum específico das regras de skills da v0.6.0, todos em lógica compartilhada usada em muitas regras:

  1. resolveLlmSink tratava qualquer chamada resolvida para um módulo de SDK de LLM como uma invocação de modelo, independentemente do nome do método — sinalizando isToolUIPart (um type guard que o pacote ai exporta ao lado de generateText) como uma chamada de LLM. Isso sozinho causou 3 dos 5 grupos de achados (AI001, AI003, AI010).
  2. DANGEROUS_CALLEES em AI005 inclui "query" para sinks no estilo injeção de SQL, mas "query" também é um verbo legítimo de invocação de LLM/agenteclaudeSdk.query({ prompt, options }), a chamada de modelo do próprio Claude Agent SDK, foi sinalizado como "saída de LLM passada para um sink perigoso" puramente por causa do nome de método compartilhado.
  3. REQUEST_SOURCES (duplicado de forma idêntica em MCP002, MCP010, VEC003) correspondia a um "params." simples — qualquer parâmetro de função convencionalmente chamado params, não necessariamente dados de requisição HTTP. Um validador de esquema de URL (assertOpenLinkParams(params: unknown)) foi sinalizado como "URL de servidor MCP de entrada do usuário".

Todos os três corrigidos na causa raiz (não no call site específico) e fixados como fixtures permanentes em test-fixtures/. Detalhes completos em CHANGELOG.md.

3. Validação vulnerável-vs-corrigido — prova recall, não apenas precisão.

As duas camadas acima apenas verificam que o scanner permanece silencioso em código seguro. As verificações de advisory do DEP003 são validadas no sentido oposto: fixe um pacote em uma versão documentada como vulnerável e confirme que ele é sinalizado, depois fixe-o na versão corrigida e confirme que não é.```bash node --test test/dependency-guard.test.js

covers: `[email protected]` (CVE-2025-6514, vulnerável) sinalizado / `[email protected]` (corrigido) limpo; `[email protected]` (antes do backdoor) limpo / `[email protected]` (depois — não existe patch legítimo para um pacote malicioso) ainda sinalizado; `llama-cpp-python==0.2.71` (CVE-2024-34359, do conjunto gerado por OSV) sinalizado / `==0.2.72` (corrigido) limpo, inclusive sob a normalização de nomes do PyPI (`llama_cpp_python`); e especificadores não fixados do tipo `langchain>=0.1.0` produzindo **zero** achados no relatório padrão. Construir este teste revelou uma lacuna real: o `DEP003` costumava corresponder avisos apenas pelo nome do pacote, sem nunca comparar de fato a versão declarada com o intervalo afetado do aviso — corrigido em [`src/scanner/semver.ts`](https://github.com/akanthed/secureai-scan/blob/main/src/scanner/semver.ts).

A ambiguidade é resolvida de forma diferente por tipo de aviso, deliberadamente. Um pacote **malicioso** dispara mesmo quando a versão declarada não pode ser resolvida — instalar um backdoor é irreversível, então ele falha em direção à sinalização. Uma **CVE** dispara em `proven` apenas quando a versão declarada é um pin exato comprovadamente dentro do intervalo afetado; versões não fixadas mas possivelmente afetadas caem para `heuristic` (somente com `--paranoid`). Aplicar a regra do tipo malicioso a um snapshot de CVE com 162 entradas colocaria um achado crítico em todo repositório que declara `langchain>=0.1.0` — ruído inacionável em escala.

## Roadmap

Consulte [`ROADMAP.md`](https://github.com/akanthed/secureai-scan/blob/main/ROADMAP.md) para saber o que foi lançado e o que está planejado. Ambos os mecanismos de linguagem são baseados em AST: ts-morph para TypeScript/JavaScript e Tree-sitter para Python. Imports, chamadas, atribuições, decoradores, escopos, argumentos nomeados, campos de dicionário e strings em Python são nós de sintaxe; o código-alvo nunca é importado ou executado, e nenhum interpretador Python é necessário. A lacuna restante do Python é a profundidade limitada de taint entre funções/arquivos, não a análise. O desempenho da varredura e os limites conhecidos estão documentados em [`docs/Performance.md`](https://github.com/akanthed/secureai-scan/blob/main/docs/Performance.md).

## Contribuindo

Contribuições são bem-vindas — consulte [`CONTRIBUTING.md`](https://github.com/akanthed/secureai-scan/blob/main/CONTRIBUTING.md) para o fluxo de trabalho, e [`docs/WritingRules.md`](https://github.com/akanthed/secureai-scan/blob/main/docs/WritingRules.md) / [`docs/RuleDevelopment.md`](https://github.com/akanthed/secureai-scan/blob/main/docs/RuleDevelopment.md) para saber como adicionar uma regra de detecção que atenda ao padrão de precisão acima. Cada nova regra precisa de um fixture tanto em [`test-fixtures/vulnerable/`](https://github.com/akanthed/secureai-scan/blob/main/test-fixtures/vulnerable) quanto em [`test-fixtures/safe/`](https://github.com/akanthed/secureai-scan/blob/main/test-fixtures/safe), uma entrada em `src/scanner/catalog.ts` e um caso em `test/corpus.test.js` — `npm test` aplica os três.

## Licença

MIT © Akshay Kanthed

Categorias