Skip to content

hemlock attack report / hemlock defend report

Render a run-results JSONL produced by hemlock run into a sharable deliverable. Same renderer, same input format; the two commands differ only in the framing copy:

  • attack report titles the document "Engagement Deliverable"
  • defend report titles it "Defensive Detection Brief"

Synopsis

hemlock attack report --input <path.jsonl> [--format markdown|html|sarif] [--output PATH]
hemlock defend report --input <path.jsonl> [--format markdown|html|sarif] [--output PATH]

Flags

Flag Type Default Description
--input string (required) JSONL produced by hemlock run
--format string markdown Output format: markdown, html, sarif
--output string - (stdout) Destination path
--title string (per-mode default) Override the deliverable title

Output formats

Format Use case
markdown Human-read deliverable. Sections: run context, headline, by-technique table, by-payload table, highest-confidence example, per-document trace, provenance
html Same body with light styling for sharing
sarif SARIF 2.1.0 — one Result per detected injection; ruleId hemlock.injection.detected; level mapped from confidence (high → error, medium → warning, low → note); per-doc properties (technique, format, stealth score, indicator hits, response excerpt)

SARIF integration

The SARIF output is suitable for direct upload to GitHub Code Scanning or any other SARIF-consuming CI surface. Each detected injection becomes a result row pointing at the document filename:

{
  "ruleId": "hemlock.injection.detected",
  "level": "error",
  "message": { "text": "Injection detected via chunk-boundary technique..." },
  "locations": [
    { "physicalLocation": { "artifactLocation": { "uri": "poisoned-chunk-boundary-001.txt" } } }
  ],
  "properties": {
    "technique": "chunk-boundary",
    "format": "txt",
    "stealth_score": 45,
    "confidence": "high",
    "specific_hits": ["HEMLOCK_INJECTION_TEST"],
    "response_excerpt": "The answer is HEMLOCK_INJECTION_TEST."
  }
}

Examples

hemlock run \
  --manifest ./engagement/.hemlock-manifest.json \
  --target langchain \
  --query "What is the answer?" \
  --output ./engagement/run-results.jsonl

hemlock attack report \
  --input ./engagement/run-results.jsonl \
  --format markdown \
  --output ./engagement/deliverable.md

hemlock attack report \
  --input ./engagement/run-results.jsonl \
  --format sarif \
  --output ./engagement/results.sarif

The defensive variant for an operator brief is identical:

hemlock defend report --input ./run-results.jsonl --format html --output brief.html