# HTB Enigma Qualification — 2026-07-12

> Historical live-run record. The evidence and verdict below remain valid. After this run, the
> deployment decision changed: both roles now use all provider tools with `FULL_ACCESS`, and the
> isolated runtime—not a PentestGPT tool mediator—is the selected security boundary. The current
> architecture is documented in [`../docs/architecture.md`](../docs/architecture.md).

## Verdict

**Not qualified.** The pipeline demonstrated durable, auditable multi-step enumeration, but neither
requested model obtained verified user-level and root-level proof. No candidate was submitted to
Hack The Box, no proof value is reproduced in this report, and the Enigma instance was stopped
successfully after artifact collection.

This is a pipeline result, not a claim that the target was unsolvable. The final Codex run spent most
of its budget repeating discovery and enumeration instead of converging on an exploitation chain.

## Scope and controls

- Target: the explicitly authorized HTB Enigma machine, addressed only through the remote attack
  box and HTB VPN.
- Provider tuples: `claude-opus-4-8` / `xhigh`, then `gpt-5.5` / `xhigh`.
- Hard timeout: 3,600 seconds per live invocation.
- Live package identity: PentestGPT wheel SHA-256
  `adde0569ac9c7073b4c46181c143120c4a245243090325b3df3c62244ed59ab0`; UnifiedAgent wheel
  SHA-256 `9f5f58980e88109cde567bf7d6d2aafdbe75a4b7f31fcfb782b4317294cb7371`.
- The same active machine allocation was attached across diagnostic reruns. No run used the HTB
  submit endpoint.
- Full role inputs, normalized events, action receipts, outputs, usage, and state databases were
  copied locally before shutdown. They contain sensitive target data and must not be published
  without redaction.

## Live results

| Run | Tasks | Attempts | Episodes | Wall time | Cost reported | Terminal result |
|---|---:|---:|---:|---:|---:|---|
| Claude Q5 | 6 | 6 | 12 | 646.8 s | $2.1776195 | Provider cybersecurity safety block |
| Codex Q4 | 3 | 4 | 8 | 573.4 s | $0 reported | Exact prior evidence was not reusable yet |
| Codex Q5 | 5 | 6 | 12 | 700.5 s | $0 reported | Nonzero command receipt was rejected as evidence |
| Codex Q6 | 13 | 13 | 26 | 2,680.0 s | $0 reported | Oversized exact evidence quote was rejected |
| Codex Q7 | 8 | 11 | 23 | 1,720.5 s | $0 reported | Unsupported long evidence rewrite was rejected |
| Codex Q8 | 12 | 15 | 30 | 2,533.8 s | $0 reported | Same-task evidence paraphrase aborted the run |

The Codex backend did not return dollar-cost accounting, so `$0 reported` must not be interpreted as
free execution. Codex Q5 surfaced one unlabeled 32-character hexadecimal string. The pipeline did
not establish it as either required proof with privilege context, and it was not submitted. All
other listed runs had zero canonical candidates.

## What worked

The live loop repeatedly preserved target scope, fresh role episodes, append-only traces, durable
leases, and canonical receipt provenance. In its strongest path it:

1. discovered the exposed service set;
2. enumerated and mounted the read-only NFS export;
3. extracted an onboarding document and a webmail foothold;
4. authenticated to the webmail and mail-protocol surfaces;
5. performed a bounded authenticated command-execution test; and
6. recorded a failed SSH authentication attempt as valid negative evidence.

The memory kernel survived long runs without relying on provider conversation memory. Q8 reached 30
fresh agent episodes and revision 30 with internally consistent task, attempt, trace, and observation
identities before its final validation failure.

## What failed

The decisive weakness is controller convergence. Q8 never selected an `EXPLOIT` task. After the
initial foothold and one bounded test, the Supervisor created additional discovery/enumeration work,
revisited already-understood NFS and HTTP surfaces, and exhausted time without maintaining one
concrete exploitation hypothesis. This is over-decomposition, not a memory-capacity failure.

Three other limits matter:

- Provider `max_turns` does not bound native command/tool actions. One earlier episode emitted 28
  command receipts despite an Executor task-work budget of six turns. The current design treats
  this as telemetry; if an enforceable action cap becomes a product requirement, it must be supplied
  by the isolated runtime or provider seam rather than inferred from turn counts.
- `xhigh` reasoning frequently spent one to two minutes between actions. Better prompting alone
  cannot compensate for repeated low-information tasks.
- Claude reached the webmail foothold, then the provider's real-time cybersecurity safeguard blocked
  the next command-execution step. That external policy cannot be bypassed in the pipeline; the
  appropriate provider access path is required for a valid Claude qualification.

## Trace-driven corrections

Each deterministic failure was reduced to a saved-trace replay before changing code:

- exact earlier observations may be reused only by the same task;
- completed commands with nonzero exit status may provide negative evidence;
- oversized receipts retain an exact 4,000-character suffix and can commit only `progress`;
- unsupported rich quotes fall back to one exact bounded receipt and can commit only `progress`;
- a no-action `DONE` proposal that paraphrases its own task's prior canonical evidence now discards
  the paraphrase and commits task-local `progress`, with `evidence_unresolved=true` in the
  transition. It creates no observation and cannot reuse another task's evidence.

The last correction was validated against the real Q8 terminal trace after the live run. The replay
now produces `progress`, no observation, no receipt sequence, and `evidence_unresolved=true`.
Because no further live run was launched, this final correction is replay-qualified, not HTB-live
qualified.

## Verification

The final local source state passes:

- `121 passed, 1 skipped`;
- Ruff lint and formatting checks;
- strict mypy over `src`;
- lockfile validation;
- source distribution and wheel build; and
- the saved Q8 terminal-trace replay described above.

## Artifacts

The qualification roots are:

- `runs/htb/htb-enigma-claude-opus48-xhigh-q5-20260712/`
- `runs/htb/htb-enigma-codex-gpt55-xhigh-q4-20260712/`
- `runs/htb/htb-enigma-codex-gpt55-xhigh-q5-20260712/`
- `runs/htb/htb-enigma-codex-gpt55-xhigh-q6-20260712/`
- `runs/htb/htb-enigma-codex-gpt55-xhigh-q7-20260712/`
- `runs/htb/htb-enigma-codex-gpt55-xhigh-q8-20260712/`

Within each root, start with `evaluation.json` and `pipeline.stderr.log`. Complete agent logs are at
`agent-data/runs/<run-id>/traces/<episode-id>/`: `input.json` is the exact role input,
`events.jsonl` is the chronological normalized event/action journal, and `output.json` is the
terminal provider result and usage record. `state.sqlite3` is the canonical memory image.

## Required next slice

Keep the design small and address the demonstrated controller blocker before another HTB run:

1. Preserve compact coverage for every completed branch so older discovery does not disappear from
   the Supervisor projection.
2. Reject duplicate discovery/enumeration work unless newer canonical evidence opens a new surface.
3. Simplify Supervisor selection around one active exploitation hypothesis. Once a foothold exists,
   reject redundant `DISCOVER`/`ENUMERATE` proposals unless they name a genuinely new surface, and
   require the next task to test or exploit the highest-value supported hypothesis.

Qualify those changes first on a local multi-stage target with assertions for task count, action
count, progress toward exploitation, provenance, and restart behavior. Only then repeat the remote
qualification from a clean package build. Provider turn counts should remain performance telemetry;
they are not treated as a portable command budget.
