This is the operator's view of the POC lab: every container, every port, the exact path a real
CVE travels from a real scan to a real Ansible patch to a real re-scan that proves it's gone.
Nothing here is simulated — the software is real, the scanner reads real installed versions,
and the patch is a genuine ansible-playbook run.
CSX saw the simulated loop. This lab shows the same loop running on real software: real CVEs in real Tomcat / Liberty / log4j / OS packages, found by a real scanner, fixed by real Ansible.
Everything runs in containers on one machine, on an isolated network. No CSX system is touched, no approvals needed. Repeatable in seconds, demoable on a laptop.
The scanner reads the real installed version over SSH. A finding clears on re-scan only because Ansible genuinely changed the version — there is no scripted "now it's fixed."
Apache Tomcat 9.0.30 — CVE-2020-1938 Ghostcat (9.8)
log4j-core 2.14.1 — CVE-2021-44228 Log4Shell (10.0)
Open Liberty 21.0.0.11 — CVE-2023-38737 SSRF
Ubuntu 18.04 OpenSSL — CVE-2022-0778
nginx (18.04) — CVE-2019-20372
Version probe over SSH + Trivy. Canonical + Qualys-XML findings.
Real ansible-core + HTTP runner. Returns the real PLAY RECAP.
ServiceNow Table API mock — change/approval workflow.
Qualys VMDR API emulator over the lab findings.
Runs the whole loop standalone and prints each step.
FastAPI control plane — the twelve agents + policy gate.
Next.js dashboard — the screen CSX watches.
Findings, plans, executions, reasoning traces.
Bus pub/sub + rate limiting.
fixed_versionapprovedansible-playbook upgrades the targetThe scanner's fixed_version for each CVE is the single source of truth: the Patch Hunter reports it, and the Ansible playbook installs exactly that version. The fix the scanner names is the fix that gets applied — no guessing, no drift.
Standalone: the orchestrator container runs steps 1–6 and prints them — proves the software loop on its own.
Through Mythal: the twelve agents drive the same connectors, so the console shows the loop with full reasoning traces (the wiring milestone).
e.g. readlink /opt/tomcat → apache-tomcat-9.0.30; or the log4j jar filename; or dpkg-query for OpenSSL.
cve_map.yaml holds the affected range + fixed_version per CVE. In-range → finding emitted.
Canonical JSON for the Scanner Liaison, and Qualys-VMDR XML for the Qualys connector.
The Executor (or the orchestrator) POSTs to ansible-control:8099/run with the playbook, the target, and the scanner's fixed_version. The control node shells out to a real ansible-playbook over SSH, snapshots the target for rollback, upgrades the software, restarts the service, and returns the real PLAY RECAP.
That recap (ok / changed / failed) is exactly what lands in the Mythal executions table and streams to the console — same UI as the simulated path, now backed by a real change on a real host.
Serves the real ServiceNow Table API path — /api/now/table/change_request. Mythal opens a change when a plan is built, reads approval at the gate, and closes it on verification. Point the connector at a real ServiceNow instance and only the base URL changes.
Serves the lab findings on Qualys's real path — /api/2.0/fo/asset/host/vm/detection/ — behind HTTP Basic auth. Mythal's Qualys connector talks to it exactly as it would to a real subscription. When CSX is ready, swap the base URL + credentials; nothing else changes.
The orchestrator prints each step with the real CVEs, the real ServiceNow change numbers, and the real Ansible recap:
CVE-2021-44228 on target-log4shell, KEV, CVSS 10.0, fix 2.17.1.
changed=6, failed=0 — the jar on disk is replaced.
The CVE is simply no longer there.
| Service | URL | Key endpoints | Health |
|---|---|---|---|
| Mythal console | localhost:3090 | Command Center, Findings, Plans, Activity, Integrations | open in browser |
| Mythal API | localhost:8090 | /health, /api/*, /presentation/ | /health |
| Scanner | localhost:8096 | POST /scan/run, /findings, /findings/qualys | /health |
| Ansible control | localhost:8099 | POST /run, /ping | /health |
| ServiceNow (mock) | localhost:8097 | /api/now/table/change_request | /health |
| Qualys (emulator) | localhost:8098 | /api/2.0/fo/asset/host/vm/detection/ | /health |
| Targets (SSH) | localhost:2210-2214 | root / ansible (debug only) | — |
All host ports sit outside the in-use block on this machine. The lab runs entirely over its internal poc-net bridge; the exposed ports are for inspection and demo convenience.
Five vulnerable targets, a real scanner, real Ansible, ServiceNow + Qualys integration shapes, and an orchestrator that proves scan → patch → verify end to end.
Point the Mythal Scanner Liaison, Executor, and Verifier at packages/connectors/poc/ so the console shows the real loop with full agent reasoning traces — not the standalone orchestrator.
Add OpenVAS for a "watch a network scan" moment, AWX for a real Ansible job-template UI, and more targets — each is a documented drop-in.