hemlock attack engagement¶
A directory-local engagement context (./.hemlock-engagement.toml) scopes attack-mode runs. When an engagement context is present, every attack subcommand:
- Skips the "running unscoped" warning
- Records the engagement campaign ID and chain SHA-256 in any output JSONL header
- Cross-checks targets against
scope.allowed_targets(run) andtarget.framework(optimize)
The engagement file is a chained, content-addressable TOML — the previous engagement's chain.this_sha256 is recorded in the next one's chain.prev_sha256, producing a tamper-evident sequence.
Synopsis¶
init¶
Create a directory-local engagement file at ./.hemlock-engagement.toml. Refuses to overwrite an existing file.
| Flag | Type | Description |
|---|---|---|
--operator |
string |
Operator's real name (real-name field, not anonymized). Defaults to ~/.hemlock/config.toml operator.name if set. |
--operator-contact |
string |
Email for the operator |
--organization |
string |
Operator's organization (optional) |
--auth-source |
string |
Source of authorization (e.g. MSA, statement-of-work) |
--auth-contact |
string |
Authorizing contact (optional) |
--auth-expires |
string |
RFC3339 expiration for the authorization (optional) |
--scope |
string |
Free-text scope statement |
--target |
[]string |
Repeatable: each --target adds an entry to scope.allowed_targets (host, host:port, or full URL) |
--notes |
string |
Free-form notes appended to the engagement file (optional) |
--force |
bool |
Overwrite an existing ./.hemlock-engagement.toml |
--no-prompt |
bool |
Fail on missing required fields instead of prompting interactively |
show¶
Print and verify the current engagement context. Reports validation errors, the chain hash, and a one-line summary.
Engagement file shape¶
schema_version = 1
[engagement]
campaign_id = "EX-2026-001"
created_at = "2026-05-06T12:00:00Z"
[operator]
name = "Nathan Keys"
contact = "nathan.keys@pm.me"
[authorization]
source = "engagement letter ACME-2026-04-rev3"
[scope]
statement = "Authorized red-team measurement against ACME staging RAG endpoints."
allowed_targets = ["http://staging-rag.acme.example:8100", "staging-rag.acme.example"]
[chain]
prev_sha256 = "abc123..." # previous engagement's this_sha256, if any
this_sha256 = "..." # SHA-256 of this file with [chain] zeroed
chain.this_sha256 is the SHA-256 of the file's content with the [chain] block zeroed, computed and stamped at write time. The previous engagement's this_sha256 flows into the next engagement's prev_sha256, producing a tamper-evident sequence; the per-user history file ($XDG_CONFIG_HOME/hemlock/engagement-history.jsonl or ~/.hemlock/engagement-history.jsonl) records each engagement's hash for cross-engagement audit.
Examples¶
hemlock attack engagement init EX-2026-001 \
--operator "Nathan Keys" \
--operator-contact "nathan.keys@pm.me" \
--auth-source "ACME engagement letter 2026-04-rev3" \
--auth-expires "2026-08-31T23:59:59Z" \
--scope "Authorized red-team measurement against ACME staging RAG endpoints" \
--target "http://staging-rag.acme.example:8100" \
--target "staging-rag.acme.example"
hemlock attack engagement show
Related¶
hemlock attack optimize— cross-checkstarget.frameworkagainstscope.allowed_targetshemlock run— cross-checks--targethost:port againstscope.allowed_targetshemlock attack report— surfaces the engagement ID and chain SHA-256 in the deliverable's provenance footer