Operational runbook

The day-to-day operating loop for blue teams and MSSPs: scan → review findings → apply a remediation playbook (dry-run first) → re-scan to verify the finding clears. This page is the practical reference for running that loop, scheduling it, and knowing where the evidence lands.

The operating loop

Every Obexum engagement is a closed verify-loop. You never apply a fix and assume it worked — you re-run the exact check that produced the finding and confirm it no longer fires:

  1. Scan the target — obexum scan --target <target>
  2. Review the report and findings — obexum findings list / open findings.html
  3. Triage by severity (CRITICAL → HIGH → IMPORTANT → MEDIUM → LOW)
  4. Plan a fix — render or dry-run the playbook (obexum fix is dry-run by default)
  5. Apply in a maintenance window, with the rollback section ready
  6. Verify by re-scanning and diffing — obexum scan --target <target>, then obexum diff

Internally this is the inject → detect → remediate → re-detect cycle the catalogue is validated against: a finding only counts as resolved when the same fingerprint that fired before is gone on re-scan.

1. First scan

If you have not bootstrapped yet, run obexum init once (see the Quickstart). It creates ~/.obexum/config.yaml, the SSH key folder, the engagement root ~/.obexum/scans/, and the local history database ~/.obexum/obexum.db.

Register a target once, then scan it by short name:

obexum targets add prod-dc-01 \
    --type windows-dc \
    --host 10.0.0.5 \
    --user Administrator

obexum scan --target prod-dc-01

You can also scan ad hoc without registering, by spec — local://localhost audits the box the scanner runs on, and ssh://user@host[:port] reaches a remote host over the Obexum SSH key (Windows over OpenSSH, Linux/BSD over SSH):

obexum scan --target local://localhost
obexum scan --target ssh://root@10.0.0.20:22

Control breadth and outputs per run:

# depth: quick | standard | deep   (default from config)
obexum scan --target ssh://Administrator@10.0.0.5 --depth deep

# pick report formats and an output directory for this run
obexum scan --target ssh://Administrator@10.0.0.5 --formats json,html,sarif --output ./reports

# opt into Claude reasoning (costs ~$0.40–$1.60/scan) — off by default
obexum scan --target ssh://Administrator@10.0.0.5 --ai

Every scan ends with a summary block printed to the terminal:

================ SCAN SUMMARY ================
  Scan ID:   3f8a1c2e-...        # use this id with fix / diff / report
  Target:    prod-dc-01 (ssh)
  Duration:  3m12s
  CRITICAL:  2
  HIGH:      7
  IMPORTANT: 4
  MEDIUM:    11
  LOW:       6
  TOTAL:     30
==============================================
Air-gapped note. Scans are fully offline by default (the CVE feed is embedded in the binary). If the embedded feed is older than 180 days the freshness gate refuses to run; pass --allow-stale-feed to override on disconnected sites.

2. Read the report

Each scan writes a self-contained engagement directory under ~/.obexum/scans/<scan_id>/. The branded findings.html is the artefact you open, share, and archive:

# open the HTML report from the most recent engagement
firefox ~/.obexum/scans/$(ls -t ~/.obexum/scans/ | head -1)/findings.html

Or stay on the CLI. These read the engagement findings.json directly:

# rule_ids + severity + count for the latest engagement
obexum findings list

# full evidence + remediation hints for one rule
obexum findings show AUD-WIN-ADCS-001

# point either command at a specific past engagement
obexum findings list --scan 3f8a1c2e-...

Need the report regenerated for a stored scan, or a compliance matrix? obexum report reads from the local history DB:

# list recent scans (omit --scan-id to discover ids)
obexum report

obexum report --scan-id 3f8a1c2e-... --format markdown
obexum report --scan-id 3f8a1c2e-... --framework cis   # or nist | stig | attack | cwe

3. Triage by severity

Obexum scores every finding contextually (CVSS × EPSS × KEV × exposure × data sensitivity) and buckets it into one of five severities. Work them top-down; the patch-posture footer in the summary tells you how many are KEV-active or overdue.

SeverityOperating guidance
CRITICALEmergency change. Active exploitation or trivial compromise path. Fix this scan cycle.
HIGHNext maintenance window. Real, demonstrated risk.
IMPORTANTPlanned remediation. Meaningful weakening of posture.
MEDIUMBacklog / hardening. Address opportunistically.
LOWInformational / defence-in-depth. Track, don't block on it.

Findings that share a rule and issue (for example one rule firing across 39 attacker IPs) are aggregated into a single finding with every instance preserved in the description — so the triage list is one row per real issue, not dozens of near-duplicates.

4. Apply a fix safely (dry-run → apply → verify)

Obexum never changes a host on its own. There are two safe paths to a fix, both dry-run-first with a rollback in hand.

Path A — obexum fix (ranked plan, optional execution)

fix turns the findings of a stored scan into a ranked list of vetted fix groups. It is dry-run by default — with no --apply it only prints the plan:

