HQ-Axiom/axiom-pentest-core

GitHub: HQ-Axiom/axiom-pentest-core

一款自托管、离线优先的渗透测试报告与 AppSec 证据控制平台,支持多源扫描结果导入、确定性去重、合规映射和防篡改审计日志。

Stars: 0 | Forks: 0

# AXIOM-Pentest-Core Local-first, evidence-driven security-testing platform for **authorized** targets, local labs, and CTFs. ![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg) ![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178c6.svg) ![Node](https://img.shields.io/badge/Node-20.18.0%20(.nvmrc)-339933.svg) ![Status](https://img.shields.io/badge/status-beta-blue.svg) ![Tests](https://img.shields.io/badge/tests-passing-success.svg) ![Version](https://img.shields.io/badge/version-0.10.6-blue.svg) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/HQ-Axiom/axiom-pentest-core/actions/workflows/ci.yml) ## TL;DR (30 seconds) - **What:** Self-hosted workspace for authorized pentest engagements. Runs your existing OSS scanners (Semgrep / Nuclei / Trivy / gitleaks / osv-scanner) under one `authorization.yml`, imports SARIF / Burp / GHAS / GitLab / CSV / Nessus findings, dedupes deterministically, triages with a hash-chained audit log, exports MD / HTML / PDF / SARIF / JSON reports. - **Why interesting:** Authorization is enforced by the engine (kill-switch, RPS limit, scope, hard refusals — in code, not policy). No telemetry, no phone-home, no automatic outbound — the only network feature is the opt-in `axiom sca` OSV.dev advisory lookup (skippable with `--dry-run`). **One complete Apache-2.0 public version — no Pro/Community split, no feature paywall (P9.0).** - **Included for everyone:** every scanner, every importer (incl. CSV / Nessus), dedupe, triage, risk scoring, **Markdown / HTML / PDF reports** + `--brand`, SARIF / JSON exports, §5.4 compliance mapping (OWASP / ASVS / PCI / ISO), **Jira / GitHub / GitLab ticket draft export** (dry-run), hash-chained audit log + **`audit anchor`**, `axiom verify`, the loopback-only **AXIOM Local Console** (the official local GUI; plus an advanced read-only single-workspace dashboard). - **Public in this build (no edition/paywall):** `axiom portfolio summary/workspaces/risks/dedupe` and `axiom metrics snapshot/list/show` run with no `AXIOM_EDITION`/license. - **Roadmap / not bundled in this public repo yet (honest, not a paywall):** `portfolio export`, the cross-workspace ticket bundle, `portfolio metrics`, `metrics diff/trend/mttr/prune`, and signed-artefact *issuance* depend on optional overlay packages not in this repo — invoking those reports "not included in this public build yet". - **Try it in 60 seconds:** git clone https://github.com/HQ-Axiom/axiom-pentest-core.git cd axiom-pentest-core pnpm install && pnpm -r build node packages/cli/bin/axiom.mjs demo --json node packages/cli/bin/axiom.mjs report -w demo-juice -f md - **Status:** beta. Latest **[signed GitHub Release: v0.10.6](https://github.com/HQ-Axiom/axiom-pentest-core/releases/tag/v0.10.6)** (source tarball + SBOM + SHA256SUMS + detached Ed25519 signatures + public key). Windows **and** Linux install are verified in CI (install-smoke on `windows-latest` + `ubuntu-latest`). A guided **noob-safe browser GUI** (Engagement Setup → manual findings → branded MD/HTML/PDF reports, no terminal needed) is included. AXIOM stays **local-first**: loopback-only Local Console, **no automatic scanning, no telemetry, no external dashboard scripts** — scan workflows run only when an authorized user explicitly starts them, on systems you own or are authorized to test. One complete public version — **no Pro/Community split, no feature paywall** (P9.0). Not on npm / Docker Hub / GHCR yet. A few heavier subsystems (portfolio export / trend analytics / signing issuance) are not implemented in this build yet (roadmap, never a paywall). Release history in [`CHANGELOG.md`](CHANGELOG.md). - **Looking for:** 3–5 pilot partners (DACH / EU boutique pentest firms, internal AppSec teams that can't use SaaS). 2-week pilot, no purchase obligation, no data upload. See [`docs/PILOT_OUTREACH_PACK.md`](docs/PILOT_OUTREACH_PACK.md). ## Why AXIOM? You already run Burp, Snyk, Semgrep, Trivy, CodeQL, or some subset. You triage the same SQL injection three times — once per tool — into a spreadsheet that resets every re-scan. AXIOM is not a replacement for any of them. AXIOM is the layer above: - **Runs** OSS scanners (Semgrep, Nuclei, Trivy, gitleaks, osv-scanner) under one `authorization.yml` with scope, RPS limit, kill-switch, and hard refusals enforced by the engine — not by convention. - **Imports** SARIF / XML / JSON from the commercial tools you already pay for. `axiom import sarif` (any v2.1.0 producer: Snyk, CodeQL, Semgrep Pro, gitleaks…), `axiom import burp` (Burp Pro XML + Burp Enterprise JSON), `axiom import ghas --source code-scanning|dependabot` (GitHub Advanced Security file exports), `axiom import gitlab --type sast|dependency|secret|dast` (GitLab Security reports). `axiom import status` lists imported batches and provenance. All importers are file-local: AXIOM never calls GitHub or GitLab APIs itself — operators feed `gh api …` / `glab api …` outputs, which keeps imports offline-testable. - **Maps to compliance frameworks** OWASP Top 10 2021, ASVS L1/L2, PCI-DSS 6.5 / 4.0, ISO 27001:2022 — report §5.4 *Compliance Coverage* in both Markdown and HTML. Anti-hallucination: unknown stays `unmapped`, never guessed. Editable via `packages/reporter/src/compliance/mappings.yml`. - **Dedupes** findings deterministically across tools via a 5-key selector tuple. 54.5 % noise reduction on Juice Shop. - **Triages** with a 5-status workflow (`open`, `triaged`, `confirmed`, `false_positive`, `wont_fix`) that **carries decisions forward across re-scans**. Reviewers see only new deltas. - **Audits** every state change in a SHA-256 hash-chained log. `axiom audit verify` walks the chain. Triage exports ship with a tamper-evident `_integrity` block. - **Reports** Markdown, HTML, and SARIF v2.1.0 with `partialFingerprints`, `kind`, `guid`, and `suppressions[]` for GitHub Code Scanning. One PR check. - **Trend / portfolio analytics** (Phase E4 — workspace snapshots, eight-class diff, time-series trend, MTTR, cross-workspace portfolio rollup). **In the public build (no edition gate):** `axiom portfolio summary/workspaces/risks/dedupe` and `axiom metrics snapshot/list/show` run for everyone. **Roadmap (optional overlay, not bundled here):** `portfolio export`, the cross-workspace ticket bundle, `portfolio metrics`, and `metrics diff/trend/mttr/prune` report "not included in this public build yet" — candidates for a future public port, never a paywall. - **Verifies signed artefacts** (`axiom verify`) fully offline — reports, SARIF exports, ticket bundles, and release manifests, with the public key pinned out-of-band. Public **releases** are signed with the production **Ed25519** key by the maintainers (see *Verifying signed releases* below). Operator-side signing **issuance** (the `sign` CLI surface, incl. cosign / Rekor) is **not wired into this public build yet** — a roadmap item, never a paywall. No automatic outbound. Self-hosted, single-binary-chain, zero telemetry, no background cloud calls (the opt-in `axiom sca` OSV.dev lookup is the sole network feature), Apache-2.0. No license key, no SaaS lock-in. What AXIOM does **not** claim: it does not replace Burp's Repeater or Snyk's vuln database or Semgrep's rule engine or Nuclei's templates. See [`docs/COMPETITIVE_POSITIONING.md`](docs/COMPETITIVE_POSITIONING.md) for the eleven-tool honest comparison and the five anti-claims. ## New to AXIOM? 👉 **Tutorial:** [`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md) — von 0 auf ersten Report in 10 Minuten, mit copy-paste Befehlen für jeden Schritt. Empfohlen für jeden, der AXIOM zum ersten Mal aufsetzt. This repository is **public on GitHub** at [`github.com/HQ-Axiom/axiom-pentest-core`](https://github.com/HQ-Axiom/axiom-pentest-core). Clone via: git clone https://github.com/HQ-Axiom/axiom-pentest-core.git cd axiom-pentest-core Not yet published to **npm** or **Docker Hub / GHCR** — those steps remain operator-gated. There is **no Pro overlay as a product model**: PDF reports, ticket draft export, branding, audit anchor, `portfolio summary/workspaces/risks/dedupe` and `metrics snapshot/list/show` are all part of this public source tree and run with no edition/license. A few overlay-only surfaces (`portfolio export`, the cross-workspace ticket bundle, `portfolio metrics`, `metrics diff/trend/mttr/prune`, and signed-artefact issuance) are **not bundled in this public repo yet** — invoking them reports an honest "not included in this public build yet", never a paywall. ## Quickstart (60 seconds) **One-script setup** (checks Node, sets up pnpm, installs, builds — no admin needed): # Linux / macOS: ./scripts/setup-linux.sh # Windows (PowerShell): .\scripts\setup-windows.ps1 **Or by hand** (use **Node 20.18.0** from `.nvmrc`, not Node 24): # Inside the repo: pnpm install && pnpm -r build node packages/cli/bin/axiom.mjs doctor # pre-flight check node packages/cli/bin/axiom.mjs demo # canned workspace with 6 findings + 2 snapshots node packages/cli/bin/axiom.mjs report -f md -w demo-juice node packages/cli/bin/axiom.mjs console --open # browser console (create the first admin in the GUI) Every command runs offline except the opt-in `axiom sca` OSV.dev advisory lookup (`--dry-run` skips its network calls). Cross-platform install notes: [`docs/INSTALL.md`](docs/INSTALL.md). New here? **[First 10 minutes guide](docs/FIRST_10_MINUTES.md)** — setup → admin → report → verify, copy-paste. ## Local Console preview The browser console is **loopback-only** (127.0.0.1), with **no telemetry and no third-party scripts**. From the Console you can import evidence, manage findings, generate branded MD/HTML/PDF reports — and **explicitly start authorized scan workflows**. AXIOM **never scans automatically**: a scan runs only when an authorized user starts it and stays within the scope you authorize. _Only use AXIOM on systems you own or have explicit written permission to test._ Start the official GUI with: node packages/cli/bin/axiom.mjs console --open It has login + RBAC, authorized scan workflows, findings, reports, audit views, and admin/account flows. The screenshots below are the **real authenticated Local Console** (a throwaway local admin + the offline `axiom demo` workspace — no real target, no real data): | New Scan | Authorization preview (no scan runs) | |---|---| | ![AXIOM Local Console — authenticated New Scan view: signed-in admin, live version, the loopback-only / no-telemetry / no-external-scripts trust strip, target URL, scan profile, and the "Authorized workflow only — never scans automatically" copy with an explicit authorization checkbox](https://static.pigsec.cn/wp-content/uploads/repos/cas/93/932c0782d90b0fc94ada6edf227358c024ef41bf80e5669e73f7190ebfb28e00.png) | ![AXIOM Local Console — Safety Preview showing the generated authorization.yml (scope, allowed ports, RPS limit, written-authorization-confirmed), allowed test types and hard refusals, with a "Start authorized scan" action](https://static.pigsec.cn/wp-content/uploads/repos/cas/4c/4c8a122f5baecfc038f205062c76ff9463b439baff70507865f58076bb7f58c0.png) | | Cross-workspace portfolio (demo data) | |---| | ![AXIOM Local Console — read-only cross-workspace Portfolio: workspace/finding/high-critical/highest-risk metric cards and a top-risks table, driven by axiom portfolio summary](https://static.pigsec.cn/wp-content/uploads/repos/cas/cc/cc18ec93196b518537ca18df19329edb890c4b9d78c8f71130ba41d4f25f6154.png) | ### Advanced single-workspace Dashboard `axiom dashboard -w ` opens a lightweight **read-only, single-workspace** view for local inspection. It is **not** a second product and **not** the primary GUI — most users should stay in the Local Console. | Dashboard overview + engagement | Findings | |---|---| | ![AXIOM Local Dashboard (advanced single-workspace view) — engagement card, severity heatmap, top risks, and the "Local-only by design" trust strip](https://static.pigsec.cn/wp-content/uploads/repos/cas/e3/e3c0da5e038a72ab903e6c343572a4105014fcb30492687f9b3f874d23f9498a.png) | ![Findings list with severity, source and per-finding evidence](https://static.pigsec.cn/wp-content/uploads/repos/cas/87/87190fa2bd67b1f9c33bb516a53659040f1b2eeb5e62a65ac092a13dfdc97d87.png) | | Dashboard reports (MD / HTML / PDF) | Generated PDF cover | |---|---| | ![AXIOM Local Dashboard reports tab with optional branding and one-click Generate for Markdown, HTML and PDF](https://static.pigsec.cn/wp-content/uploads/repos/cas/06/065034d3b9246e25c0d0f4ce2baa341347239bad7317210d2298f84367bbdb23.png) | ![Branded "AXIOM Security Report" PDF cover with client, project and classification from the engagement](https://static.pigsec.cn/wp-content/uploads/repos/cas/2e/2e81d1a695be7c1d9f3307fc329c0cfc73d5b5523ba26033dd20bc9c04f648ac.png) | ### Attach evidence to findings (P5.5) Attach screenshots, openssl/curl output, Burp dumps, HTTP captures, or any small text/log/json file to a finding. The file is copied into the workspace (your source is untouched), hashed with SHA-256, and recorded with a hash-chained audit event. Metadata flows into MD / HTML / JSON / SARIF reports and the local dashboard. # Attach node packages/cli/bin/axiom.mjs evidence add -w my-first \ --finding \ --file \ --kind terminal|screenshot|http|text|json|log|other \ --title "..." --description "..." --json # List + inspect node packages/cli/bin/axiom.mjs evidence list -w my-first --finding node packages/cli/bin/axiom.mjs evidence show -w my-first --evidence Storage: `workspaces//evidence/attachments//-`. Default size cap 10 MiB (`--max-bytes` to override). Symlinks always refused; directories refused; path traversal stripped. **No upload, no remote storage, no automatic screenshot.** See `docs/EVIDENCE_ATTACHMENTS_USAGE.md`. ### Distribution status ### One complete public version (P9.0 — no Pro split) As of **v0.10.4**, AXIOM has **no Community/Pro/Enterprise split and no feature paywall.** There is one normal public version, and `axiom --version` reports a plain version string. Every shipped feature works for everyone: - every scanner, importer (SARIF / Burp / Nuclei / ZAP / GHAS / GitLab / **CSV** / **Nessus**), dedupe, triage, risk scoring; - **reports in Markdown / HTML / PDF** (PDF is a normal feature now — pure-JS pdfkit renderer, no chromium), plus **safe MD/HTML branding** (`--brand`); - **SARIF / JSON / Markdown findings exports**; - **ticket draft export** for Jira / GitHub / GitLab (`axiom ticket export`, dry-run — writes files, never calls an API); - **hash-chained audit log** + `audit verify` + out-of-band **`audit anchor`** tamper evidence; - offline signing **verification** (`axiom verify`), the loopback-only **AXIOM Local Console** (plus an advanced single-workspace dashboard), OWASP / ASVS / PCI / ISO compliance mapping. `portfolio summary/workspaces/risks/dedupe` and `metrics snapshot/list/show` run in this public build. A few overlay-only surfaces (`portfolio export`, cross-workspace ticket bundle, `portfolio metrics`, `metrics diff/trend/mttr/prune`, signed-artefact **issuance**) are **not bundled in this public repo yet** — invoking them reports an honest "not included in this public build yet" (never "requires Pro"). They are candidates for a future public port, not a paywall. There is no hidden feature gate. Any paid offering would be support / integration / training, never a locked feature. ## Local packaging P1.4a ships a Dockerfile + a local release script. Nothing is published — all artefacts stay on the build host. # Plan-only manifest (verifies version, computes SHA-256, writes no artefacts): node scripts/make-release.mjs --dry-run --json # Real local release — runs pnpm -r build, pnpm -r test, then pnpm pack the CLI: node scripts/make-release.mjs # Optional: build a container image (Node 22 Debian-slim, multi-stage, ~750 MB): docker build -t axiom-local:0.10.4 . docker run --rm -v "$PWD/workspaces:/app/workspaces" axiom-local:0.10.4 --version Or use the wrapper `Makefile`: make image # docker build -t axiom-local: . make image-smoke # build + axiom --version + doctor --json + demo with mounted volume make release-dry # manifest-only dry run make release # full local release (build + test + pnpm pack) make verdaccio-smoke # local Verdaccio registry-install proof (skipped without Verdaccio) make registry-install-smoke # alias for verdaccio-smoke make help # list all targets ### Container runtime contract The image is loopback-by-design (D9 / D13): the Local Console refuses to bind on a non-loopback host. CLI commands work fully inside the container. For a smoke run: docker run --rm -v "$PWD/workspaces:/app/workspaces" axiom-local:0.10.4 demo --json docker run --rm -v "$PWD/workspaces:/app/workspaces" axiom-local:0.10.4 report -w demo-juice -f pdf -o /app/workspaces/report.pdf Mounting the host's `workspaces/` directory makes the container's writes visible to subsequent `axiom` calls (on host or container). The auth DB lives at `/root/.axiom` — mount a separate host directory to persist users + sessions across container restarts. Console-mode inside the container is **deferred to a later P1 step** — the dashboard's hard loopback-bind guard would need a deliberate `AXIOM_DASHBOARD_ALLOW_EXTERNAL_BIND=1` env-path before published-port `docker run -p 18888:18888` makes sense. CLI surface (every `axiom` subcommand) works fine inside the container today. Output lands in `release-artifacts/` (git-ignored): one `.tgz` per packed workspace + `release-manifest.json` with SHA-256 hashes, the resolved version, git commit, and a paranoia-pass that refuses any artefact path matching `.env` / `.sqlite` / `workspaces/` / `.axiom/`. No `npm publish`, no `docker push`, no tag — the operator decides what happens next. Container volumes (operator-mounted, not VOLUME-declared so `docker run --rm` works cleanly): - `/app/workspaces` — per-workspace SQLite ledgers - `/root/.axiom` — global auth DB (users + sessions) ### Verifying signed releases **v0.5.1 is the first AXIOM release that officially documents and versions the P1.5 signed-release flow.** P1.5 turns `make-release.mjs --sign` into a self-describing, versioned **signed release directory** (default `dist/releases/axiom-v/`, override with `--out `): # Release signing (Mode A, offline Ed25519 — no Rekor, no network; maintainer/production key): axiom keygen # one-time, private key 0600 make release # or: node scripts/make-release.mjs AXIOM_EDITION=enterprise \ node scripts/make-release.mjs --sign --signer "you@org" \ --out dist/releases/axiom-v0.10.6 The folder contains the tarball, the signed `release-manifest.json` + its sidecar, `SHA256SUMS`, detached raw Ed25519 `.sig` files, the **public** key (`axiom-pub.pem`), `provenance.json` and a `README_VERIFY.md`. Consumers verify **fully offline** (verification is ungated — works in Community), three independent ways: # 1. AXIOM-native (the cryptographic root of trust): axiom verify release --manifest release-manifest.json --key axiom-pub.pem # 2. Tool-agnostic integrity: sha256sum -c SHA256SUMS # 3. Defense-in-depth with stock OpenSSL: base64 -d SHA256SUMS.sig > /tmp/s.sig openssl pkeyutl -verify -pubin -inkey axiom-pub.pem -rawin -in SHA256SUMS -sigfile /tmp/s.sig Pin `axiom-pub.pem` **out of band** — AXIOM never trusts a key embedded in a sidecar. None of these paths contacts a network or a transparency log. Full detail + the honest reproducibility caveat: [`docs/SIGNED_RELEASES.md`](docs/SIGNED_RELEASES.md). ### Productization history (v0.6.0 → v0.7.0 — superseded by P9.0) Earlier versions (v0.6.x–v0.7.1) experimented with a public-core + private `axiom-pro` overlay split that gated PDF / ticket bundles / portfolio / metrics / signed-artefact issuance behind a Pro/Enterprise edition. **P9.0 (v0.7.2) removed that split entirely**: AXIOM is now one public version with no edition gate and no feature paywall. PDF, ticket draft export, branding and audit anchor are public; portfolio, trend metrics and signed-artefact issuance are simply not implemented in this public build yet (roadmap, not locked). The old overlay packages and `FEATURE_REQUIRES_PRO` paths are historical only. #### Public OSS Distribution readiness (released in v0.6.2) As of v0.6.2, every public package is verifiably packable into a clean npm tarball — proven on every release-cut by `make public-distribution-smoke`: # Per-package pack + invariant scan (zero Pro code, zero secrets, # zero operator data; SHA-256 recorded). Tarballs land in # dist/public-pack-audit/ (git-ignored). make public-pack-audit # → status: ok (fails=0, warns=0) # → 13 packages, 9.7 KB–199.6 KB each # Full end-to-end smoke (split-audit + private-profile-check + # pack-audit; add --docker if axiom-local:0.10.4 image is built). make public-distribution-smoke # Direct invocations (with JSON output) are also supported: node scripts/public-npm-pack-audit.mjs --json node scripts/public-distribution-smoke.mjs --json # Optional Docker public-image smoke (proves the image carries the public # source only — zero private overlay packages on disk). make image # if not already built make public-image-smoke The full **What is** and **What isn't** in each tarball is contracted in [`docs/public-oss-distribution.md`](docs/public-oss-distribution.md). Every public `package.json` still carries `"private": true` — flipping that flag is the single deliberate operator gesture that authorises a public `npm publish`. **Public source is live on GitHub ([`HQ-Axiom/axiom-pentest-core`](https://github.com/HQ-Axiom/axiom-pentest-core), since 2026-06-07), and a signed GitHub Release ([v0.7.0](https://github.com/HQ-Axiom/axiom-pentest-core/releases/tag/v0.7.0)) is published. No `npm publish` has happened. No Docker image published.** # Public release smoke (ephemeral signing key in $TMPDIR, no trust-roots): make release-smoke-public # Private release smoke (bundles release/private/production-trust-roots.example.json): make release-smoke-private # Both profiles + customer-verify simulation + leak scan in one command: make release-smoke `make release-smoke` emits signed releases into `dist/release-smoke*/` (git-ignored), runs `axiom verify release` against each, asserts that the private manifest's `trust_roots.sha256` matches the shipped `production-trust-roots.json`, runs `axiom doctor --json` against the private trust-roots (expects `production_trust_root:true`), then re-verifies in a sandboxed `$TMPDIR` (third-party simulation). Schema: `axiom-release-profile-smoke/v1`. **No network, no Rekor, no push, no publish.** Full 20-step acceptance gate: [`docs/release-profile-acceptance-gate.md`](docs/release-profile-acceptance-gate.md). All five Pro/Enterprise overlay packages — `@axiom/pro-reporter` (P1.9), `@axiom/pro-ticket-bundle` (P1.11), `@axiom/pro-metrics` (P1.12 + P1.13), `@axiom/pro-portfolio-export` (P1.14), and `@axiom/ent-signing` (P1.15) — have been **physically externalised** out of this repository and live in a separate private `axiom-pro` overlay repo (no remote, no publish). Public-core is **Pro-code-free**: zero `packages/pro-*/` or `packages/ent-*/` directories, zero `@axiom/(pro|ent)-*` reference in any public `package.json` dependency bucket; enforced by `scripts/public-split-audit.mjs` (`status:"ok"`, 0 fails, 0 warns) and by the overlay's `overlay-install-from-tarballs.mjs` smoke. Two further enterprise namespaces (`@axiom/ent-rbac` P1.16, `@axiom/ent-compliance` P1.17) are vocabulary-reserved with prospective audit-guard tests; no overlay package on disk yet (assessment docs in [`docs/rbac-extraction-assessment.md`](docs/rbac-extraction-assessment.md) and [`docs/custom-compliance-extraction-assessment.md`](docs/custom-compliance-extraction-assessment.md)). ## Authorization is non-optional ## What AXIOM is A coherent pipeline that combines SAST (repo indexer, route mapper, dataflow-light, secrets, SCA), DAST (passive crawler + active-safe probes for reflection / SQL-error / SSRF / path-traversal / open-redirect), a Playwright-driven browser verifier (XSS reflection, cookie hygiene, login recording), session-aware authenticated crawling, declarative business-logic invariants, and a unified reporting engine (Markdown, HTML, SARIF, JSON) — all gated by a single authorization manifest and recorded in a per-workspace SQLite ledger with full HTTP evidence and an append-only audit log. AXIOM is a **TypeScript monorepo** of 13 packages built with pnpm workspaces. State lives in each workspace's `.axiom/db.sqlite`; nothing is uploaded anywhere. ## Easiest mode — AXIOM Local Console If this is your first time, skip the per-stage CLI and use the **Local Console** — a loopback-only browser wizard that drives the whole pipeline (index → routes → scan → verify → report) from a 12-step UI with explicit authorization checkboxes. Same safety enforcement as the CLI; nothing binds outside `127.0.0.1`. AX="$(pwd)/packages/cli/bin/axiom.mjs" node "$AX" console --open See [`docs/gui-quickstart.md`](docs/gui-quickstart.md) for the full walkthrough. For unattended / CI runs, the equivalent one-liner is `axiom scan-wizard --url --profile quick --confirm-authorization`. ## Quick start ### Prerequisites - **Node 20.18.0 (recommended/tested — see `.nvmrc`).** The floor is 20.10, but use **20.18.0**. **Do not use Node 24** — the native modules (`better-sqlite3`, `argon2`) have no prebuilds for it yet and `pnpm install` will fail to build them (this bites Windows hardest). `nvm use` picks up `.nvmrc` automatically. - **pnpm 9+** — `corepack enable && corepack prepare pnpm@9.12.0 --activate`. If corepack errors with `EPERM` (common on Windows without admin), install pnpm with npm instead: `npm install -g pnpm@9.12.0`. - **Build tools** for `better-sqlite3` / `argon2` (Linux apt: `build-essential python3`; macOS: `xcode-select --install`; Windows: see `docs/INSTALL.md`). - **Optional:** chromium for browser-verify — `pnpm exec playwright install chromium` The Quickstart below sets `$AX` to the absolute path of the CLI entry point so subsequent examples work regardless of `cwd`. For convenience you can also `alias axiom="node $AX"`. Every later example in this README assumes `$AX` is set. git clone https://github.com/HQ-Axiom/axiom-pentest-core.git cd axiom-pentest-core nvm use && corepack enable && pnpm install && pnpm -r build pnpm -r test # unit tests across all packages # optional: install chromium for browser-agent verification (~250 MB, one-time) pnpm exec playwright install chromium AX="$(pwd)/packages/cli/bin/axiom.mjs" node "$AX" doctor # env self-check `axiom doctor` validates Node version, pnpm, the native `better-sqlite3` binding, YAML support, write permissions, and (warn-only) the chromium binary. A green doctor is a precondition for every other command. When a check fails, doctor now prints an `install hint:` line with the platform-specific command — paste that line and run it. ## First scan against OWASP Juice Shop (E2E) End-to-end run against a local Juice Shop with authenticated crawling and browser verification: # One-time: clone the Juice Shop source so the indexer / route-mapper have code to walk git clone https://github.com/juice-shop/juice-shop.git ~/juice-shop docker run --rm -d --name juice-shop -p 3000:3000 docker.io/bkimminich/juice-shop node "$AX" workspace create juice-shop-local --seed-auth # Edit workspaces/juice-shop-local/authorization.yml — confirm scope, owner, window node "$AX" auth show -w juice-shop-local # HTTP-only login: POSTs credentials, extracts JWT from response body, # synthesizes a Playwright-compatible storage state. Never persists secrets. node "$AX" auth login -w juice-shop-local --role admin \ -u http://127.0.0.1:3000/rest/user/login \ --field email=admin@juice-sh.op --field password=admin123 \ --bearer-path authentication.token # Full pipeline: index -> routes -> secrets -> http_tester -> reporter node "$AX" run -w juice-shop-local \ -r ~/juice-shop -b http://127.0.0.1:3000 \ --active-safe --as admin --no-sca # Browser-verify every reflection finding (single Chromium pass) node "$AX" browser verify-xss -w juice-shop-local --all-reflections # Render a Markdown report node "$AX" report -w juice-shop-local -f md docker rm -f juice-shop Authenticated crawl reaches **+60 % more 2xx routes** and **-70 % 401s** vs. anonymous baseline on Juice Shop. Browser verification reduces reflection false-positives by **~87.5 %** on the same target. **Shortcut:** the bash script `scripts/demo-juice-shop.sh` automates all of the above — see `docs/checkpoints.md` for the Phase 6 entry. ## CLI surface 40+ top-level commands, in workflow order (run `axiom --help` for the authoritative list; the table below covers the orchestrating commands; the 5 standalone external-adapter commands `axiom semgrep / nuclei / trivy / gitleaks / osv-scanner` are documented under §"Adapters" — they're each a thin wrapper around the matching binary, used for adapter-specific debugging; the unified entry-point is `axiom adapters run-all`): | Command | Purpose | |---|---| | `axiom init` | First-run helper; prints next steps and links to docs | | `axiom doctor` | Environment self-check (Node, pnpm, sqlite, yaml, chromium) | | `axiom workspace create / list / info` | Create or inspect a workspace (DB, audit log, evidence dir) | | `axiom auth init / show / inspect` | Seed and validate an `authorization.yml` manifest | | `axiom auth login` | HTTP-only login: capture session + bearer for a role | | `axiom auth session list / show / remove` | Manage captured per-role storage states | | `axiom index run / list / show` | Walk a repo: files, projects, frameworks, entry points, deps | | `axiom routes run / list / show` | Extract HTTP routes (Express, FastAPI, OpenAPI) from indexed code | | `axiom http crawl` | Authorized HTTP crawl, optionally `--as `, `--active-safe` | | `axiom http requests` | Inspect captured requests / responses (filter by role, status) | | `axiom scan` | Single-shot: scope-check + crawl + active-safe probes | | `axiom run` | Full agent pipeline: index -> routes -> (secrets, sca) -> http -> report | | `axiom secrets scan` | Local secret scanner (always masks values before persistence) | | `axiom sca` | Dependency CVE check via OSV.dev (npm, PyPI, Go, Maven, ...) | | `axiom dataflow scan` | SAST-light: source-to-sink taint heuristics (JS / TS / Python) | | `axiom invariants validate / run` | Declarative business-logic rules over captured responses | | `axiom hypotheses idor` | Two-role response diff for IDOR / BOLA detection | | `axiom browser status / screenshot` | Chromium status; on-demand screenshot of an authorized URL | | `axiom browser record-login` | Headed Playwright session-capture (storage state per role) | | `axiom browser verify-xss [] [--all-reflections]` | Live-DOM XSS / reflection verifier | | `axiom correlate` | Link findings back to mapped routes (path-anchored regex) | | `axiom coverage` | Route-coverage report (matched vs. uncovered routes) | | `axiom findings list / show / export` | Inspect / filter findings; export md / json / sarif | | `axiom findings dedupe / clusters / cluster {show,split,triage,triage-bulk}` | Cluster duplicate findings (5 deterministic keys), reversible split, MAX-severity policy | | `axiom findings triage / triage-bulk / triage-history` | Per-finding decisions: open / accepted / dismissed / false_positive / wont_fix; cluster propagation; audit-only history | | `axiom findings triage-policy {validate,apply}` | Declarative auto-triage rules (YAML v1) — protects local direct decisions by default | | `axiom findings triage-export / triage-import` | Portable JSON for sharing decisions across workspaces (stable selectors, --force override) | | `axiom findings scans-list / diff / triage-carryover` | Cross-run delta + propagate triage from earlier runs (CI re-scan workflow) | | `axiom adapters {status, run-all}` | Unified entry point for 5 OSS scanners + native HTTP crawl. `--profile {quick,full,deep,ci}` presets, `--parallel`, `--fail-on ` exit-code policy | | `axiom replay ` | Emit a curl (or Playwright fetch stub) to reproduce a finding | | `axiom report -f md\|html` | Full 12-section report (incl. 5.1 Consolidated Findings, 5.2 Triage Status) with evidence appendix | | `axiom console --open` | **AXIOM Local Console** — the official local GUI (multi-user, loopback-only) | | `axiom dashboard -w` | Advanced read-only single-workspace view (secondary; most users want `axiom console`) | | `axiom audit verify -w [--json]` | Verify the workspace's hash-chained NDJSON audit log; non-zero exit on a broken chain | | `axiom kill [--clear]` | Drop / clear the kill-switch sentinel — refuses subsequent runs | Run any command with `--help` for full options. ## Architecture +---------------------------+ | axiom CLI (commander) | +-------------+-------------+ | +----------------+----------------+ | | +----------v----------+ +------------v-----------+ | @axiom/orchestr. | | AuthGate / KillSw | | topo + budgets | | ScopeEnforcer | +----------+----------+ +------------+-----------+ | | +-----------+----------+----------+-----------+----------+ | | | | | | v v v v v v +-----+ +--------+ +--------+ +---------+ +---------+ +--------+ |index| |route- | |dataflow| |sca- | |http- | |browser-| |er | |mapper | |-light | |secrets | |tester | |agent | +-----+ +--------+ +--------+ +---------+ +----+----+ +---+----+ | | +----------+---------+ v +---------+ +---------+ | reporter|<--|business-| | md/html/| |logic | | sarif | +---------+ +----+----+ | +------v-------+ | dashboard | loopback-only | (zero-dep) | +--------------+ All packages persist through @axiom/core (SQLite via better-sqlite3) and share types through @axiom/shared. 13 packages: `shared`, `core`, `cli`, `orchestrator`, `indexer`, `route-mapper`, `http-tester`, `browser-agent`, `sca-secrets`, `dataflow-light`, `business-logic`, `reporter`, `dashboard`. See `docs/decisions.md` for ADRs and `docs/checkpoints.md` for the per-phase delivery log. ## Security model - **Authorization manifest** — Zod-validated YAML with target metadata, scope allowlists, allowed test types, rate / budget limits, scan window, hard refusals, and operator attestation. The AuthGate snapshots the parsed manifest into the DB at scan start. - **Scope enforcement** — Domain (literal + leading-wildcard), IPv4 / IPv6 / CIDR allowlists, port allowlist, default-deny on private ranges, hard block on cloud-metadata endpoints (`169.254.169.254`, `fd00:ec2::254`, `metadata.google.internal`, ...). - **Kill switch** — Presence of `.axiom/KILL_SWITCH` halts every running and future agent immediately. `axiom kill` toggles it; `axiom kill --clear` removes it. - **RPS limiter** — Per-host token bucket (default `max_rps_per_host: 5`). Hard cap on total requests per scan via `max_total_requests`. - **Budget cap & timeouts** — Per-agent budget, global deadline, hard 2x-budget timeout enforced by the orchestrator (`runPlan`). - **Audit log** — Append-only NDJSON at `.axiom/audit.log`. Every agent start, scope decision, finding write, kill-switch event, and report generation is recorded. - **Secret masking** — Secret-scanner findings always mask the value before persistence (`AKIA****...****MPLE`). `axiom auth login` records field **names** only, never values or tokens. - **Loopback-only dashboard** — Refuses to bind `0.0.0.0` unless `--allow-external`. Sets `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy: no-referrer`. No CDN, no remote scripts, no remote fonts. - **Hermetic marker probes** — Reflection / open-redirect canaries use the unresolvable `axiom-canary.invalid` domain; markers carry per-finding `axm_` IDs so they can be unambiguously attributed in the live DOM later. ## Findings and verification Each finding carries a `severity` (`info | low | medium | high | critical`), a `confidence` (`unconfirmed | low | high | verified`), and — once browser-verified — a `verification_status`: | `verification_status` | Meaning | |---|---| | `verified_xss` | Marker rendered in script context (inline `