@orkastery/cli 0.5.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +37 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
- package/adapters/openclaw/README.md +81 -9
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +123 -9
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +3 -1
- package/dist/adapters/grok-events.js +227 -0
- package/dist/adapters/grok-mcp-servidor.js +612 -0
- package/dist/adapters/grok-mcp.js +178 -0
- package/dist/adapters/grok.js +686 -0
- package/dist/agendador-cpu.js +92 -0
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +51 -46
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +94 -40
- package/dist/branch-de-estado.js +23 -10
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +2 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +528 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +238 -0
- package/dist/ci.js +248 -45
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +47 -39
- package/dist/claims.js +10 -9
- package/dist/company-brain-client.js +10 -3
- package/dist/company-brain-migration.js +11 -5
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +25 -8
- package/dist/conducao.js +89 -29
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +111 -87
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +89 -89
- package/dist/doctor-forja.js +343 -0
- package/dist/doctor-pulse-cron.js +113 -1
- package/dist/doctor.js +164 -6
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +154 -54
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +21 -18
- package/dist/evalrunner.js +35 -32
- package/dist/fabrica-batida.js +34 -21
- package/dist/fabrica-estado.js +33 -21
- package/dist/fix.js +21 -19
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +123 -80
- package/dist/handoff.js +23 -13
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +51 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +44 -1
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +34 -31
- package/dist/horario.js +20 -1
- package/dist/hosts.js +104 -134
- package/dist/index.js +864 -554
- package/dist/indice-vetorial.js +14 -12
- package/dist/init.js +11 -2
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +123 -69
- package/dist/intelligence-graph-query.js +37 -22
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +31 -1
- package/dist/licoes.js +12 -11
- package/dist/locale-accounts.js +228 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +86 -10
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +288 -0
- package/dist/locale-gerados.js +5 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +83 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +140 -2
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +183 -6
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +177 -66
- package/dist/locale-thread.js +149 -5
- package/dist/locale-verify.js +80 -4
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +553 -9
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +293 -12
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +10 -5
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +10 -2
- package/dist/master.js +118 -41
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-install.js +90 -15
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +116 -22
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +68 -24
- package/dist/mcp-transportes.js +17 -0
- package/dist/memoria.js +63 -58
- package/dist/merge-da-entrega.js +85 -0
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +17 -18
- package/dist/network-roadmap.js +94 -54
- package/dist/noctum-aceite.js +929 -0
- package/dist/noctum-arco.js +540 -33
- package/dist/noctum-capacidade.js +3 -3
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +539 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1217 -0
- package/dist/noctum-envelope.js +253 -17
- package/dist/noctum-execucao.js +100 -24
- package/dist/noctum-fechamento.js +416 -0
- package/dist/noctum-fila.js +49 -10
- package/dist/noctum-guarda.js +333 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +387 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +390 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +594 -0
- package/dist/noctum-rede.js +102 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +861 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-retomada-rede.js +71 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +679 -0
- package/dist/ocupacao.js +3 -1
- package/dist/onboarding.js +16 -5
- package/dist/orkmind.js +39 -23
- package/dist/orquestracao.js +31 -35
- package/dist/parado-no-condutor.js +160 -139
- package/dist/phase.js +96 -42
- package/dist/policies.js +33 -0
- package/dist/postura-local.js +11 -6
- package/dist/preflight.js +2 -1
- package/dist/procedencia.js +9 -14
- package/dist/projeto-alvo.js +59 -20
- package/dist/prompts.js +136 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +143 -27
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +136 -3
- package/dist/ratelimit.js +13 -4
- package/dist/recall.js +14 -13
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +63 -45
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +326 -78
- package/dist/roadmap-reservas.js +32 -32
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +279 -85
- package/dist/runtime-escada.js +429 -0
- package/dist/runtime-profiles.js +130 -63
- package/dist/runtimes.js +42 -5
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +366 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +196 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +19 -2
- package/dist/session-watcher-claude.js +74 -19
- package/dist/session-watcher-grok.js +425 -0
- package/dist/session-watcher.js +174 -13
- package/dist/sessoes-contas.js +42 -5
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +67 -66
- package/dist/ship-publicar.js +263 -92
- package/dist/ship.js +160 -17
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +9 -9
- package/dist/thread.js +121 -18
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +5 -2
- package/dist/varredura-acoes.js +500 -0
- package/dist/verify.js +491 -32
- package/dist/worktree-local.js +12 -10
- package/dist/worktree.js +81 -85
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +10 -5
- package/references/security-checklist.md +3 -3
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.actionlint = actionlint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** actionlint JSON: paths are relative to the repository root (it runs from there). The snippet is its first source line (the rest is the caret ruler, which moves with the column). */
|
|
6
|
+
function actionlint(output, ctx) {
|
|
7
|
+
const list = (0, util_1.parseReport)('actionlint', output);
|
|
8
|
+
return list.map(e => ({
|
|
9
|
+
tool: 'actionlint', rule: `actionlint/${e.kind ?? 'error'}`, category: 'workflow', severity: (0, util_1.mapSeverity)('actionlint', 'any'),
|
|
10
|
+
file: (0, util_1.repoPath)(e.filepath, ctx), line: e.line, message: e.message ?? '', snippet: (e.snippet ?? e.message ?? '').split('\n')[0],
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eslint = eslint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** ESLint JSON: `filePath` is absolute inside the container. A message without a rule is a parse error. */
|
|
6
|
+
function eslint(output, ctx) {
|
|
7
|
+
const files = (0, util_1.parseReport)('eslint', output);
|
|
8
|
+
return files.flatMap(f => (0, util_1.asArray)(f.messages).map(m => ({
|
|
9
|
+
tool: 'eslint', rule: m.ruleId ?? 'parse-error', category: 'quality', severity: (0, util_1.mapSeverity)('eslint', m.severity), stack: 'js',
|
|
10
|
+
file: (0, util_1.repoPath)(f.filePath, ctx), line: m.line, message: m.message ?? '', snippet: m.message ?? '',
|
|
11
|
+
})));
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitleaks = gitleaks;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** The secret value never leaves this function: the snippet is its sha256, and Match/Secret/commit data are dropped. */
|
|
6
|
+
function gitleaks(output, ctx) {
|
|
7
|
+
const leaks = (0, util_1.parseReport)('gitleaks', output);
|
|
8
|
+
return leaks.map(l => ({
|
|
9
|
+
tool: 'gitleaks', rule: l.RuleID ?? 'unknown', category: 'secret', severity: (0, util_1.mapSeverity)('gitleaks', 'any'),
|
|
10
|
+
file: (0, util_1.repoPath)(l.File ?? '', ctx), line: l.StartLine, message: l.Description ?? l.RuleID ?? 'secret',
|
|
11
|
+
snippet: (0, util_1.sha256)(l.Secret ?? l.Match ?? ''),
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.golangciLint = golangciLint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** golangci-lint JSON: runs inside the stack directory, so `Pos.Filename` is relative to it (or `../src/..` from the root mount). */
|
|
6
|
+
function golangciLint(output, ctx) {
|
|
7
|
+
const report = (0, util_1.parseReport)('golangci-lint', output);
|
|
8
|
+
return (0, util_1.asArray)(report.Issues).map(i => ({
|
|
9
|
+
tool: 'golangci-lint', rule: i.FromLinter ?? 'unknown', category: 'quality', severity: (0, util_1.mapSeverity)('golangci-lint', i.FromLinter), stack: 'go',
|
|
10
|
+
file: (0, util_1.repoPath)(i.Pos?.Filename ?? '', ctx, 'stack'), line: i.Pos?.Line, message: i.Text ?? '',
|
|
11
|
+
snippet: (0, util_1.asArray)(i.SourceLines).join('\n') || (i.Text ?? ''),
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.govulncheck = govulncheck;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/**
|
|
6
|
+
* govulncheck `-format json` is a stream. One finding per advisory and vulnerable module; `reachable` is true when
|
|
7
|
+
* some trace of it has a function frame in the user's own module (the first SBOM module, the one without version).
|
|
8
|
+
*/
|
|
9
|
+
function govulncheck(output, ctx) {
|
|
10
|
+
const messages = (0, util_1.parseReport)('govulncheck', output);
|
|
11
|
+
const main = messages.find(m => m.SBOM)?.SBOM?.modules?.[0]?.path;
|
|
12
|
+
const summaries = new Map();
|
|
13
|
+
for (const m of messages)
|
|
14
|
+
if (m.osv)
|
|
15
|
+
summaries.set(m.osv.id, m.osv.summary ?? m.osv.id);
|
|
16
|
+
const byKey = new Map();
|
|
17
|
+
for (const m of messages) {
|
|
18
|
+
if (!m.finding)
|
|
19
|
+
continue;
|
|
20
|
+
const trace = (0, util_1.asArray)(m.finding.trace);
|
|
21
|
+
const module = trace[0]?.module ?? 'unknown';
|
|
22
|
+
const calledFromMain = main !== undefined && trace.some(fr => fr.module === main && fr.function !== undefined);
|
|
23
|
+
const key = `${m.finding.osv}|${module}`;
|
|
24
|
+
const known = byKey.get(key);
|
|
25
|
+
if (known) {
|
|
26
|
+
if (calledFromMain)
|
|
27
|
+
known.reachable = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
byKey.set(key, {
|
|
31
|
+
tool: 'govulncheck', rule: m.finding.osv, category: 'dependency', severity: (0, util_1.mapSeverity)('govulncheck', 'any'), stack: 'go',
|
|
32
|
+
file: (0, util_1.stackFile)('go.mod', ctx), message: summaries.get(m.finding.osv) ?? m.finding.osv, snippet: module, reachable: calledFromMain,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return [...byKey.values()];
|
|
36
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NORMALIZERS = exports.partialOf = void 0;
|
|
4
|
+
const actionlint_1 = require("./actionlint");
|
|
5
|
+
const eslint_1 = require("./eslint");
|
|
6
|
+
const gitleaks_1 = require("./gitleaks");
|
|
7
|
+
const golangci_lint_1 = require("./golangci-lint");
|
|
8
|
+
const govulncheck_1 = require("./govulncheck");
|
|
9
|
+
const npm_audit_1 = require("./npm-audit");
|
|
10
|
+
const osv_scanner_1 = require("./osv-scanner");
|
|
11
|
+
const oxlint_1 = require("./oxlint");
|
|
12
|
+
const pip_audit_1 = require("./pip-audit");
|
|
13
|
+
const ruff_1 = require("./ruff");
|
|
14
|
+
const semgrep_1 = require("./semgrep");
|
|
15
|
+
const trivy_1 = require("./trivy");
|
|
16
|
+
const zizmor_1 = require("./zizmor");
|
|
17
|
+
var util_1 = require("./util");
|
|
18
|
+
Object.defineProperty(exports, "partialOf", { enumerable: true, get: function () { return util_1.partialOf; } });
|
|
19
|
+
/** One normalizer per catalog tool (key = catalog name). Output that breaks the tool's `expect` contract throws `security-scan.parse`. */
|
|
20
|
+
exports.NORMALIZERS = {
|
|
21
|
+
gitleaks: gitleaks_1.gitleaks, semgrep: semgrep_1.semgrep, 'trivy-vuln': trivy_1.trivyVuln, 'trivy-config': trivy_1.trivyConfig, 'trivy-license': trivy_1.trivyLicense,
|
|
22
|
+
'npm-audit': npm_audit_1.npmAudit, 'pip-audit': pip_audit_1.pipAudit, govulncheck: govulncheck_1.govulncheck, zizmor: zizmor_1.zizmor, actionlint: actionlint_1.actionlint, eslint: eslint_1.eslint, ruff: ruff_1.ruff, 'golangci-lint': golangci_lint_1.golangciLint,
|
|
23
|
+
// RM-072 (D13): as ferramentas do catalogo so do Agile (tools-agil.json), atras de flag.
|
|
24
|
+
'osv-scanner': osv_scanner_1.osvScanner, oxlint: oxlint_1.oxlint,
|
|
25
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.npmAudit = npmAudit;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/**
|
|
6
|
+
* npm audit v2: one finding per advisory (the `via` objects), deduplicated per package. A `via` that is a string only
|
|
7
|
+
* says the package is affected through another one, whose own entry carries the advisory. The report names no file,
|
|
8
|
+
* so the finding is on the stack's `package-lock.json` (the audit runs with `--package-lock-only`).
|
|
9
|
+
*/
|
|
10
|
+
function npmAudit(output, ctx) {
|
|
11
|
+
const report = (0, util_1.parseReport)('npm-audit', output);
|
|
12
|
+
const seen = new Set();
|
|
13
|
+
const out = [];
|
|
14
|
+
for (const [pkg, v] of Object.entries(report.vulnerabilities)) {
|
|
15
|
+
for (const via of v.via ?? []) {
|
|
16
|
+
if (typeof via === 'string')
|
|
17
|
+
continue;
|
|
18
|
+
const rule = /GHSA-[0-9a-z-]+/i.exec(via.url ?? '')?.[0] ?? `npm:${via.source ?? via.title ?? 'unknown'}`;
|
|
19
|
+
const key = `${pkg}|${rule}`;
|
|
20
|
+
if (seen.has(key))
|
|
21
|
+
continue;
|
|
22
|
+
seen.add(key);
|
|
23
|
+
out.push({
|
|
24
|
+
tool: 'npm-audit', rule, category: 'dependency', severity: (0, util_1.mapSeverity)('npm-audit', via.severity), stack: 'js',
|
|
25
|
+
file: (0, util_1.stackFile)('package-lock.json', ctx), message: via.title ?? rule, snippet: via.name ?? pkg,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.osvScanner = osvScanner;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** A pontuacao CVSS do grupo em severidade (as faixas do CVSS 3); sem ela, a do advisory; sem nada, o padrao. */
|
|
6
|
+
function severidade(grupo, vulns) {
|
|
7
|
+
const nota = Number(grupo.max_severity);
|
|
8
|
+
if (grupo.max_severity && Number.isFinite(nota) && nota > 0)
|
|
9
|
+
return nota >= 9 ? 'critical' : nota >= 7 ? 'high' : nota >= 4 ? 'medium' : 'low';
|
|
10
|
+
return (0, util_1.mapSeverity)('osv-scanner', vulns.map(v => v.database_specific?.severity).find(Boolean));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* RM-072 (D13): osv-scanner v2 (`scan source --format json`), so no Agile Check e atras de `check.agile.osv_scanner`. Um
|
|
14
|
+
* achado por grupo de aliases (o mesmo problema com id do GHSA, do PYSEC ou do Go vira um so), com o primeiro id do
|
|
15
|
+
* grupo como regra e o pacote como trecho, no lockfile que o resultado nomeia.
|
|
16
|
+
*/
|
|
17
|
+
function osvScanner(output, ctx) {
|
|
18
|
+
const report = (0, util_1.parseReport)('osv-scanner', output);
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const r of (0, util_1.asArray)(report.results)) {
|
|
21
|
+
for (const p of (0, util_1.asArray)(r.packages)) {
|
|
22
|
+
const porId = new Map((0, util_1.asArray)(p.vulnerabilities).map(v => [v.id, v]));
|
|
23
|
+
const grupos = (0, util_1.asArray)(p.groups).length ? (0, util_1.asArray)(p.groups) : (0, util_1.asArray)(p.vulnerabilities).map(v => ({ ids: [v.id] }));
|
|
24
|
+
for (const g of grupos) {
|
|
25
|
+
const vulns = g.ids.map(id => porId.get(id)).filter((v) => !!v);
|
|
26
|
+
out.push({ tool: 'osv-scanner', rule: g.ids[0], category: 'dependency', severity: severidade(g, vulns),
|
|
27
|
+
file: (0, util_1.repoPath)(r.source.path, ctx), message: vulns.find(v => v.summary)?.summary ?? g.ids[0], snippet: p.package.name });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.oxlint = oxlint;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const util_1 = require("./util");
|
|
39
|
+
/**
|
|
40
|
+
* RM-072 (D13): oxlint `--format json`, so no Agile Check e atras de `check.agile.oxlint`, como primeiro passe antes do
|
|
41
|
+
* `eslint` (nao tira regra dele). O `filename` e relativo ao diretorio da stack, onde o wrapper roda; a regra e o
|
|
42
|
+
* `code` (`eslint(no-eval)`, `unicorn(...)`), e o trecho e a mensagem, como no `eslint`.
|
|
43
|
+
*/
|
|
44
|
+
function oxlint(output, ctx) {
|
|
45
|
+
const report = (0, util_1.parseReport)('oxlint', output);
|
|
46
|
+
return (0, util_1.asArray)(report.diagnostics).map(d => ({
|
|
47
|
+
tool: 'oxlint', rule: d.code ?? 'oxlint', category: 'quality', severity: (0, util_1.mapSeverity)('oxlint', d.severity), stack: 'js',
|
|
48
|
+
file: path.posix.normalize(path.posix.join(ctx.stackDir, d.filename ?? '')), line: (0, util_1.asArray)(d.labels)[0]?.span?.line,
|
|
49
|
+
message: d.message ?? '', snippet: d.message ?? '',
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pipAudit = pipAudit;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/**
|
|
6
|
+
* pip-audit gives no severity and no file. The catalog severityMap is `{"*": "high"}` (as govulncheck's): the safe side
|
|
7
|
+
* is to let a known vulnerable dependency reach the loop, never to hide it as medium.
|
|
8
|
+
* The file is the stack's `requirements.txt`, the only manifest the catalog command audits.
|
|
9
|
+
*/
|
|
10
|
+
function pipAudit(output, ctx) {
|
|
11
|
+
const report = (0, util_1.parseReport)('pip-audit', output);
|
|
12
|
+
return (0, util_1.asArray)(report.dependencies).flatMap(d => (0, util_1.asArray)(d.vulns).map(v => ({
|
|
13
|
+
tool: 'pip-audit', rule: v.id, category: 'dependency', severity: (0, util_1.mapSeverity)('pip-audit', 'any'), stack: 'python',
|
|
14
|
+
file: (0, util_1.stackFile)('requirements.txt', ctx), message: v.description?.split('\n')[0] ?? v.id, snippet: d.name,
|
|
15
|
+
})));
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ruff = ruff;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** Ruff JSON: `filename` is absolute inside the container. */
|
|
6
|
+
function ruff(output, ctx) {
|
|
7
|
+
const list = (0, util_1.parseReport)('ruff', output);
|
|
8
|
+
return list.map(d => ({
|
|
9
|
+
tool: 'ruff', rule: d.code ?? 'syntax-error', category: 'quality', severity: (0, util_1.mapSeverity)('ruff', 'any'), stack: 'python',
|
|
10
|
+
file: (0, util_1.repoPath)(d.filename, ctx), line: d.location?.row, message: d.message ?? '', snippet: d.message ?? '',
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.semgrep = semgrep;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/**
|
|
6
|
+
* Semgrep JSON. `extra.lines` needs a login in the OSS CLI, so the snippet is the text bound to the rule's
|
|
7
|
+
* metavariables when there are any, else the rule message: both survive a line shift. Paths are relative to the
|
|
8
|
+
* directory Semgrep ran from, the repository root.
|
|
9
|
+
*/
|
|
10
|
+
function semgrep(output, ctx) {
|
|
11
|
+
const report = (0, util_1.parseReport)('semgrep', output);
|
|
12
|
+
return (0, util_1.asArray)(report.results).map(r => {
|
|
13
|
+
const bound = Object.values(r.extra.metavars ?? {}).map(m => m.abstract_content ?? '').join(' ').trim();
|
|
14
|
+
const message = r.extra.message ?? r.check_id;
|
|
15
|
+
return {
|
|
16
|
+
tool: 'semgrep', rule: r.check_id, category: 'sast', severity: (0, util_1.mapSeverity)('semgrep', r.extra.severity),
|
|
17
|
+
file: (0, util_1.repoPath)(r.path, ctx), line: r.start?.line, message, snippet: bound || message,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trivyVuln = trivyVuln;
|
|
4
|
+
exports.trivyConfig = trivyConfig;
|
|
5
|
+
exports.trivyLicense = trivyLicense;
|
|
6
|
+
const util_1 = require("./util");
|
|
7
|
+
const results = (tool, output) => (0, util_1.asArray)((0, util_1.parseReport)(tool, output).Results);
|
|
8
|
+
/** Trivy fs `--scanners vuln`: one finding per advisory and package; the snippet is the package name (no version, so a bump that keeps the CVE stays `existing`). */
|
|
9
|
+
function trivyVuln(output, ctx) {
|
|
10
|
+
return results('trivy-vuln', output).flatMap(r => (0, util_1.asArray)(r.Vulnerabilities).map(v => ({
|
|
11
|
+
tool: 'trivy-vuln', rule: v.VulnerabilityID, category: 'dependency', severity: (0, util_1.mapSeverity)('trivy-vuln', v.Severity),
|
|
12
|
+
file: (0, util_1.repoPath)(r.Target, ctx), message: v.Title ?? v.Description ?? v.VulnerabilityID, snippet: v.PkgName ?? '',
|
|
13
|
+
})));
|
|
14
|
+
}
|
|
15
|
+
/** Trivy config: failed checks only; the snippet is the offending source line, else the check message. */
|
|
16
|
+
function trivyConfig(output, ctx) {
|
|
17
|
+
return results('trivy-config', output).flatMap(r => (0, util_1.asArray)(r.Misconfigurations).filter(m => m.Status === undefined || m.Status === 'FAIL').map(m => {
|
|
18
|
+
const cause = (0, util_1.asArray)(m.CauseMetadata?.Code?.Lines).filter(l => l.IsCause).map(l => l.Content ?? '').join('\n').trim();
|
|
19
|
+
return {
|
|
20
|
+
tool: 'trivy-config', rule: m.ID, category: 'iac', severity: (0, util_1.mapSeverity)('trivy-config', m.Severity),
|
|
21
|
+
file: (0, util_1.repoPath)(r.Target, ctx), line: m.CauseMetadata?.StartLine, message: m.Message ?? m.Title ?? m.ID,
|
|
22
|
+
snippet: cause || (m.Message ?? m.ID),
|
|
23
|
+
};
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
/** Trivy license: one finding per package and license name. */
|
|
27
|
+
function trivyLicense(output, ctx) {
|
|
28
|
+
return results('trivy-license', output).flatMap(r => (0, util_1.asArray)(r.Licenses).map(l => ({
|
|
29
|
+
tool: 'trivy-license', rule: l.Name ?? 'unknown', category: 'license', severity: (0, util_1.mapSeverity)('trivy-license', l.Severity),
|
|
30
|
+
file: (0, util_1.repoPath)(l.FilePath || r.Target, ctx), message: `${l.PkgName ?? ''} ${l.Name ?? ''} (${l.Category ?? 'license'})`.trim(),
|
|
31
|
+
snippet: l.PkgName ?? '',
|
|
32
|
+
})));
|
|
33
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.asArray = void 0;
|
|
37
|
+
exports.sha256 = sha256;
|
|
38
|
+
exports.parseError = parseError;
|
|
39
|
+
exports.partialOf = partialOf;
|
|
40
|
+
exports.parseReport = parseReport;
|
|
41
|
+
exports.mapSeverity = mapSeverity;
|
|
42
|
+
exports.repoPath = repoPath;
|
|
43
|
+
exports.stackFile = stackFile;
|
|
44
|
+
const crypto = __importStar(require("node:crypto"));
|
|
45
|
+
const path = __importStar(require("node:path"));
|
|
46
|
+
const tools_1 = require("../tools");
|
|
47
|
+
let catalog;
|
|
48
|
+
/** The catalog is read once per process: normalizers look a tool up for every finding. */
|
|
49
|
+
// RM-072 (D13): as entradas do catalogo do Agile entram so pelo nome delas, que o Classic nao usa.
|
|
50
|
+
const loadTools = () => (catalog ??= [...(0, tools_1.loadTools)(), ...(0, tools_1.loadAgileTools)()]);
|
|
51
|
+
const DEFAULT_SEVERITY = 'medium';
|
|
52
|
+
function sha256(text) {
|
|
53
|
+
return crypto.createHash('sha256').update(text).digest('hex');
|
|
54
|
+
}
|
|
55
|
+
function parseError(tool, reason) {
|
|
56
|
+
const first = (reason.split('\n').find(l => l.trim()) ?? '').trim().slice(0, 200);
|
|
57
|
+
return new Error(`security-scan.parse: ${tool}: ${first}`);
|
|
58
|
+
}
|
|
59
|
+
function parseJsonStream(text) {
|
|
60
|
+
const values = [];
|
|
61
|
+
let depth = 0;
|
|
62
|
+
let inString = false;
|
|
63
|
+
let escaped = false;
|
|
64
|
+
let start = -1;
|
|
65
|
+
for (let i = 0; i < text.length; i++) {
|
|
66
|
+
const c = text[i];
|
|
67
|
+
if (inString) {
|
|
68
|
+
if (escaped)
|
|
69
|
+
escaped = false;
|
|
70
|
+
else if (c === '\\')
|
|
71
|
+
escaped = true;
|
|
72
|
+
else if (c === '"')
|
|
73
|
+
inString = false;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (c === '"')
|
|
77
|
+
inString = true;
|
|
78
|
+
else if (c === '{' || c === '[') {
|
|
79
|
+
if (depth++ === 0)
|
|
80
|
+
start = i;
|
|
81
|
+
}
|
|
82
|
+
else if (c === '}' || c === ']') {
|
|
83
|
+
if (--depth === 0)
|
|
84
|
+
values.push(JSON.parse(text.slice(start, i + 1)));
|
|
85
|
+
if (depth < 0)
|
|
86
|
+
throw Error('unbalanced JSON');
|
|
87
|
+
}
|
|
88
|
+
else if (depth === 0 && !/\s/.test(c))
|
|
89
|
+
throw Error(`unexpected "${c}" outside a JSON value`);
|
|
90
|
+
}
|
|
91
|
+
if (depth !== 0)
|
|
92
|
+
throw Error('truncated JSON');
|
|
93
|
+
return values;
|
|
94
|
+
}
|
|
95
|
+
const nonEmpty = (v) => Array.isArray(v) ? v.length > 0 : v !== undefined && v !== null && v !== '' && v !== false;
|
|
96
|
+
/** The type of an error entry: Semgrep writes `"Timeout"` or `["PartialParsing", [locations]]`. */
|
|
97
|
+
const typeOf = (e) => {
|
|
98
|
+
const t = e?.type;
|
|
99
|
+
return String(Array.isArray(t) ? t[0] : t ?? '');
|
|
100
|
+
};
|
|
101
|
+
const isTolerated = (e, tol) => e?.level === tol.level && tol.types.includes(typeOf(e));
|
|
102
|
+
/**
|
|
103
|
+
* The non-fatal part of a tool report under the catalog `expect.tolerate` (Semgrep warn-level `Timeout` and
|
|
104
|
+
* `PartialParsing`): `partial-timeout: 2, partial-parsing: 1`, in the catalog order of the types; undefined when the
|
|
105
|
+
* tool has no `tolerate`, the output does not parse, or nothing was tolerated. `parseReport` already refused any entry
|
|
106
|
+
* outside the tolerance.
|
|
107
|
+
*/
|
|
108
|
+
function partialOf(catalogName, output) {
|
|
109
|
+
const tol = loadTools().find(t => t.name === catalogName)?.expect.tolerate;
|
|
110
|
+
if (!tol)
|
|
111
|
+
return undefined;
|
|
112
|
+
let list;
|
|
113
|
+
try {
|
|
114
|
+
list = JSON.parse(output)?.[tol.key];
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
if (!Array.isArray(list))
|
|
120
|
+
return undefined;
|
|
121
|
+
const kebab = (t) => t.replace(/^Partial/, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
122
|
+
const parts = tol.types.map(t => [t, list.filter(e => isTolerated(e, tol) && typeOf(e) === t).length])
|
|
123
|
+
.filter(([, n]) => n > 0).map(([t, n]) => `partial-${kebab(t)}: ${n}`);
|
|
124
|
+
return parts.length ? parts.join(', ') : undefined;
|
|
125
|
+
}
|
|
126
|
+
/** Parses a tool report and enforces the catalog `expect` contract (shape, requireKey, failIfKey); throws security-scan.parse. */
|
|
127
|
+
function parseReport(tool, output, catalogName = tool) {
|
|
128
|
+
const spec = loadTools().find(t => t.name === catalogName);
|
|
129
|
+
if (!spec)
|
|
130
|
+
throw parseError(tool, 'not in the catalog');
|
|
131
|
+
const { shape, requireKey = [], failIfKey = [], tolerate } = spec.expect;
|
|
132
|
+
let value;
|
|
133
|
+
try {
|
|
134
|
+
if (shape === 'stream') {
|
|
135
|
+
const values = parseJsonStream(output);
|
|
136
|
+
if (values.length === 0)
|
|
137
|
+
throw Error('empty stream');
|
|
138
|
+
return values;
|
|
139
|
+
}
|
|
140
|
+
value = JSON.parse(output);
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
// A secret scanner's output may hold the secret: its parse error carries a fixed reason, never output content.
|
|
144
|
+
if (spec.category === 'secret')
|
|
145
|
+
throw parseError(tool, 'invalid JSON');
|
|
146
|
+
throw parseError(tool, output.trim() ? output : e.message);
|
|
147
|
+
}
|
|
148
|
+
if (shape === 'array') {
|
|
149
|
+
if (!Array.isArray(value))
|
|
150
|
+
throw parseError(tool, 'expected a JSON array');
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
154
|
+
throw parseError(tool, 'expected a JSON object');
|
|
155
|
+
const obj = value;
|
|
156
|
+
for (const k of requireKey)
|
|
157
|
+
if (!(k in obj))
|
|
158
|
+
throw parseError(tool, `missing key "${k}"`);
|
|
159
|
+
for (const k of failIfKey) {
|
|
160
|
+
// Entries the catalog tolerates (non-fatal, see partialOf) do not fail the tool; any other entry does.
|
|
161
|
+
const v = tolerate?.key === k && Array.isArray(obj[k]) ? obj[k].filter(e => !isTolerated(e, tolerate)) : obj[k];
|
|
162
|
+
if (nonEmpty(v))
|
|
163
|
+
throw parseError(tool, `tool reported "${k}": ${JSON.stringify(v).slice(0, 160)}`);
|
|
164
|
+
}
|
|
165
|
+
return obj;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Severity through the catalog `severityMap`, case-insensitive, with '*' as the catch-all. A value the map does not
|
|
169
|
+
* know (or a tool without a map) is `medium`, never an exception.
|
|
170
|
+
*/
|
|
171
|
+
function mapSeverity(tool, raw, fallback = DEFAULT_SEVERITY) {
|
|
172
|
+
const map = loadTools().find(t => t.name === tool)?.severityMap;
|
|
173
|
+
if (!map)
|
|
174
|
+
return fallback;
|
|
175
|
+
const key = String(raw ?? '').toLowerCase();
|
|
176
|
+
for (const [k, v] of Object.entries(map))
|
|
177
|
+
if (k.toLowerCase() === key)
|
|
178
|
+
return v;
|
|
179
|
+
return map['*'] ?? fallback;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* A file path as printed by a tool, made relative to the repository root with posix separators. An absolute path is
|
|
183
|
+
* taken under `ctx.root` (the container mount); a relative one is relative to the repository root, or to the stack
|
|
184
|
+
* directory when `from` is 'stack' (tools that run inside it). A path that leaves the mount is returned normalized.
|
|
185
|
+
*/
|
|
186
|
+
function repoPath(file, ctx, from = 'root') {
|
|
187
|
+
const mount = path.posix.resolve('/', (ctx.root || '/src').replaceAll('\\', '/'));
|
|
188
|
+
let f = file.replaceAll('\\', '/');
|
|
189
|
+
// golangci-lint run at the mount root prints `../src/x.go`: relative to a sibling of the mount, so root-relative.
|
|
190
|
+
const sibling = `../${path.posix.basename(mount)}/`;
|
|
191
|
+
if (f.startsWith(sibling))
|
|
192
|
+
f = path.posix.join(mount, f.slice(sibling.length));
|
|
193
|
+
const abs = path.posix.resolve(mount, from === 'stack' ? ctx.stackDir : '.', f);
|
|
194
|
+
const rel = path.posix.relative(mount, abs);
|
|
195
|
+
if (rel === '' || rel.startsWith('..'))
|
|
196
|
+
return path.posix.normalize(f);
|
|
197
|
+
return rel;
|
|
198
|
+
}
|
|
199
|
+
/** A file the stack owns (lockfile, requirements.txt, go.mod), inside the stack directory. */
|
|
200
|
+
function stackFile(name, ctx) {
|
|
201
|
+
return path.posix.normalize(path.posix.join(ctx.stackDir.replaceAll('\\', '/'), name));
|
|
202
|
+
}
|
|
203
|
+
const asArray = (v) => Array.isArray(v) ? v : [];
|
|
204
|
+
exports.asArray = asArray;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.zizmor = zizmor;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** zizmor JSON (`--format json`). Rows are 0-based in the report, lines are 1-based here; the primary location wins. */
|
|
6
|
+
function zizmor(output, ctx) {
|
|
7
|
+
const list = (0, util_1.parseReport)('zizmor', output);
|
|
8
|
+
return list.filter(z => !z.ignored).map(z => {
|
|
9
|
+
const loc = (0, util_1.asArray)(z.locations).find(l => l.symbolic?.kind === 'Primary') ?? (0, util_1.asArray)(z.locations)[0];
|
|
10
|
+
const local = loc?.symbolic?.key?.Local;
|
|
11
|
+
const row = loc?.concrete?.location?.start_point?.row;
|
|
12
|
+
return {
|
|
13
|
+
tool: 'zizmor', rule: z.ident, category: 'workflow', severity: (0, util_1.mapSeverity)('zizmor', z.determinations?.severity),
|
|
14
|
+
file: (0, util_1.repoPath)(local?.verbatim_path ?? local?.given_path ?? '', ctx), line: row === undefined ? undefined : row + 1,
|
|
15
|
+
message: [z.desc, loc?.symbolic?.annotation].filter(Boolean).join(': ') || z.ident,
|
|
16
|
+
snippet: loc?.concrete?.feature ?? z.desc ?? z.ident,
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|