Security properties

What the record proves, and what it does not.

Agentmetry is an evidence and coverage sensor, not a sandbox and not a policy enforcement plane. The properties below are the ones a security architect will test in the first meeting. They are stated at the strength the code actually has.

Provenance of the trail

Hash chain

agentmetry verify --trail walks each JSONL line: sequence number and SHA-256 over the previous hash plus the canonical event. A deleted or edited line is detectable.

RFC 6962 Merkle root

The heartbeat carries a Merkle root and tree size over the trail. That is a periodic commitment that lands in the SIEM, outside the endpoint's blast radius. It is not a per-event chain proof. Direct SIEM push strips the chain envelope. Tailing the JSONL with a collector would keep it.

External anchors

Checkpoints of (tree_size, root) can be published off the host. An edit below that size stops matching a value the machine can no longer retract. The default anchor log sits beside the trail; copy it off the box.

Evidence packs

Exports include a SHA-256 integrity manifest over the included events. That is a bundle you can hand to an incident, not a certification.

See it

Prove one record without handing over the rest.

The chain answers whether a file was altered, but proving one event with it means handing over every event before it. The Merkle tree over the same record hashes answers it in a few hashes, against a root the heartbeat has already published. This is that tree, built in your browser by the same RFC 6962 rules as trail_merkle.py, over the home page's thirteen records.

Records at the bottom, the published root at the top. Orange hashes are the proof.

Building the tree…

The proof: 0 hashes, 0 bytes

    That and record 9 are all a verifier is given. The other 12 records stay private.

    published root
    …
    recomputed
    …

    Verifying…

    The check that counts is against a root recorded where the audited machine cannot rewrite it, such as the heartbeat in your SIEM. A proof that only matches the root it carries shows it is well formed, not that the trail was not rewritten. On a real trail the same proof is about 1.2 KB against 8.3 MB.

    See it fail

    The rewrite the chain cannot catch, and what does.

    An edit breaks the chain. Recomputing every hash after the edit mends it, and anyone with the whole machine can do that. What they cannot do is change a root that was published off the host before they arrived. Play both moves on the same thirteen records, hashed in your browser by the ports of trail_chain.py and trail_merkle.py.

    Red: verify cannot vouch for it. Amber: re-hashed, and the chain cannot tell.
    On the machine: agentmetry verify --trail
    …
    Off the host: checkpoint, tree size 13

    anchored …

    now …

    Thirteen records, chained, and a checkpoint of their root already published off the host.

    What the chain does not prove

    A well-formed chain proves ordering and non-modification of the bytes that were written. It does not prove who wrote them: anyone with write access to the trail can build a valid chain. In the open-source sensor that stays true, because a single machine recording itself never needs a fleet identity. The Enterprise package adds per-host Ed25519 signing of forwarded events, verified by the console against each host's registered key. That is a first cut, built and tested, not yet run on a customer fleet. Tamper-evident is not the same as attributable. Say that before a reviewer does.

    Coverage attestation

    Default interval 300s. The heartbeat reports each checkable agent surface as one of four states, because a boolean was answering two different questions.

    covered
    Agent is installed here, and our hook is in its config.
    uncovered
    Agent is installed here, and our hook is not. This is the incident.
    absent
    Agent is not on this machine. Not a finding.
    unknown
    Cannot determine. A service profile (the MSI's virtual service account) degrades the beat on purpose: Path.home() there is not a developer.

    Codex trusts hooks by hash and skips untrusted ones silently. A file check cannot see that decision. Covered is not the same as capturing for Codex.

    Defaults that look like controls

    DLP and tool policy default to log

    Regex scanning of tool arguments runs in the hook process. Block mode exists and is the only path that stops a call before it runs. Shipping default is log. Do not describe this as a policy enforcement layer.

    Sequence detection, 14 built-in rules

    Findings are events on the same trail. They are not preventions. The public benchmark covers 13 of those 14 rules across 54 recorded sessions (26 attack, 28 benign). agentmetry benchmark exits non-zero on a miss or a false positive. The README quotes that output and CI fails if the quote drifts.

    Approvals are inferred

    IDEs do not always report that a human clicked approve. When a tool runs after an ask, the recorder may emit an approval_response flagged reason: inferred:*. That is a reconstruction, not a native approval workflow the product owns.

    The coverage gap

    Agentmetry sees the agents it is wired into. An unmanaged ChatGPT tab, Microsoft 365 Copilot, or Cursor with hooks deleted is invisible to it. That is network, CASB, and endpoint policy territory. Every competitor's homepage omits this sentence. It is the first thing a CISO should hear.

    Fleet packaging, stated as it is

    The Enterprise MSI installs, upgrades and uninstalls in CI on a clean Windows runner, with the service running as a virtual account. It has not been run against a customer Intune tenant. It is not EV-signed and is not a clean-room certified build. Intune Remediations need Plan 2 or Windows Enterprise E3/E5, not base Intune. The Splunk TA is a private add-on, not a Splunkbase listing, and is not AppInspected.

    Continuity

    One maintainer. The Apache-2.0 core is the floor: trails, detections, and forwarders do not depend on a vendor cloud remaining available. Enterprise pilots get a perpetual license, a source deposit with each delivery, and an automatic Apache-2.0 grant on a Continuity Event (cessation, insolvency, or incapacity). The clause is in the pilot SOW. Trails stay readable with or without us.

    Report a vulnerability via SECURITY.md. For how the recorder is built, start at the product page.