VIRP does not let AI speak first. Reality speaks first, inside a bound session.
Cryptographic trust primitives for AI agents operating on real infrastructure.
When an AI agent tells you your firewall policy is misconfigured, can you prove it actually checked?
When it says a BGP session is established, did it read that from a real device — or fabricate it?
When it claims a config change succeeded, where is the evidence?
VIRP makes every agent claim verifiable. Not with prompts. Not with guardrails. With cryptography.
VIRP is an open protocol that signs every device observation at the point of collection, before the AI ever sees it.
A dedicated process — the O-Node — connects to your network devices, captures raw output, and signs it with HMAC-SHA256. The AI agent receives pre-signed data. It can reason about what the device returned. It cannot forge it, modify it, or fabricate it — because it never holds the signing key.
This is not a policy. It is a code path.
Agent: "FortiGate policy 2 allows all traffic with no AV/IPS."
VIRP:
verdict: VERIFIED
HMAC: da383afe...c18
chain_seq: 4882
session_id: f84c1a3e...
device_id: 0x00000002 (FW-01)
command_hash: 7c2b4d3a... (show firewall policy 2)
timestamp: 2026-03-11T14:30:22.917384Z
Verify it yourself.
During development of IronClaw, we observed an AI system:
- Generating firewall policies with valid UUIDs that did not exist
- Reporting threats from RFC 5737 documentation addresses
- Proposing routing changes based on fabricated OSPF adjacency states
Every output was technically plausible. None of it was real.
Prompt engineering, output validation, and behavioral guardrails did not fix it. The AI fabricated output directly in its response text without invoking the signed execution path.
VIRP is the structural fix.
┌─────────────────────┐ ┌─────────────────────┐
│ AI Node (CT 210) │ │ O-Node (CT 211) │
│ │ │ │
│ Agent + LLM │─────▶│ VIRP C Library │
│ │ │ Device Credentials │
│ Zero credentials │ │ Signing Keys │
│ Zero signing keys │◀─────│ Chain Database │
└─────────────────────┘ └──────────┬──────────┘
│ SSH
┌──────────┼──────────┐
Cisco IOS FortiGate PA-850
The Cage — three structural walls enforce isolation:
| Wall | Mechanism |
|---|---|
| 1 | AI node has no network route to devices |
| 2 | Device ACLs accept SSH from O-Node IP only |
| 3 | O-Node socket locked to authorized processes |
| # | Name | What It Does | Status |
|---|---|---|---|
| P1 | Verified Observation | Device output HMAC-signed at collection | Production |
| P2 | Tiered Authorization | Command classification enforced below AI | Production |
| P3 | Verified Intent | Signed proposals before execution | Implemented |
| P4 | Verified Outcome | Before/after signed comparison | Implemented |
| P5 | Baseline Memory | Deviation detection from signed history | Implemented |
| P6 | Trust Chain | SQLite tamper-evident chain | Implemented |
| P7 | Trust Federation | Ed25519 cross-tenant verification | Implemented |
Production primitives have accumulated operational history across real deployments. Implemented primitives are complete, tested, and exercised in integration runs, but have not yet accumulated equivalent production hours.
VIRP has been running continuously on production infrastructure since March 2026.
- 66 days of continuous operation at time of this writing
- 2,024 cryptographically linked chain artifacts across 81 sessions
- 99.9% chain integrity (verified against full export)
- 35-router BGP topology: full verification under 60 seconds
- FortiGate audit: 15 findings on real hardware, zero false positives
Fabrication is prevented by protocol design, assuming the O-Node is uncompromised. See SECURITY.md for the full trust boundary analysis, including known open work on TCP-path mutual authentication.
# Dependencies (Debian/Ubuntu)
sudo apt install -y build-essential git \
libssl-dev libsodium-dev libsqlite3-dev \
libssh2-1-dev libcurl4-openssl-dev libjson-c-dev
# Clone and build
git clone https://github.com/nhowardtli/virp.git && cd virp
make CISCO=1 FORTIGATE=1 PANOS=1 ASA=1 LINUX=1
make CISCO=1 FORTIGATE=1 PANOS=1 ASA=1 LINUX=1 prod
# Test
make all-tests
make test-session
make test-session-key
# Generate a signing key and start the O-Node
./build/virp-tool keygen -o /etc/virp/keys/onode.key
./build/virp-onode-prod \
-k /etc/virp/keys/onode.key \
-s /tmp/virp-onode.sock \
-d /etc/virp/devices.json \
-c /var/lib/virp/chain.dbSystemd unit file: deploy/virp-onode.service
- C library (libvirp) — 13,743 source lines + 2,867 header lines, C11,
-Wall -Wextra -Werror -pedantic - Go implementation — 2,739 lines, identical wire format, interop-tested against the C reference
- Vendor drivers — Cisco IOS, FortiOS, PAN-OS, Cisco ASA, Juniper, Linux, Wazuh
- Session handshake —
SESSION_HELLO/SESSION_HELLO_ACK/SESSION_BINDstate machine with HKDF-derived session keys - Trust chain — SQLite-backed, tamper-evident, crash-safe
- Federation — Ed25519 via libsodium for cross-tenant artifact verification
- 101 test cases across 23 files: 71 C unit + integration tests, 30 Python end-to-end and parity tests, plus libFuzzer harness, concurrency tests, and live-hardware tests
- Integrations — Prometheus exporter, NetBox sync
Won't a sufficiently advanced AI just learn not to fabricate? No. Fabrication is a structural failure mode: the model generates output in response text without invoking the signed execution path. No amount of training prevents a language model from producing plausible-sounding text. VIRP makes the difference between "text that looks like an observation" and "an observation" cryptographically distinguishable. The fix is not at the model layer.
Why not just hash the device output after the fact? Because the question is not "did this bytestring get tampered with after we recorded it?" — it is "did this bytestring come from a real device?" Hashing after the AI sees the data lets the AI insert the data. VIRP signs at the point of collection, in a process the AI cannot reach, with a key the AI cannot read.
How is this different from agent observability or tracing platforms?
Observability tools record what the agent claimed to do. VIRP records what was cryptographically verified to have happened. Tracing tells you the agent said it ran show firewall policy 2. VIRP tells you the device responded, here is the signed response, here is its position in the tamper-evident chain.
Is the O-Node a single point of compromise? Yes, and intentionally so. The O-Node is the trust boundary; you harden it the way you would harden a HSM or a credential vault. VIRP's job is to compress the trust surface from "everywhere the AI can reach" down to "one process you can audit." That is a manageable problem. The original is not.
Can I use VIRP without the rest of IronClaw?
Yes. VIRP is a protocol and a reference implementation. IronClaw is one consumer of it. Any agent, dashboard, or automation system can be a VIRP consumer — the wire format is documented in docs/VIRP-WIRE-FORMAT.md.
| Topic | Location |
|---|---|
| Protocol specification | docs/VIRP-SPEC-RFC-v2.md |
| Wire format reference | docs/VIRP-WIRE-FORMAT.md |
| The seven trust primitives | docs/VIRP-7-PRIMITIVES.md |
| AI trust stack model | docs/AI-TRUST-STACK.md |
| Observation flow end-to-end | docs/VIRP-OBSERVATION-FLOW.md |
| Validator manifest contract | docs/VALIDATOR-MANIFEST-CONTRACT.md |
| Threat model and trust boundaries | SECURITY.md |
| Contributing | CONTRIBUTING.md |
- IETF Draft:
draft-howard-virp-05(drafts -01 through -05 submitted) - Formal verification: machine-verified in ProVerif and Tamarin (Phase 1: HMAC key secrecy + non-injective agreement under Dolev-Yao)
- License: Apache 2.0
We are particularly interested in:
- Infrastructure engineers running VIRP against production fleets
- Security researchers attacking the protocol
- Driver authors for Juniper, Arista, Meraki, and cloud APIs
- Protocol designers working on the IETF drafts
See CONTRIBUTING.md for setup, code standards, and the new-driver checklist. Security issues: see SECURITY.md.
Nathan M. Howard — Third Level IT LLC — nhoward@thirdlevelit.com
A responsible system does not guess when evidence is absent. It says: I don't know, and here's why.