codatrace: confirmação em execução

O codatrace roda dentro da aplicação e mostra quais findings do codafort foram alcançados por dado não confiável durante a execução.

Ele não procura vulnerabilidade nova: confirma ou deixa de confirmar o que a análise do código apontou. Essa confirmação pode entrar na declaração contra-assinada (o artefato coda-attestation/1 que o attest create emite).

Fronteira ética. O agente observa e não altera: não injeta payload, não muda resultado de chamada, não bloqueia requisição, não termina processo. Não é WAF nem sandbox. Quando o agente falha, ele deixa de observar: no boot, desliga-se e diz por quê numa linha de stderr; durante a execução, para de enviar eventos.
Licença. No binário público, o coletor do codatrace exige licença Pro, Verified ou Platform (o Vibe não inclui runtime; sem ela, recusa e diz como ativar). Só o schema é livre. O agente carregado na aplicação nunca é bloqueado: a falta de licença não derruba a aplicação. Ver planos.

Os três vereditos

VereditoSignificaO que fazer
confirmed-at-runtimeum evento sem sanitizador correlacionou com o finding: o fluxo aconteceu, sem defesaprioridade máxima; é o que a declaração contra-assinada pode afirmar
sanitized-at-runtimeo sink foi alcançado com um sanitizador da política, da categoria certa, no caminhoexiste defesa ali
unreachednenhum fluxo com dado de requisição foi observado naquele pontonunca leia como "seguro": é "não medido"

unreached tem três causas que o coletor não distingue: rota não exercitada, sink chamado com dado interno ou categoria que o agente não observa. Por isso a evidência diz literalmente não medido, nunca seguro.

Instalar

O binário vem com os agentes de Python, Node e JVM no mesmo pacote. Não há pacote PyPI nem npm: agente e coletor precisam ser da mesma versão. Baixe em Download ou instale a fórmula codatrace.rb publicada como asset do release.

codatrace install python     # materializa o agente e imprime como carregá-lo
codatrace install node
codatrace install jvm        # fora da matriz (linux-arm64/Windows): imprime a linha de cc para recompilar

O fluxo

# 1. A política diz o que o agente observa; ela vem da taxonomia do codafort.
#    O pacote do release traz a política gerada do mesmo commit:
codatrace policy --output policy.json

# 2. Suba a aplicação com o agente (`codatrace install <runtime>` imprime as linhas exatas).
export CODATRACE_POLICY=policy.json CODATRACE_EVENTS=events.jsonl
node --import .codatrace/agents/node/codatrace_agent.mjs app.js    # Node: o --import garante a ordem em ESM
#    Python: no início do processo `import codatrace_agent; codatrace_agent.install()` e
#    `app = codatrace_agent.wsgi(app)` (Django; no Flask, `app.wsgi_app`) ou `codatrace_agent.asgi(app)`.
#    JVM: java -agentpath:.codatrace/agents/jvm/libcodatrace.so=events.jsonl …

# 3. Exercite a aplicação (testes de integração, staging, tráfego real de homologação).

# 4. A análise de código, para cruzar:
codafort engine analyze --source . --output static.json

# 5. Colete e correlacione por arquivo, linha e categoria:
codatrace collect --events events.jsonl --static static.json --policy-file policy.json --output laudo.json
SOCK="$(mktemp -d)/codatrace.sock"   # multi-worker: diretório privado, CODATRACE_EVENTS="$SOCK" nos workers
codatrace collect --socket "$SOCK" --timeout 600 --static static.json --policy-file policy.json --output laudo.json

# 6. A contribuição de evidência para a declaração contra-assinada (coda-evidence/1, modality: iast):
codatrace coverage > coverage.json
codatrace evidence --report laudo.json --coverage coverage.json > iast-ev.json
codafort attest create --evidence iast-ev.json

Com --socket, os agentes só se conectam a um socket do mesmo usuário. --timeout é a janela da coleta (padrão 30 s); o laudo diz quantas conexões o prazo cortou (socket_connections_cut_by_deadline). Sem --socket, o coletor lê de --events ou do stdin, que é o caminho para CI sem aplicação viva. Quem consegue escrever no canal de eventos consegue alterar o que será assinado.

codatrace evidence --verdicts publica os pares (finding, veredito) resumidos no verdict_digest, só com id opaco e verdict, nunca arquivo ou linha. Sem --coverage, a cobertura do agente fica ausente na evidência: "não medido", nunca zero.

O que ele não vê

  • O agente confere se algum valor da requisição aparece dentro do argumento do sink. Valor transformado antes do sink (hash, compressão, codificação) passa sem confirmação: isso pode esconder um fluxo, mas não gera falso positivo. Valor com menos de 3 caracteres é ignorado, e concatenação parcial escapa.
  • A cobertura de sinks é parcial. codatrace coverage lista o que cada agente observa.
  • Parte da taxonomia não tem evento a observar em execução: regras numéricas e estruturais (índice, divisão, limite de laço, alocação, overflow, ReDoS) e, por enquanto, categorias como log, CORS, NoSQL, XPath, template e header splitting. Essas ficam unreached.
  • Python e Node: a fonte automática lê só a query string; para o corpo, chame begin_request no seu middleware.
  • Python: driver de banco cujo connect não é atributo gravável fica sem cobertura.
  • Node: função exportada solta de pacote ESM não é observada; método em protótipo é.
  • JVM: sem cobertura de SQL nem de XSS. Frames de framework (Spring, Tomcat, Jackson…) não contam como código da aplicação. O sanitizador é observado na entrada do método.
  • Teto de emissão: CODATRACE_MAX_EVENTS (padrão 10 000). O descarte aparece no laudo em events_over_cap.

Como o codatrace só reporta fluxo observado, um falso positivo é bug.