Skip to content

ADR-0082: KALI.Art Phase A — operator-usable pen-test pod

  • Status: Accepted
  • Date: 2026-05-23
  • Driver: discuss_module_kali_art_2026_05_10 locked KALI.Art as "the pen-tester's standard distribution complement to DoYour.Art (which is craft-your-own code)." The v3.7.0 scaffold (PR #678 family — KALI-1) shipped the pod + gVisor RuntimeClass + ttyd launcher + 9 TypeScript schemas; the operator surface was a placeholder until K-A1.
  • Related: PRs #1012 (K-A1), #1013 (K-A2), #1014 (K-A3), this PR (K-A4); ADR-0025 (offensive-suite parent), ADR-0081 (DoYour.Art Phase A — same operator-surface pattern).

Context

The KALI.Art pod (kali-art/), gVisor RuntimeClass (gvisor-offensive, shared with doyour-art), VLAN 2902 NAD, ttyd launcher (Go) + UTXO licence-token gate stub shipped earlier this year. 9 TypeScript schemas in dashboard/src/lib/kali/ (audit, ai-companion, exploit-pattern, nmap-import, pdf-report, pie-workflow, quick-launch, span-comparison, tier-gate) captured the wire shapes. None of this was usable by an operator: there was no dashboard route, the pod's /rpc endpoint did not exist, and the AI Companion / Quick-Launch were schema-only.

The dashboard-only operator-access invariant (project_dashboard_only_operator_access_2026_05_13) treats a feature without UI as incomplete. Phase A closes that for KALI.Art.

Decision

Ship KALI.Art Phase A as 4 sub-PRs, mirroring the DoYour.Art Phase A pattern. The 6 open questions from the discuss memo (locked defaults in the memo's "Addendum 1") are reaffirmed verbatim:

# Question Decision
1 Persistent home quota Team 1 GB / Enterprise 10 GB (locked)
2 Multi-user collaboration 1 session per operator (no shared sessions)
3 Custom tool installation apt install writes to overlay layer that resets on session end
4 Kali version pinning Rolling release + weekly snapshot via CLONER fn 7
5 Free trial Zero free (hard Team+ gate)
6 Compliance bundle SOC 2 Type II covers KALI at base level; dedicated audit pack add-on for FIPS / banking

Phase A sub-PRs

Sub-PR Scope Status
K-A1 Dashboard route /art-studio/kali (5th tab), session-store.ts (in-memory dual-mode-ready), 4 API routes, tier-gate enforcement (403 Free/Indie + 429 concurrent + 403 prod-DOM), 25 i18n keys × 3 locales ✅ #1012
K-A2 Pod /rpc server on :8084 using pkg/cross-module-rpc.Authorize. 3 tools (nmap-quick-scan, sslyze-handshake-probe, nikto-baseline) with target validation + binary_missing branch. ACL ConfigMap. Closes the cross-MÓDULO loop with DoYour.Art (template scapy-plus-kali-nmap.py now end-to-end) ✅ #1013
K-A3 Sidebar: Tool Quick-Launch (15 curated tools × 5 categories) + AI Companion chat stub (4-bucket regex keyword map → suggestion list). API /api/kali/ai-companion. 15 i18n keys × 3 locales ✅ #1014
K-A4 This PR — ADR + module-docs in 3 langs + recovery-memo entry

Shared security envelope

  • gvisor-offensive RuntimeClass (runsc) — syscall isolation, shared with DoYour.Art.
  • VLAN 2902 macvlan, subnet 172.21.0.0/16. NetworkPolicy egress allow-list = DUT INSIDE only; OOBI fabric blocked from KALI's data-plane NIC; customer's MGMT (via RELAY) HARD BLOCKED.
  • Non-root user (UID 1000), no ServiceAccount token mounted, no ConfigMap / Secret access beyond the ACL mount.
  • Cross-MÓDULO /rpc default-deny on both sides (ACL Go lib + ConfigMap matching platform/cross-module/acl.yaml).
  • Audit log mandatory (auditd + shell history JSONL → sealed audit hash-chain). Retention 90 d (Team) / 7 y (Enterprise).
  • AI Companion HARD rule: never executes shell commands autonomously — every suggestion is operator-confirmed in the terminal.

DOM mode interaction (carried forward from discuss memo)

DOM mode Phase A behaviour
greenfield / staging / lab ✅ Full enable. Default.
production 🚨 HARD BLOCKED in Phase A (403 from /api/kali/sessions). PIE workflow approval + read-only-tools subset lands in K-A5 / Phase B follow-up.
prod-partition ⚠ Enable with partition-scoped target enforcement (not in Phase A; deferred).

Consequences

Positive

  • The dashboard-only invariant is satisfied for the second member of the offensive suite (DoYour.Art was the first; KALI.Art now matches).
  • The 4-sub-PR cadence keeps each merge small + reviewable + revertable.
  • The cross-MÓDULO loop with DoYour.Art is closed end-to-end — operators can now write doyour_sdk.invoke("kali-art", "nmap-quick-scan", ...) from a Scapy art piece and KALI answers from the real pod (template scapy-plus-kali-nmap.py).
  • The 3 tools served by /rpc map 1:1 to the ACL entries shipped in Phase D-1 — wire stability across MÓDULOs.

Negative / deferred

  • K-A5 / Phase B still owes:
  • PIE workflow integration (operator-confirmed production override + read-only-tools subset)
  • ttyd iframe embedded inside the session page (Phase A surfaces "Session id" + terminal-pending box; the real iframe needs Service exposure work + same-origin reverse-proxy plumbing)
  • Real MCP bridge (kali-art-mcp sidecar fork of mcp-kali-server upstream) replacing the AI Companion stub
  • Audit log + PDF report wiring (schemas exist; transport doesn't)
  • PVC kali-home per-operator persistence
  • The 9 schemas in dashboard/src/lib/kali/ (audit, exploit-pattern, nmap-import, pdf-report, pie-workflow, span-comparison) are not yet exercised by the UI. Phase B picks them up one at a time.
  • The 12-PR roadmap from the discuss memo (K-1 through K-12 + the AI/Caldera Addendum's K-13..K-15) was reorganised into Phase A (K-A1..K-A4) + Phase B (K-B1+). The implementation plan in the memo is now superseded by this ADR.

Alternatives considered

  • Skip K-A2 (no cross-MÓDULO /rpc) — would have left the Phase D-2 SDK template (scapy-plus-kali-nmap.py) dangling. Rejected: cross-MÓDULO is the moat differentiator (no competitor has it).
  • Pin Kali to a snapshot for reproducibility — rejected per the discuss memo Q4 decision: rolling release + weekly snapshot via CLONER fn 7 + operator can opt to pin per-session.
  • Open KALI.Art to Free tier with a 1-hour trial — rejected per Q5: hard Team+ gate. Trial path is via the conference-sandbox account, not the production UI.
  • Build the AI Companion before the cross-MÓDULO RPC — rejected: RPC is the operator-visible value (running an actual nmap), AI Companion is icing. K-A2 ships first; K-A3 builds on it.

Compliance

Per CLAUDE.md: "Dashboard is the ONLY operator interface." Phase A delivers every operator-facing primitive (session create / list / end, AI suggestion, Quick-Launch pick) via /art-studio/kali/*; no kubectl exec into the kali pod required.

Per the locked ZTP-prem posture: Tier B obfuscation preserved (pod stays on ztp-prem.tlsstress.art/tier: B label). gosec W0 baseline stays at 0 findings post-merge (4 new inline-annotated #nosec for the launcher's intentional exec.Command(ttyd) + os.OpenFile(audit_path) + os.MkdirAll(audit_dir) + log-with-env-var-arg; documented rationale per site).

References