Documentation

Everything on this page covers the open-source CLI, licensed Apache 2.0. It is complete: nothing below requires an account, a key, or a server.

Install

pip install attestral
attestral --version

Python 3.10+. The core has two dependencies (click, pyyaml). Optional LLM elicitation adds the anthropic package: pip install "attestral[llm]".

Try the full loop on the bundled demo:

git clone https://github.com/attestral-labs/attestral && cd attestral
attestral scan examples/demo-project
attestral compile examples/demo-project -o policy.yaml
attestral drift policy.yaml examples/demo-project/runtime-events.jsonl

The loop

Attestral treats the design review, the runtime policy, and the audit evidence as one artifact in three forms:

attestral scan

attestral scan PATH [-o STEM] [--format md|json|both] [--llm] [--fail-on SEVERITY]
FlagBehavior
-o, --outputOutput file stem (default attestral-report).
--formatmd for the human report, json for the chained evidence, both (default).
--llmAdds LLM threat elicitation on top of the deterministic layer. Requires ANTHROPIC_API_KEY. LLM findings are tagged origin: llm and never mixed silently with rule findings.
--fail-onExit non-zero if findings at or above this severity exist. Works as a fail-closed CI gate.

Ingestion is automatic: *.tf files feed the cloud model; mcp.json, *.mcp.json, and claude_desktop_config.json feed the agent-runtime model.

attestral verify

attestral verify report.json

Recomputes the hash chain offline and exits 0 (VALID) or 1 (INVALID). No network, no server, no account. An auditor can verify a two-year-old report on an air-gapped laptop.

attestral compile

attestral compile PATH [-o mcp-guard-policy.yaml]

Compilation is fail-closed by construction:

Do not hand-edit a compiled policy. Change the design, re-run the review, re-compile. If policy and review can diverge silently, the evidence is worthless. That is the point of the binding.

attestral drift

attestral drift POLICY_FILE EVENTS_FILE [--fail-on-drift]
RuleSeverityFires when
DRF-001criticalA server appears in telemetry that is not in the attested design.
DRF-002criticalA server the review denied is invoked at runtime.
DRF-003highA filesystem path outside the attested roots is accessed.
DRF-004highA TLS-constrained server is observed over plaintext.

--fail-on-drift exits non-zero on any finding, so drift checks run as a CI step or a cron job against yesterday's telemetry.

Writing rules

Rules are YAML with structured matchers. There is no eval anywhere, and an unknown matcher fails closed: the rule simply never matches.

rules:
 - id: ORG-001
    title: Internal ALB missing auth attribute
    severity: high
    target: aws_lb            # component type prefix, or "model"
    match: { attr_missing: auth }
    description: ...
    recommendation: ...
    frameworks: ["NIST AC-3", "SOC2 CC6.1"]
MatcherSemantics
attr_equalsAttribute equals value exactly.
attr_inAttribute is one of the listed values.
attr_missingAttribute is absent from the ingested design.
attr_starts_with / attr_containsString prefix / substring on the attribute.
attr_list_contains / attr_list_any_ofMembership tests over list attributes.
attr_any_containsAny of several needles across one or more attributes.
model_has_bothModel-level: both component type prefixes exist in the design.

Load custom packs alongside the core pack via RuleEngine(["org_rules.yaml"]).

Evidence chain

Every run commits its findings to a SHA-256 hash chain: entry N hashes the canonical JSON of finding N together with the hash of entry N−1, starting from a zero genesis. The final hash (the chain head) appears in the report header and in every compiled policy.

The consequence: altering, inserting, or deleting any past entry changes every subsequent hash. A reviewer who records the chain head (in a PR comment, a ticket, an email) has permanently committed the whole review.

Telemetry format

drift reads JSONL, one event per line. mcp-guard emits this format natively, and anything else can adapt to it in a few lines:

{"ts": "2026-07-10T14:01:02Z", "server": "docs", "tool": "read_file", "args": ["/srv/docs/design.md"]}
FieldRequiredMeaning
serveryesMCP server name as configured.
toolyesTool invoked.
argsnoArguments; paths are checked against attested roots.
urlnoTransport endpoint; checked against TLS constraints.
tsnoISO-8601 timestamp, carried into drift findings.

GitHub Action

Run drift checks on a schedule so conformance is continuous, not annual:

- uses: attestral-labs/attestral@v1
  with:
    policy: policy.yaml
    events: events.jsonl

A complete nightly workflow (pull telemetry, re-compile the policy from the reviewed main branch, drift-check) ships in examples/github-actions/drift-schedule.yml. The mcp-guard telemetry emitter lives in integrations/mcp-guard/.

Terraform extra

The core ships a dependency-free Terraform scanner. For full-fidelity HCL parsing (nested blocks, correct types), install the extra. Attestral picks it up automatically and falls back gracefully on malformed files:

pip install "attestral[terraform]"

Roadmap

Attestral is an open-source project. Everything documented above is the complete, current surface. Next up, roughly in order: a full HCL expression evaluator, more rule packs (Kubernetes, GCP, Azure), PR design-diffing, and import from legacy threat modeling exports. Issues and contributions are welcome on GitHub.