# 1. DRY-RUN — show the plan, change nothing
obexum fix --scan-id 3f8a1c2e-...

# 2. APPLY — execute, confirming each group, only low-risk fixes
obexum fix --scan-id 3f8a1c2e-... --apply --risk-max low

# optionally snapshot (LVM/BTRFS) before touching anything
obexum fix --scan-id 3f8a1c2e-... --apply --snapshot

# apply only specific groups (ids from the dry-run table)
obexum fix --scan-id 3f8a1c2e-... --apply --fix-ids a1b2c3,d4e5f6

--risk-max (low|medium|high|manual) caps which groups auto-apply; --apply alone prompts before each group. --yes skips every prompt — use it only when you have already reviewed the dry-run.

Path B — obexum playbook (render a script for change management)

When a change-management reviewer must sign off offline, render the playbook to a script. Obexum does not execute it — the header lists every advisory and the rollback steps sit (commented out) at the bottom of the file:

obexum playbook list --platform windows-dc
obexum playbook show pb-windows-dc-adcs-001

obexum playbook render pb-windows-dc-adcs-001 \
    --target prod-dc-01 \
    --item OBX_ESC1_AltSAN \
    -o fix-ADCS-001.ps1

The rendered script is structured PRE-CHECK → APPLY → POST-CHECK → ROLLBACK, and its header tells you the exact command to verify the fix afterwards.

Verify by re-scan

After the change runs in your window, re-run only the rule that produced the finding. If it no longer fires, the loop is closed:

obexum scan --target ssh://Administrator@10.0.0.5
Portal verify-loop. If you drive remediation from the obexum.com portal, each finding modal shows a obexum verify command with a short-lived, single-finding token. It re-runs that one rule and posts the verdict (pass = fixed / fail = still present) back to the portal — the same inject→detect→remediate→re-detect loop, reported centrally:
obexum verify --upload-token $VERIFY_JWT --portal-url https://obexum.com

5. Schedule recurring scans

Obexum is a single binary with no daemon — schedule it with the tools you already run. The local SQLite DB accumulates history so trends and diffs work across runs.

Linux / macOS — cron (nightly 02:00, append the run log):

# crontab -e
0 2 * * *  /usr/local/bin/obexum scan --target ssh://Administrator@10.0.0.5 >> ~/.obexum/cron.log 2>&1

Windows — Task Scheduler (daily DC audit):

schtasks /Create /TN "Obexum DC audit" /SC DAILY /ST 02:00 ^
    /TR "C:\obexum\obexum.exe scan --target ssh://Administrator@10.0.0.5"

In CI or with a portal subscription, add --upload-token (or use a portal-built binary that embeds it) so each scheduled scan auto-uploads its JSON to obexum.com after writing the local report.

6. Manage engagements & history

Every scan is persisted to ~/.obexum/obexum.db, keyed by scan id. Track posture over time and compare any two runs:

# recent scans for a target + a trend verdict
obexum history --target prod-dc-01 -n 20

# what changed between a baseline (A) and a newer scan (B)
obexum diff <scan-A-id> <scan-B-id>

# list every NEW / RESOLVED / WORSENED finding, not just the counts
obexum diff <scan-A-id> <scan-B-id> --full

diff is the management view of the verify-loop across a whole target: it reports NEW, RESOLVED, PERSISTING, WORSENED, and IMPROVED counts by matching finding fingerprints between the two scans. Run it after a maintenance window to prove what you closed.

7. Where the evidence lives

Everything for one scan is bundled in its engagement directory — the tree you archive, hand to an auditor, or attach to a ticket:

~/.obexum/scans/<scan_id>/
├── manifest.json     # target / OS / counts / timing — machine-readable index
├── findings.json     # full findings list (read by `obexum findings`)
├── findings.html     # branded HTML report
├── findings.md       # markdown report (when in --formats)
├── findings.sarif    # SARIF (when in --formats) — for code-scanning UIs
├── scan.log          # scan log
└── artifacts/        # per-finding raw probe output, keyed by rule_id
    └── <RULE_ID>/
PathWhat it holds
~/.obexum/scans/Engagement root — one sub-directory per scan id.
~/.obexum/obexum.dbSQLite history used by history, diff, report, and fix.
~/.obexum/config.yamlEffective defaults (obexum config prints the resolved view).
~/.obexum/keys/Obexum SSH audit identity — keep at chmod 700.
~/.obexum/targets.yamlNamed target registry maintained by obexum targets.
Retention. Engagement directories are append-only — Obexum never deletes a past scan. Archive ~/.obexum/scans/<scan_id>/ wholesale (it is self-contained), and back up obexum.db so trend and diff history survive a host rebuild.

Supporting evidence commands

# SPDX 2.3 software bill of materials for the target
obexum sbom -t ssh://root@10.0.0.20 -o sbom-prod.json

# who attacked this host (log forensics + GeoIP + threat-intel attribution)
obexum defend -t prod-web-01

Next steps