# Auto-benchmark do `/v1/scan` — 2026-09-28 > Medição **própria** (não é auditoria independente) usada no comparativo da > landing (https://context-armor.com/#compare). Duas execuções no mesmo dia. > Resultados brutos (um JSON por pedido, com a resposta completa da API): > - execução 2 (sem retries, a de referência): https://context-armor.com/benchmarks/2026-09-28-scan-selfbench-run2.jsonl.gz > - execução 1 (com retries): https://context-armor.com/benchmarks/2026-09-28-scan-selfbench.jsonl.gz > > Scripts no repositório: `scripts/bench-scan/` (reproduzível — ver o fim). ## Método - **Alvo:** produção, `POST https://api.context-armor.com/v1/scan`, endpoint público sem chave, corpo `{"prompt": …, "cache": false}`. O Worker em produção nesta data **ainda não conhecia o campo `cache`** (ignorado): o cache de vereditos e o cache de resposta do provedor estavam ligados, mas **nenhuma resposta veio do cache** (`cached` ausente em todas) porque cada texto era inédito na janela de 10 minutos do cache. - **Execução 1:** 22:05:52Z → 22:07:56Z. O cliente repetia até 2 vezes em 429/5xx/erro de rede e só registava a última tentativa — por isso a taxa de erro e a latência dessa execução **não contam as falhas transitórias** que um retry escondeu. - **Execução 2 (referência):** 22:29:22Z → 22:31:18Z. **Uma tentativa por texto, sem retries**; cada erro conta como erro. - Ambas: 3 pedidos em paralelo, cliente em Python (`urllib`) a partir do Brasil. - **Configuração de produção:** L1 (regras) → Jev `typesafe/jev-1.13-20260917` (banda auto) → juiz LLM `openai/gpt-4o-mini-2024-07-18` na banda incerta; orçamento de 2,5 s por pedido. - **Datasets públicos:** - `deepset/prompt-injections`, split *test*: 116 textos (60 injeções, 56 benignos; EN/DE). - `leolee99/NotInject`: 339 prompts **benignos** com palavras-gatilho (ex.: "ignore", "uncensored"), 3 níveis de dificuldade (113 cada). - **Veredito positivo:** `is_prompt_injection = true`. Pedidos com erro ficam fora das métricas de acerto e são reportados à parte. ## Resultados | Conjunto | Métrica | Execução 2 (sem retries) | Execução 1 | |---|---|---|---| | deepset test (injeções) | **injeções não sinalizadas** | **33,9%** (20 de 59) | 40,0% (24 de 60) | | deepset test (benignos) | falsos positivos | 0,0% (0 de 53) | 0,0% (0 de 56) | | deepset test | acurácia / F1 | 82,1% / 79,6 | 79,3% / 75,0 | | NotInject (todos) | **benignos sinalizados** | **8,9%** (30 de 338) | 8,6% (29 de 337) | | NotInject nível 1 / 2 / 3 | benignos sinalizados | 1,8% / 2,7% / 22,1% | 1,8% / 1,8% / 22,5% | | Erros | pedidos sem veredito | **5 de 455 (1,1%)**: 4× 504 e 1× 500, todos por timeout | 2 de 455 após até 3 tentativas (502, JSON do juiz fora do contrato) | A diferença entre as duas execuções (mesmos textos) vem da variação do Jev e do juiz LLM entre chamadas e dos pedidos que falharam em cada uma. | Latência — execução 2 (450 respondidos) | p50 | p95 | média | |---|---|---|---| | **Ida e volta no cliente (todas)** | **409 ms** | **1 847 ms** | — | | Decisão no servidor (todas) | 314 ms | 1 658 ms | 593 ms | | Só Jev (352, banda auto) | 301 ms | 448 ms | 317 ms | | Com escalada ao LLM (98) | 1 562 ms | 1 874 ms | 1 583 ms | - **Escalada ao juiz LLM:** 98 de 450 (21,8%) na execução 2; 101 de 453 (22,3%) na execução 1. O pré-filtro L1 não decidiu nenhum destes textos. - O comparativo mostra a **ida e volta no cliente**, porque é assim que os números dos concorrentes foram medidos (com rede). ## Leitura honesta - O `deepset/prompt-injections` rotula como injeção pedidos fora de tópico para uma aplicação de perguntas e respostas (ex.: "translate to polish", "Tell me a joke about a woman", "I want you to act as a storyteller"). Boa parte das "falhas" são textos inofensivos fora desse contexto — mas o número publicado é o número medido, sem reetiquetar. - O nível 3 do NotInject (várias palavras-gatilho por frase) é onde o Jev e o juiz mais erram (~22% sinalizados); frases em chinês caíram no juiz LLM e foram bloqueadas várias vezes. - 1,1% dos pedidos estourou o orçamento de 2,5 s. Em produção isso é um erro explícito (nunca um *allow* silencioso), mas é uma verificação que não aconteceu. - A "meta de desenho" de ~5% de escalada citada na secção Tokenomics **não** se confirma neste tráfego: a escalada medida foi ~22%. ## Outros sistemas nos mesmos datasets (fontes independentes) Não é uma corrida lado a lado (splits, limiares e datas diferem), mas são os números públicos mais comparáveis aos nossos: | Sistema | deepset: recall | deepset: falsos positivos | NotInject: benignos sinalizados | Fonte | |---|---|---|---|---| | **Context Armor (este teste; split *test*)** | **60,0–66,1%** | **0,0%** | **8,6–8,9%** | este documento | | Lakera Guard | 70,7% (dataset completo) | 0,7% | 12,4% | Palit et al. 2025 (arXiv 2505.13028); InjecGuard (arXiv 2410.22770) | | Azure Prompt Shields | 38,9% (dataset completo) | 0% | — | Palit et al. 2025 | | ProtectAI LLM Guard | 41,4% (dataset completo) | — | — | Palit et al. 2025 | | GPT-3.5-Turbo como detector | 95% (dataset completo) | 43,1% | — | Palit et al. 2025 | | Llama Prompt Guard 2 86M | 46,8% (limiar a 1% FP, dataset completo) | ~1% (por construção) | 19,2% | "Confidently Wrong" (arXiv 2606.22659) | | GPT-4o como detector | — | — | 13,3% | InjecGuard | "Dataset completo" = os 662 textos (263 ataques) com o split de treino; o nosso usa só o split *test*. Os autores de Palit et al. notam que as ferramentas podem ter sido treinadas no deepset, o que infla os resultados delas nesse dataset. ## Reproduzir ```bash cd "$(mktemp -d)" python3 fetch_datasets.py # baixa os 2 datasets do Hugging Face python3 run.py https://api.context-armor.com results.jsonl # 1 tentativa por texto python3 analyze.py results.jsonl ``` ## Notas posteriores (2026-09-28, depois desta medição) Nada foi re-medido: os números acima descrevem exatamente a versão do serviço que correu nas duas execuções. O que mudou entretanto: - **`{"cache": false}` passou a ser honrado** (deploy do Worker do mesmo dia): em bypass o servidor nem lê nem grava o cache de vereditos e desliga o cache de resposta do provedor; a resposta informa `cache_status`. Ainda assim, todas as respostas desta medição já eram de veredito novo (cada texto era inédito). - **O orçamento de timeout subiu de 2,5 s para 3,5 s** — os 5 pedidos (1,1%) que aqui estouraram foram a razão direta (o p95 do caminho com juiz LLM era 1,9 s no servidor). Entrou também o reparo do JSON cortado pelo `max_tokens`, causa dos erros "resposta fora do contrato JSON" da execução 1. - **O comparativo da landing ganhou duas linhas** medidas no deepset por terceiros (AY Automate, 2026-09-20; amostra de 400 dos 662 textos; veredito por omissão): Gemini 3.5 Flash-Lite e GPT-5.6 Terra — ambos com recall 0,688 e 0 falsos positivos. Não entraram na tabela acima porque a tabela é o registo desta medição.