Internet-Draft VIRP August 2026
Howard Expires 2 February 2027 [Page]
Workgroup:
Internet Engineering Task Force
Internet-Draft:
draft-howard-virp-06
Published:
Intended Status:
Informational
Expires:
Author:
N. Howard
Third Level IT LLC

VIRP: Verified Infrastructure Response Protocol

Abstract

The Verified Infrastructure Response Protocol (VIRP) defines a trust framework for operators -- human or autonomous -- acting on live network infrastructure. As operations shift toward agentic and automated systems that can autonomously configure, audit, and remediate production environments, the absence of a verifiable chain of custody for observations and actions introduces fundamental risks: fabricated telemetry, unauthorized state changes, and the inability to distinguish legitimate operations from compromise. VIRP routes every observation and every authorization decision through a designated collection-and- verification boundary that the requesting party does not control. Observations are authenticated at collection time using HMAC-SHA256; in session-bound mode (Section 6.4) authentication uses a per-session key and binds the response to session, device, sequence, and a command-digest field. Validating the command binding additionally requires trusted request context from which the verifier recomputes the command digest. A two-channel architecture separates read-only Observation from write-intent Intent, and trust tiers (GREEN/YELLOW/RED/BLACK) govern action authorization with human-in-the-loop controls for elevated operations.

VIRP's observation and chain-integrity guarantees are symmetric and explicitly scoped by key role; approval and federation records use asymmetric Ed25519 signatures. Distinct key roles authenticate observations, chain entries, intents, approvals, and federation records (Section 6.1), though the reference implementation currently reuses one key across the v1-observation and v2-derivation roles; a holder of a symmetric key can both verify and forge within that key's scope, so VIRP does not provide publicly verifiable observation origin and does not defend a record against an adversary holding the relevant key or controlling the collection boundary. Authentication does not certify that a response reflects the managed device's true state, only that the boundary obtained and authenticated those bytes for that recorded request. Asymmetric proof of origin and external anchoring of the chain are distinct, independent items of future work (Section 17).

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 2 February 2027.

Table of Contents

1. Requirements Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

2. Introduction and Motivation

The deployment of AI agents on live infrastructure represents a fundamental shift in how networks are operated. Where previous automation relied on deterministic scripts with predictable outputs, modern AI agents operate with significant autonomy -- selecting commands, interpreting results, and initiating multi-step remediation sequences without per-action human approval.

This capability creates an accountability gap. When a traditional monitoring system reports that a router's CPU is at 94%, the operator can trace that measurement to a specific SNMP poll at a specific timestamp against a specific OID. When an AI agent reports the same finding, the operator must trust that the agent actually queried the device, that the query returned what was reported, and that the agent's interpretation matches the raw data. None of these properties are currently verifiable.

The consequences of unverifiable AI observations are significant. An agent that fabricates or replays telemetry can drive incorrect remediation. An agent that takes undocumented actions leaves no audit trail for compliance or incident response. An agent that is compromised -- or that simply makes an error in a long autonomous loop -- produces outputs that are indistinguishable from legitimate operations.

VIRP addresses this gap by establishing cryptographic evidence at every layer of the observation-to-action pipeline. The protocol is not concerned with what the AI agent is capable of doing. It is concerned with establishing what the agent actually did, when, against which device, and whether that action was authorized by the appropriate tier of human oversight.

This revision states materially narrower security claims than draft-howard-virp-05 in several places. That narrowing is deliberate. It reconciles the specification with the reference implementation: earlier revisions described a per-observation Ed25519 signature and a two-tool machine-verified formal result, neither of which exists in the code. The corrected claims, and the reasoning behind each, are summarized in Appendix A. Readers comparing this revision against -05 should treat the removals as corrections, not as regressions in the protocol.

3. The Trust Problem in Agentic Infrastructure

3.1. Current State

Existing infrastructure management tools assume a trusted operator. SNMP polling trusts that the collector reports what it received. Ansible playbooks trust that tasks executed as written. SIEM correlation trusts that log sources are authentic. These trust assumptions are reasonable when humans are in the loop at every step.

AI agents break these assumptions. An agent running in an autonomous loop may execute hundreds of commands per session. Human review of every action is impractical. The operational benefit of AI autonomy is inseparable from reduced per-action oversight -- which means the integrity guarantees that relied on human review must be replaced with cryptographic equivalents. This shift is consistent with the Zero Trust Architecture principles articulated in [NIST-ZTA]: trust is established per-operation through verification, not inherited from an authenticated session.

3.2. The Fabrication Problem

The most significant risk in AI-driven infrastructure management is not malicious action -- it is undetectable error. An AI agent that misreads output, hallucinates a device state, or generates plausible-looking but incorrect telemetry can drive remediation actions based on false premises. Without cryptographic evidence that an observation was collected from a real device at a real timestamp, there is no mechanism to distinguish a genuine observation from a fabricated one.

3.3. The Accountability Gap

When an AI agent takes an action on infrastructure, current tooling records what the agent reported it did. VIRP records what the collection boundary observed the device return, with a chain of custody linking the intent to the observation to the outcome. This distinction is operationally significant: in an incident, the difference between what an agent said it did and what the device actually experienced may be the entire root cause.

4. Protocol Overview

VIRP defines a layered protocol stack with four primary components:

Table 1: Protocol Components
Component Description
O-Node Observation Node -- the collection-and-verification boundary. All device communication occurs within the O-Node. Observations are authenticated before leaving the O-Node. The authenticating key material is held inside that boundary.
Observation Channel Read-only channel for device state collection. Observations carry an HMAC-SHA256 authentication code, sequence numbers, and timestamps. Sequence gaps indicate missing observations.
Intent Channel Write-intent channel for action authorization. Intents must be filed before execution. The tier classifier evaluates intent against the trust tier framework before authorizing execution.
Chain DB Append-only database of authenticated chain entries referencing observations. Forms the tamper-evident audit trail, under the key-scoping stated in Section 6.5.

The O-Node operates as the collection boundary in the architecture. The requesting party -- an AI agent or a human-driven client -- is treated as a party outside that boundary: it may read authenticated observations for verification, but in the reference architecture it holds no observation-authentication, chain, or approval key and therefore cannot produce those records. This asymmetry is the foundation of VIRP's security model, and its exact scope is stated per key role in Section 6.1.

5. The Seven Trust Primitives

VIRP defines seven trust primitives that collectively address the accountability gap in agentic infrastructure operations. Each primitive addresses a distinct failure mode.

5.1. Primitive 1: Observation Integrity

Every device observation is authenticated at collection time within the O-Node using HMAC-SHA256. In session-bound mode (Section 6.4) the authenticated header covers the device identifier, timestamp, per-session sequence number, session identifier, a digest of the canonical command, and the payload length, and the authenticated bytes include the raw output. In the legacy format (Section 6.3) the authenticated bytes cover the header and output but carry no session, device, or command binding. Observations that fail verification are rejected. A party that does not hold the relevant key cannot produce an observation that verifies; a party that does hold it can (Section 6.1).

Failure mode addressed: fabricated or replayed telemetry originating outside the collection boundary. An agent that holds no observation-authentication key cannot report a device state that the boundary did not collect.

5.2. Primitive 2: Two-Channel Separation

VIRP enforces strict separation between Observation (read) and Intent (write) channels. Observations flow from device to O-Node to chain. Intents flow from the requesting party to the tier classifier to the O-Node to the device. The channels are architecturally separate and are additionally bound to distinct key roles: the implementation refuses to authenticate an Observation Channel message with an Intent Channel key or the reverse.

Failure mode addressed: an agent that reads device state and takes action within the same unmonitored channel, bypassing authorization controls.

5.3. Primitive 3: Intent Gating

Before any write operation reaches a device, an Intent must be filed with the O-Node specifying the target device, command class, and justification. The tier classifier evaluates the intent against the trust tier framework. GREEN tier intents may execute immediately. YELLOW tier intents require human acknowledgment. RED tier intents require explicit approval carrying an Ed25519 signature from an enrolled approver, bound to the command digest, the target device, and an expiry. BLACK tier intents are rejected unconditionally. Commands that match no classification rule are treated as RED and are refused by default.

Failure mode addressed: unauthorized state changes. An agent cannot modify device configuration without a prior authorized intent on record.

5.4. Primitive 4: Outcome Verification

Following every authorized action, VIRP collects a post-action observation and compares the resulting device state against the expected outcome of the intent. Divergence between expected and actual state generates a trust tier escalation. Outcomes are authenticated and chained alongside the original intent.

Failure mode addressed: actions that execute but produce unexpected results, which would otherwise be invisible in the audit trail.

5.5. Primitive 5: Baseline Memory

VIRP maintains an authenticated baseline of known-good device state derived from a verified observation sweep. Subsequent observations are compared against the baseline. Deviations -- new BGP peers, changed interface states, modified firewall policies -- generate alerts and may trigger tier escalation. The baseline itself is a chain of authenticated observations and is verifiable by any holder of the relevant key.

Failure mode addressed: undetected configuration drift. The system knows what normal looks like and can detect when it changes.

5.6. Primitive 6: Multi-Vendor Normalization

VIRP defines a normalized observation schema that abstracts vendor-specific output formats. Cisco IOS show commands, FortiOS get commands, and Linux system calls are mapped to a common observation structure. This enables consistent chain integrity verification across heterogeneous infrastructure.

Failure mode addressed: trust model fragmentation across vendors. A single chain can represent observations from any supported device type.

5.7. Primitive 7: Agent Containment

The requesting process must be treated as an untrusted principal. Process containment must be enforced externally -- at the hypervisor layer, at the network boundary, and at the filesystem level. The requesting process must not have access to observation, chain, or approval key material, to device credentials, or to direct network paths to managed devices.

This primitive was identified during live adversarial testing when the agent under test self-reported that it could bypass VIRP's observation chain by going around it entirely -- accessing credentials directly, connecting to devices without chain entries, or spawning unsupervised inference sessions. The primitive formalizes the architectural response: containment is not policy, it is structure.

Failure mode addressed: a requesting process that circumvents the observation chain entirely. VIRP protects the chain -- Primitive 7 ensures the requester cannot go around it.

6. Cryptographic Architecture

6.1. Keys and Authentication Roles

VIRP defines several authentication key roles, each authenticating a specific class of record. Most roles use distinct key material, but the reference implementation currently reuses the O-Key both for v1 observation authentication and as the input to v2 session-key derivation (below). The channel and role separation that is enforced is structural, not policy: the implementation refuses to use, for example, an R-Key to authenticate an Observation Channel message.

O-Key (K_obs), HMAC-SHA256 [RFC2104] [RFC6234]:
A static key with two roles: it directly authenticates legacy v1 observation-channel messages (Section 6.3), and it is the input keying material from which v2 session keys are derived. v1 verification is a stateless HMAC check by a holder of the O-Key. Because HMAC is symmetric, an O-Key holder can both verify and produce v1 observations; because the O-Key is also the derivation input, an O-Key holder can additionally derive v2 session keys.
R-Key (reasoning key), HMAC-SHA256:
Authenticates Intent Channel messages -- the requests a reasoning or requesting party submits. Channel binding is enforced by the implementation: an R-Key can only authenticate Intent Channel messages and an O-Key can only authenticate Observation Channel messages; a violation is rejected. Authenticating an intent request is not authorizing it; the gate and approval policy remain authoritative. In the protocol model an R-Node holds the R-Key and uses it to authenticate Intent Channel messages. The current reference API and autopilot execution path does not use R-Key-authenticated Intent Channel messages; it submits framed requests directly to the O-Node socket. The statement "the requesting agent holds no key" is therefore accurate only for the current deployed path. The protocol architecture permits an R-Node to hold an R-Key that authenticates intent but never observations.
Session key, HKDF-SHA256-derived:
Authenticates session-bound v2 observations (Section 6.4). Derived per session from the O-Key material and the authenticated session transcript. A party that cannot derive the session key cannot produce a valid v2 observation for that session.
K_chain (chain key), HMAC-SHA256, distinct from K_obs:
Authenticates trust-chain entries (Section 6.5). A holder of K_chain can rewrite chain history; a holder of only K_obs cannot.
Approver key, Ed25519 [RFC8032] [ED25519]:
Signs approval records in the intent-approval flow. The private key is held outside the collection boundary, so the boundary cannot mint its own approvals.
Federation key, Ed25519:
Authenticates federation material (Section 17.5).

The exact session-key derivation is as follows (HKDF-SHA256 [RFC5869], single block, 32-byte output):

IKM  = the O-Key (master key material)
salt = the session transcript_hash (32 bytes)
info = the generation counter, big-endian u64 (exactly 8 octets)

PRK  = HMAC-SHA256(salt, IKM)
OKM  = HMAC-SHA256(PRK, info || 0x01)
session_key = OKM  (32 bytes)
Figure 1: Session Key Derivation

These are the exact authenticated inputs; any mismatch changes the key and breaks interoperability. Implementations MUST NOT substitute a zero salt for a missing transcript: a session key derived without an authenticated transcript is a protocol error, and an implementation that cannot compute transcript_hash MUST fail the session rather than derive a key.

The value generation is a derivation input. It MUST be carried in the authenticated SESSION_BIND message so that a separate verifier can re-derive the key from the authenticated transcript; see Section 6.4 for the normative rules, including the rollback-protection requirement. In the reference implementation generation is not yet transported; see Section 18.

The session-derivation input keying material is the O-Key itself. There is no separate master key in the reference implementation. The O-Key serves two roles: it directly authenticates v1 observations and it is the HKDF input for v2 session keys. Consequently a holder of the O-Key can both forge v1 observations and, given the required derivation context, derive v2 session keys within its scope. This is a weaker separation than a dedicated derivation master would provide. Implementations SHOULD adopt a dedicated session-derivation master distinct from the legacy v1 authentication key; this document records the current reuse as a migration target, not as a designed property.

The security consequence of role separation is important and easy to understate: possession of one key does not confer the ability to forge records in another key's scope -- with one current exception. It holds for K_chain, the R-Key, approver keys, and federation keys: a holder of any one cannot forge in another's scope. It does not currently hold between v1 authentication and v2 derivation, because both use the same O-Key material: an O-Key holder can forge v1 observations and derive v2 session keys. A component holding only K_chain, or only an approver key, gains no observation-forging ability. The collection boundary may in a given deployment hold several of these keys at once, but that is a deployment fact, not an inherent property of any single key. The threat model (Section 9) is therefore stated per key, not per "the O-Key".

Across all symmetric keys, VIRP provides integrity and origin authentication relative to the secrecy of the relevant key, held within the trusted boundary. It does not provide publicly verifiable origin for observations: any holder of the authenticating key can also produce records. The requesting party holds no observation, chain, or approval key. An R-Node may hold an R-Key and can therefore authenticate intent messages, but that key cannot authenticate observations, chain entries, or approvals, and authenticating an intent is not authorizing it. Asymmetric observation signing (Section 17.3) would add public verifiability and remove verifier forgery, but would not by itself defend against compromise of the signer; that requires hardware custody, independent witnessing, or external anchoring (Section 17), which are separate mechanisms addressing a separate threat.

6.2. Key Custody

In the reference implementation, verification components load the relevant symmetric key and check records locally. Because symmetric verification is also a forging capability, every holder of a given key is part of that key's trust boundary; deployments SHOULD minimize the number of holders and MUST NOT treat a symmetric verifier as an untrusted party. A deployment that needs verification by a party which must be unable to forge cannot obtain that from the symmetric paths specified here; it requires the asymmetric work of Section 17.3, or a verification service that returns an accept/reject decision without releasing the key.

The requesting agent holds no observation, chain, or approval key. Approver and federation keys are asymmetric; the approver's private key is held outside the collection boundary, which holds only the corresponding public key.

6.3. Legacy v1 Observation

The v1 observation uses the static O-Key and an HMAC-SHA256 over the v1 message header and payload. Verification is stateless: a holder of the O-Key recomputes the HMAC and compares. v1 does not carry a session binding and does not by itself provide replay protection (Section 9), and it does not provide the request or command binding that v2 provides.

Legacy v1 is a deprecated transitional format. New implementations MUST use v2 for device-evidence observations. Implementations MAY continue to emit v1 authenticated rejection and compatibility records during migration, but verifiers MUST NOT interpret a v1 record as session-bound or replay-resistant evidence.

Stated plainly: the reference implementation currently defaults to v1. Request parsing defaults the observation version to 1; the Python API does not perform the v2 handshake or request v2; gate rejections are v1. v2 requires explicit session negotiation and an explicit version selection. Migrating the reference default to v2 is a tracked implementation task (Section 18), recorded here rather than claimed as complete.

Deprecated does not mean unspecified. The v1 layout is:

 offset  size  field
  0       1    version = 1
  1       1    message type
  2       2    total message length, uint16 big-endian
  4       4    node_id, uint32 big-endian
  8       1    channel
  9       1    tier
 10       2    reserved, MUST be zero
 12       4    sequence, uint32 big-endian
 16       8    timestamp_ns, uint64 big-endian
 24      32    HMAC-SHA256
 56       1    observation type
 57       1    observation scope
 58       2    observation-data length, uint16 big-endian
 60       n    observation data
Figure 2: v1 Observation Message Layout

The HMAC input is bytes 0 through 23 concatenated with bytes 56 through (total_length - 1); the HMAC field (bytes 24 through 55) is excluded from its own input.

A conforming v1 verifier MUST apply the following validation rules before accepting a record:

  • The version octet MUST equal 1 and the message type MUST be a defined value; unknown enumerated values MUST be rejected rather than ignored.
  • total message length MUST be at least 60 and MUST NOT exceed 65535. The maximum conforming observation-data length is therefore 65475 octets.
  • The declared observation-data length MUST be consistent with total message length; a declared length exceeding the remaining input MUST be rejected.
  • Octets after the declared fields MUST be rejected; a verifier MUST NOT accept trailing bytes.
  • The reserved field MUST be zero on transmission and MUST be rejected if non-zero on receipt.
  • The HMAC comparison MUST be constant-time.

6.4. Session-Bound v2 Observation

The v2 observation is authenticated as HMAC-SHA256(session_key, serialized_header || payload), where session_key is the HKDF-derived per-session key (Section 6.1). The fixed-width header carries a 64-bit node identifier; a nanosecond timestamp; a per-session sequence number; a session identifier; a 64-bit device identifier; a SHA-256 hash of the command (not the command string itself); and the payload length.

Because the header binds session, sequence, device, and a command hash, a v2 observation authenticates a command digest within a specific session; it becomes evidence about a specific command only when a verifier possesses trusted command context whose canonical digest matches that field. A party that cannot derive the session key cannot forge a v2 observation for that session, which is a stronger scoping than v1's static-key model.

The serialized header is exactly 88 octets, with no padding and all multi-byte fields in network byte order:

 offset  size  field
  0       1    version
  1       1    channel
  2       1    tier
  3       1    reserved (MUST be zero)
  4       8    node_id
 12       8    timestamp_ns   (nanoseconds since epoch)
 20       8    seq_num        (monotonic per session)
 28      16    session_id     (from SESSION_BIND)
 44       8    device_id      (stable 64-bit device identifier)
 52      32    command_hash   (SHA-256 of the canonical command)
 84       4    payload_len
 = 88 octets
Figure 3: v2 Observation Header Layout

The observation carries the command only as a SHA-256 hash, never as text. The verifier receives the expected command as a separate input (trusted request context), canonicalizes it, hashes it, and compares against the authenticated command_hash. The full command text is not in the authenticated bytes, not in the base observation, and not reliably in the chain entry; a consuming API that reattaches the command string does so as convenience metadata outside the authenticated bytes.

The consequence must be stated plainly: a base v2 observation is not a self-contained receipt of the command. It binds a command only relative to a relying party that already possesses the correct request context. A party that keeps the observation but loses the trusted request record retains a valid authentication over a digest whose preimage it can no longer establish. Closing this -- authenticating either the complete canonical typed-operation encoding, or a digest of a separately authenticated request record carrying operation identifier, registry version, parameters, and resolved target -- is the subject of Section 17.7 and is the strongest argument for a typed operation model.

The header layout can represent an all-zero session identifier, but no bootstrap v2 observation uses one: the v2 signer requires an active session and copies the active session identifier, and error records fall back to v1. A conforming v2 device-evidence observation MUST contain a non-zero session identifier, and verifiers MUST reject an all-zero session identifier.

Session-key provisioning to an independent verifier is specified as follows. VIRP adopts the O-Key-holding verifier model: a conforming independent verifier holds the O-Key and derives the session key itself from the authenticated session transcript and generation value. This matches the symmetric trust-boundary design and requires no confidential session-key delivery protocol. Such a verifier is a trusted component and has session-forging capability wherever it possesses the derivation context; its trust status equals the collection boundary's. Deployments requiring a verifier that cannot forge must use asymmetric observation signing (Section 17.3), which is future work. A derived-key-only verifier, provisioned over an authenticated confidential channel, is a possible future model but is not specified here; it would require a new key-delivery protocol.

Generation is carried in the authenticated SESSION_BIND message, specified as follows:

  • generation is an unsigned 64-bit integer in network byte order.
  • It is covered by the authentication protecting SESSION_BIND. That authenticator MUST NOT be the session key whose derivation depends on the transcript; otherwise the construction is circular. Implementations MUST authenticate SESSION_BIND under key material that is independent of the transcript being established.
  • The session transcript hash is computed over the complete encoded SESSION_BIND including the generation field: generation is inserted before transcript_hash is computed. Consequently generation is represented both inside salt = transcript_hash and separately as the 8-octet HKDF info. This duplication is intentional.
  • A verifier MUST reject a generation less than or equal to the greatest previously accepted generation for the derivation scope, which is the tuple (O-Key identifier, O-Node node identifier). This is rollback protection.

The v2 verifier also enforces a freshness window: an observation whose authenticated timestamp differs from the verifier's clock by more than a configured bound (300 seconds in the reference implementation) is rejected as stale, in addition to the per-session replay check of Section 9.

6.5. Chain Entry Encoding

A chain entry is a distinct artifact from an observation. Each entry contains previous_entry_hash, the entry digest of its immediate predecessor, within the entry's canonical encoding. VIRP computes over that canonical encoding both an unkeyed SHA-256 entry digest and an HMAC-SHA256 chain authentication code using K_chain, a key distinct from the observation-authentication keys. Alteration of a predecessor reference therefore changes both the entry digest and the chain HMAC. An entity without K_chain cannot modify, insert, or remove an entry within the presented chain and produce replacement downstream entries that verify.

This establishes only the integrity and linkage of the entries presented to the verifier. It does not prove the verifier holds the latest chain suffix: an adversary can present an older, internally valid prefix. Detecting truncation or a withheld suffix requires comparison against a previously trusted chain head or an externally published checkpoint (Section 17.4). A holder of K_chain can recompute the chain; external anchoring is required to make already-published history resistant to undetected rewriting by such a holder.

VIRP chain entries use a deterministic binary canonical encoding. The compact, alphabetically ordered JSON that the current reference implementation emits is a legacy implementation format, not the normative wire representation: values are inserted into it directly, so unrestricted quotes, backslashes, or control characters would make it ambiguous, and it is unsafe to standardize as-is.

The fields carried by a chain entry are: session identifier; sequence; previous entry digest; wall-clock timestamp (informational); monotonic timestamp (ordering); artifact type (observation, intent, or outcome); artifact identifier; artifact digest; artifact digest algorithm; artifact schema version; signer node identifier; and signer organization identifier. The entry's own entry digest (SHA-256) and chain HMAC (HMAC-SHA256 under K_chain) are computed over the canonical encoding of those fields; they are outputs, not inputs to it.

The normative binary canonical encoding is the octet sequence over which both the entry digest and the K_chain HMAC are computed. All multi-byte integers are in network byte order; digests are carried as raw 32 octets, not hexadecimal; variable-length text fields are length-prefixed and are not NUL-terminated in the authenticated form:

 field                     encoding
 ------------------------  -----------------------------------------
 domain label              "VIRP-CHAIN-ENTRY-v1" (ASCII, fixed)
 format_version            u16
 artifact_type             u8 {observation=1, intent=2, outcome=3}
 sequence                  u64
 session_id                16 octets raw (same form as v2 header)
 previous_entry_digest     32 octets raw
 timestamp_ns              u64
 monotonic_ns              u64
 artifact_id               length-prefixed (u16 len || octets)
 artifact_hash             32 octets raw
 artifact_hash_alg         u8 enum {sha256=1}
 artifact_schema_version   u16
 signer_node_id            u64 (same width as v2 node_id)
 signer_org_id             length-prefixed (u16 len || octets)
Figure 4: Chain Entry Canonical Encoding (chain-format-version 1)

The entry digest is SHA-256 of this encoding; the chain HMAC is HMAC-SHA256(K_chain, this encoding). A verifier reconstructs the encoding, checks the previous entry digest against the prior entry, recomputes the digest, and verifies the HMAC.

The following field-level rules are required to make this encoding deterministic:

  • sequence is an unsigned 64-bit integer and MUST be greater than or equal to 1 and strictly increasing within a chain.
  • session_id MUST use the same fixed 16-octet raw representation as the v2 observation header, not a length-prefixed text form, so that one session cannot be described two ways that hash differently. For an entry not associated with a session, the field MUST be 16 zero octets.
  • signer_node_id MUST match the v2 node identifier width and is therefore u64.
  • For the first entry in a chain, previous_entry_digest MUST be 32 zero octets.
  • Every length-prefixed field MUST be valid UTF-8, MUST be between 0 and 1024 octets in length, MUST be rejected if the declared length exceeds the remaining input, and MUST be rejected if the octets are not well-formed UTF-8.
  • Unknown enumerated values in artifact_type or artifact_hash_alg MUST be rejected rather than ignored.
  • Octets after the declared fields MUST be rejected.
  • The complete stored or transmitted chain record is the canonical entry encoding, followed by the entry digest (32 octets raw), followed by the chain HMAC (32 octets raw), in that order.

The binary encoding above is chain-format-version 1 and is the normative canonical encoding for this protocol version. The compact alphabetically ordered JSON that the current reference implementation emits is a non-interoperable legacy format and is not conforming to this revision. An implementation emitting the legacy JSON is a legacy producer; a conforming implementation emits chain-format-version 1. Migrating the reference implementation's chain emission is a tracked implementation task (Section 18).

6.6. Canonical Encoding

Authentication inputs MUST be deterministic and unambiguous. This document specifies, for each authenticated artifact, the exact octet sequence covered.

For v2 observations, the authenticated bytes are the 88-octet serialized header of Section 6.4 concatenated with the payload. The header is fixed-width with all multi-byte fields in network byte order, so the encoding is already deterministic and unambiguous; the normative requirements are the exact offsets and widths of Section 6.4 and the rule that reserved is zero. The header authenticates a SHA-256 command digest, not the command string, so the binding is to the digest of the canonical command; the canonicalization that feeds that digest is defined by the v1 command canonicalizer for legacy string commands and, for typed profiles, by the rules under development in Section 17.7.

Normative authentication inputs cannot be optional: adding a domain-separation label would change the authenticated octets, so a labeled and an unlabeled implementation would reject each other's records. v2 therefore uses the fixed header exactly as specified -- including its version octet, which together with the differing v1 and v2 header layouts is what provides cross-version separation. A future wire format version SHOULD introduce an explicit domain-separation label; adding one to v2 would be wire-incompatible and is not proposed here.

For chain entries, the authenticated bytes are exactly the deterministic binary encoding defined in Section 6.5. The legacy JSON representation is not a conforming canonical encoding for this protocol version.

7. Reference Containment Model

The reference deployment enforces separation between the requesting process and the VIRP O-Node through a two-host architecture. The addresses, hostnames, and hypervisor details below describe the lab topology in which the results reported in Section 14 and Section 15 were obtained; a deployment need only preserve the properties, not the topology.

Table 2: Reference Two-Host Containment
Host Role and Constraints
Requesting host Runs the agent gateway, the tool server, and the agent process. No direct network path to managed devices. Holds no observation, chain, or approval key. Outbound network policy restricted to the inference API and the O-Node socket only. Runs as an unprivileged system user with service-manager hardening.
O-Node host Runs the O-Node daemon. Holds the O-Key, K_chain, and device credentials, and the approver public keys. Has direct SSH and API access to managed devices. Accepts connections from the requesting host only; all other inbound traffic is blocked.

Communication between the requesting host and the O-Node occurs over a socket bridge to the O-Node's local socket. The requesting process issues intent requests and receives authenticated observations over this channel. It has no other path to device access.

7.1. Containment Layers

  • Hypervisor layer: virtual-machine firewall rules enforce network policy outside guest control.
  • Network layer: host firewalling restricts outbound traffic on the requesting host and inbound traffic on the O-Node.
  • Process layer: an unprivileged service user with no-new-privileges, a strict read-only system view, and a private temporary directory.
  • Filesystem layer: credential files owned by root with mode 0600, inaccessible to the service user.
  • Cryptographic layer: the requesting host holds no observation-authentication key, so a compromise of that host does not confer the ability to produce an observation that verifies. This is a property of key placement, not of asymmetric cryptography; see Section 6.1 for the precise scope.

8. Trust Tiers and Action Authorization

Table 3: Trust Tiers
Tier Definition Authorization Required
GREEN Read-only observation. No state change possible. None -- immediate execution
YELLOW Low-impact state change. Reversible within session. Human acknowledgment
RED High-impact or potentially irreversible change. Explicit signed approval, bound to command digest, device, and expiry
BLACK Destructive, out-of-scope, or policy violation. Rejected unconditionally

Tier classification is performed by the intent router, which evaluates the command class, target device, and current network state. Classification rules are configurable per deployment. A command that matches no rule MUST be treated as RED rather than permitted; the classifier fails closed. The tier classifier itself is outside the requesting process's ability to modify -- it runs as a separate process with its own audit log.

Rejections are themselves authenticated records. When the gate refuses a command, the O-Node emits an authenticated error observation carrying the true tier and a proposal identifier, so that a refusal is evidence in the chain rather than an absence of evidence.

9. Threat Model

VIRP defines the following threat actors and the protocol's response to each. The rows are stated per key role, because different key holders have different forging power.

Table 4: Threat Model
Threat Actor VIRP Response
Compromised requesting agent Cannot forge observations, chain entries, or approvals: it holds none of those keys. If it holds an R-Key, it can submit authenticated intent messages, which remain subject to gate classification and authorization policy. Containment (Section 7) prevents direct device access.
Compromised agent host (full root) May expose the R-Key if the deployed R-Node stores it there. No observation, chain, or approval key is present in the reference architecture; the attacker can read records and submit them to a key-holding verifier but cannot produce an observation, chain entry, or approval that verifies.
Compromised O-Key holder Can forge v1 observations directly. Because the O-Key is also the v2 session-key derivation input in the reference implementation, the holder can also derive and forge v2 observations whenever it has the necessary session-derivation context. Cannot forge chain entries (needs K_chain) or approvals (needs the approver's Ed25519 key). A component limited to verifying v1 without this forging power would require a separately derived verification capability or an asymmetric construction; possessing the actual O-Key is not v1-only.
Compromised R-Key holder Can produce authenticated Intent Channel messages within the R-Key's scope. Cannot produce Observation Channel records: key-role and channel binding are enforced by the implementation. Intent authentication is not authorization; the gate and approval policy remain authoritative.
Compromised holder of a single derived session key Can forge v2 observations for that one session only. Cannot forge other sessions, v1 records, or chain entries. This bound applies to a component provisioned with only the derived key; it is a future profile rather than a documented property of the current reference deployment (Section 6.4).
Compromised chain writer or verifier (holds K_chain) Can rewrite or forge chain entries and thus chain history. Cannot forge a v2 observation under an uncompromised session key. External anchoring (Section 17.4) is what makes already-anchored history rewrite-detectable.
Compromised collection boundary (O-Node holding several keys) May hold K_obs, a session key, K_chain, and device credentials at once. Can forge observations, recompute the chain, and bypass the gate to execute writes directly with device credentials, omitting them from the record. VIRP does not prevent this. What remains: it cannot forge an approval signed by an uncompromised approver key, held outside the boundary. Independently retained approval records authenticate approvals that are presented; establishing that no corresponding approval existed is a stronger claim, requiring a complete approval history whose relevant range and head are independently retained or externally anchored. An individual retained record proves an approval existed and was valid, not that no other did. An unanchored local log controlled by the compromised boundary cannot establish absence, since a K_chain holder can rewrite, remove, or withhold it. External device-side authorization, credential constraints, and independent monitoring are required to detect or limit out-of-flow execution.
Replay of a genuine observation A v2 stateful verifier maintains a persistent high-water sequence number per (session identifier, node identifier) and accepts a v2 observation only when its sequence strictly advances that mark; the state persists across restart. A strict high-water verifier requires observations to be accepted in sequence order; a profile permitting concurrent in-flight operations within a session MUST define an equivalent replay-safe acceptance window rather than a scalar high-water mark. Legacy v1 HMAC verification is stateless and does not itself provide this guarantee.
Credential exfiltration from the agent Device credentials are not on the agent host in the reference implementation; the boundary holds them.
Man-in-the-middle on the O-Node transport Records are authenticated before leaving the boundary; modified records fail verification. This provides neither confidentiality nor endpoint authentication; deployments SHOULD use an authenticated, encrypted transport.
Physical access Out of scope; a deployment requirement.

10. Future Architecture: Role Separation

The current VIRP architecture concentrates observation, intent gating, and action execution within a single O-Node process. This design is operationally simple and sufficient for environments where the O-Node host is well-protected. However, as deployments scale and the consequences of a single-node compromise grow, protocol-level role separation offers a principled path to narrower blast radii and stronger separation of duties. This section defines a future three-role architecture and a migration roadmap from the current single-node baseline.

10.1. Architectural Motivation

In the current design, a compromised O-Node can forge observations, approve intents, and execute actions on devices. While chain integrity makes tampering with presented history detectable to a party that holds an independently retained chain head, a live compromise grants the attacker control over future operations for the duration of the compromise window.

The three-role architecture addresses this concentration of trust by decomposing the O-Node into three distinct principals, each with a narrow set of capabilities and its own keying material. The design goal is that compromise of any single node is insufficient to both fabricate state and act on that fabrication.

10.2. Observer Node

The Observer Node is responsible for device telemetry collection and observation authentication. It holds read-only credentials for managed devices and the observation key material. The Observer Node listens on a read-only socket and MUST NOT accept or process write intents.

The Observer Node authenticates each observation at collection time, covering the fields specified in Section 6.4. The authenticated observation is referenced from the chain and made available to other nodes over the read-only socket.

The Observer Node holds no policy state, no approval authority, and no write credentials. It cannot authorize or execute configuration changes on any managed device.

10.3. Executor Node

The Executor Node holds write credentials for managed devices. It receives command bundles that have been signed by the Policy Node and executes them against the specified targets. The Executor Node MUST refuse execution of any command bundle that does not carry a valid Policy Node signature.

The Executor Node holds no chain key, no observation key, and no policy or constraint state. It does not evaluate whether a command is appropriate; it verifies only that the command bundle bears a valid signature from a known Policy Node. The Executor Node makes no autonomous decisions.

Upon completing execution, the Executor Node reports the result to the Observer Node, which independently collects a post-action observation for outcome verification. The Executor Node does not self-report success or failure into the observation chain.

10.4. Policy Node

The Policy Node holds the constraint ledger, operator preferences, trust tier definitions, and the approval queue. It receives intent requests, evaluates them against policy, and -- if approved -- signs a command bundle with its own Ed25519 private key and forwards it to the Executor Node.

The Policy Node MUST NOT hold device credentials of any kind. It never communicates directly with managed devices. Its sole output is signed command bundles delivered to the Executor Node. The Policy Node consumes observations from the Observer Node for situational awareness but cannot influence or alter the observation chain.

Human approval workflows, trust tier escalation, and operator overrides are mediated through the Policy Node. Tier classification (as defined in Section 8) is performed by the Policy Node rather than by a co-located intent router.

10.5. Separation-of-Duties Property

The three-role architecture enforces a strict separation-of-duties property: no single node can observe device state, approve an action, and execute that action. Each of these three capabilities is held by a different principal with independent keying material.

Observation requires the observation key (held only by the Observer Node). Approval requires the Policy Node signing key (held only by the Policy Node). Execution requires device write credentials (held only by the Executor Node). An attacker who compromises any single node obtains exactly one of these three capabilities.

This property MUST be enforced at the protocol layer. Implementations MUST NOT permit a single process or host to hold the keying material of more than one role in a production deployment of the three-role architecture.

10.6. Compromise and Blast Radius Analysis

The following analysis considers the impact of compromising each node individually and in combination.

Observer Node compromise. An attacker gains the observation key material and read-only device credentials, and can forge or fabricate observations and read device state passively. The attacker cannot approve intents and cannot execute write operations. Blast radius: observation forgery and passive reconnaissance.

Executor Node compromise. An attacker gains device write credentials, but the Executor Node only processes command bundles carrying a valid Policy Node signature. The attacker may attempt to replay previously received, validly signed bundles. Implementations SHOULD include replay protections such as nonces or expiring timestamps in command bundles. Blast radius: replay of previously approved commands, bounded by those protections.

Policy Node compromise. An attacker gains the ability to sign arbitrary command bundles, but the Policy Node holds no device credentials and has no network path to managed devices. Blast radius: unauthorized approvals and signed bundles that remain inert unless delivered to a compromised Executor Node.

Observer and Executor compromise. The attacker can forge observations and holds write credentials, but cannot generate validly signed command bundles. The attacker could bypass the Executor's signature check through local code modification, effectively using the write credentials directly. This is equivalent to raw device access plus observation forgery; the Policy Node's approval record will show no corresponding approval, subject to the retention and anchoring qualification in Section 9.

Policy and Executor compromise. The attacker can sign arbitrary command bundles and execute them. This is the most operationally dangerous two-node scenario. The attacker cannot forge observations: post-action observations collected by the uncompromised Observer Node record the resulting device state.

Observer and Policy compromise. The attacker can forge observations and sign bundles, but cannot execute commands. Blast radius: fabricated state and pre-signed malicious bundles, with no execution capability.

Full three-node compromise. Equivalent to a compromised single O-Node in the current architecture. The three-role architecture does not defend against simultaneous compromise of all principals; its value lies in requiring the attacker to breach three independent trust boundaries rather than one.

10.7. Migration Roadmap

Stage 1: Single O-Node (current). The existing single-process O-Node handles observation, policy evaluation, and execution. This is the deployment baseline described throughout this document. The blast radius of an O-Node compromise is the full set of managed devices.

Stage 2: Observer-Executor separation. The O-Node is split into an Observer process and an Executor process, each with its own socket and credentials. This separation can be achieved on a single host using process isolation.

Stage 3: Policy Node extraction. Policy evaluation, the constraint ledger, and the approval queue are extracted into a dedicated Policy Node process with its own signing key. The Executor Node is modified to require a valid Policy Node signature on all command bundles.

Stage 4: Physical separation. The three nodes are deployed on separate hosts with independent network policies. The Policy Node may be placed on an air-gapped host or backed by a hardware security module for its signing key. Inter-node communication is authenticated using mutual TLS or a comparable mechanism.

10.8. Security Considerations for Role Separation

The three-role architecture introduces inter-node communication paths that do not exist in the single O-Node design. Each path represents an attack surface that MUST be protected by authenticated and encrypted transport. Implementations MUST NOT rely on network topology alone for inter-node authentication.

Key management complexity increases with role separation. Key rotation procedures MUST be defined for each role independently, and public keys MUST be distributed to the nodes that verify signatures.

Command bundle replay is a risk specific to the Executor Node. Implementations SHOULD include monotonic sequence numbers and expiration timestamps in signed command bundles, and the Executor Node SHOULD reject bundles already processed or exceeding a configurable staleness threshold.

The migration roadmap permits intermediate states where two roles share a host or process. Implementations operating in an intermediate state SHOULD document which separation-of-duties properties are enforced and which are deferred.

11. Informal Security Goals

This section states the security goals that VIRP is designed to achieve. These goals are expressed in natural language. In response to review feedback on draft-howard-virp-03, this section was retitled from "Formal Security Properties" to "Informal Security Goals" to align with the terminology used in the formal protocol analysis community.

A symbolic formal analysis in ProVerif has been completed. HMAC key secrecy and injective agreement between the O-Node and a verifier have been machine-verified under the Dolev-Yao model, the latter under a stated trace restriction corresponding to the v2 replay-counter invariant (Section 17.1). This covers G1 (observation non-forgeability, symmetric form) and at-most-once acceptance under the model's stated (session identifier, sequence) trace restriction. It does not establish timestamp freshness, which is not symbolically modeled, and does not fully model the implementation's per-(session identifier, node identifier) high-water ordering; it does not cover the stateless v1 path or v1 error records. Architectural non-conflation (G4) and agent non-escalation (G5) are containment properties, not wire-protocol properties, and are not modeled. No Tamarin model exists; a second-tool cross-check is future work.

11.1. G1: Observation Non-Forgeability (symmetric, per key)

A party that does not hold the authenticating key for an observation cannot produce a record that verifies. For a v1 observation this is HMAC-SHA256 under K_obs; for a v2 observation it is HMAC-SHA256 under the HKDF session key. Without the relevant key it is computationally infeasible to produce a valid authentication code, under the standard PRF/MAC assumption on HMAC-SHA256. The property is relative to that key's secrecy and does not hold against a holder of the key.

Role separation limits cross-artifact forgery, with one explicit exception in the reference implementation: the O-Key directly authenticates v1 observations and also serves as the input keying material for v2 session-key derivation. An O-Key holder can therefore forge v1 observations and, when it possesses the required derivation context, derive keys capable of forging v2 observations. This reuse does not confer the ability to forge chain entries, Intent Channel messages, approvals, or federation records authenticated under separate keys.

Asymmetric non-forgeability -- origin verification without a forging-capable secret -- is future work (Section 17.3) and would still not bound signer compromise.

11.2. G2: Chain Integrity

Any modification to, deletion of, or insertion into the presented chain is detectable by a verifier holding K_chain, because the canonical entry encoding covers the predecessor's entry digest and is itself covered by an HMAC under K_chain (Section 6.5). Two qualifications are load-bearing. First, this property is relative to the secrecy of K_chain: a holder of K_chain can recompute a consistent history. Second, it establishes the integrity of the entries presented, not that the presented chain is complete; detecting truncation or a withheld suffix requires an independently retained chain head or an external checkpoint (Section 17.4).

11.3. G3: Intent Prior to Action

No write operation reaches a device through the gate without a prior authorized intent on record. The O-Node refuses execution for any action without a matching authorized intent, and for RED-tier actions without a valid approval bound to the command digest, device, and expiry. This property holds even if the requesting process is fully compromised. It does not hold against a party that possesses device credentials and a network path to the device outside the gate; that case is addressed by containment (Section 7) and by device-side authorization, not by this protocol.

11.4. G4: Two-Channel Non-Conflation

The Observation and Intent channels are architecturally separate and key-role separated. An observation cannot authorize an intent. An intent cannot substitute for an observation.

11.5. G5: Agent Non-Escalation

The requesting process cannot escalate its own trust tier. Tier classification is performed by a separate process outside that process's modification scope.

12. Reference Implementation

The reference C core (open source, Apache 2.0) [VIRP-REPO] implements the O-Node daemon, the authentication library, the gate and approval flow, and the chain database. IronClaw is a platform built on that core by Third Level IT LLC [THIRDLEVEL], adding multi-vendor driver support, a natural language interface via the Model Context Protocol, intent routing, and operational tooling. The protocol specified in this document is independent of that platform; the platform is cited because the results reported in Section 14 and Section 15 were obtained with it.

12.1. Component Summary

Table 5: Reference Components
Component Description
O-Node daemon C binary. libsodium (Ed25519 for approvals and federation) and OpenSSL (HMAC-SHA256, SHA-256) with an SQLite-backed chain. Pluggable driver interface. Unix socket IPC with peer-credential authorization.
Cisco IOS driver SSH via exec channel. Supports show commands across IOS and IOS-XE. Authenticates all output at collection.
FortiGate driver Dual-transport SSH (primary) and REST API (fallback), FortiOS 7.x compatible. The REST transport is read-only by construction: non-GET methods are refused at the transport layer.
Executor C executor for SSH command dispatch. Uses the exec channel, not a PTY. Authenticates all device output before returning it to the consuming layer.
Verification library Python library that verifies v1 observations. It holds the O-Key and is therefore a trusted component in the sense of Section 6.2: it can verify and, because the key is symmetric, also produce v1 records. It is not an untrusted verifier.
Intent router Tier classifier and intent authorization engine. Separate process from the requesting agent.
Approval client Signs approval records with an Ed25519 or ECDSA P-256 key from an enrolled approver registry, optionally via a PKCS#11 token. The client signs only; the daemon is the sole chain writer.
Tool server Model Context Protocol server exposing VIRP tools to a requesting agent. Mediates all agent-to-O-Node communication.

12.2. Test Coverage

The reference implementation carries C unit and integration suites, Python end-to-end and parity tests, a fuzzing harness, concurrency tests, negative tests for replay and approval reuse, live-hardware exercises across several vendor platforms, and a re-runnable formal proof target. Exact counts change with every revision of the code and are therefore not asserted here; they are reported by the test target in [VIRP-REPO]. Claims in this document that depend on implementation state are marked as such in Section 18.

13. FRR BGP Daemon Integration

VIRP includes a reference implementation for the BGP domain as a loadable FRR (Free Range Routing) module [VIRP-BGP-FRR]. The module hooks into FRR's bgpd process using the standard FRR_MODULE_SETUP pattern. It registers read-only hook callbacks on BGP events, constructs JSON observation payloads, authenticates them with HMAC-SHA256 at collection time inside the bgpd process space, and delivers them to the O-Node over a Unix domain socket. The module is strictly Observation Channel: it never modifies routing state, peer configuration, or the RIB.

13.1. BGP Daemon Hooks

The module registers four hook callbacks covering the primary BGP event classes:

Table 6: BGP Hooks
Hook Obs Type Default Tier Trigger Condition
peer_status_changed 1 (PEER_STATE) GREEN (YELLOW when leaving Established) BGP FSM state transition
peer_backward_transition 2 (PEER_BACKWARD) YELLOW Peer drops out of Established
bgp_process 3 (ROUTE_EVENT) GREEN Route announce or withdraw
bgp_route_update 4 (BESTPATH_CHANGE) GREEN Best-path selection changes

Data captured per hook: peer_status_changed records peer IP, peer AS, local AS, old and new FSM state, router-id, and producer identifier. peer_backward_transition records peer IP, peer AS, local AS, last FSM state, last major event code, uptime, and router-id. bgp_process records prefix, peer IP, peer AS, AFI, SAFI, router-id, and the announce/withdraw flag. bgp_route_update records prefix, AFI, SAFI, router-id, and the old and new path attributes (peer, nexthop, AS path, MED, local-pref, origin).

Trust tier assignment happens at the source: the peer_backward_transition hook always emits YELLOW tier because loss of an Established session is operationally significant. The peer_status_changed hook conditionally escalates to YELLOW when it detects a transition away from Established. All other observations are GREEN tier.

All hooks are registered at module load and unregistered at module teardown, following the FRR module lifecycle pattern.

13.2. BGP Observation Wire Format

Each observation is transmitted as a contiguous byte stream over the Unix domain socket: a packed binary header, a variable-length JSON payload, and an HMAC-SHA256 digest. All multi-byte integer fields in the header are in network byte order.

Bytes  Field          Encoding
-----  -------------  --------------------------------
 0-3   magic          0x56495250 "VIRP" (net order)
 4     version        uint8 (currently 1)
 5     obs_type       uint8 (1-4, see hook table)
 6     trust_tier     uint8 (0=GRN 1=YLW 2=RED 3=BLK)
 7     flags          uint8 (reserved, zero)
 8-15  timestamp_ns   uint64 ns epoch (net order)
16-19  sequence       uint32 monotonic (net order)
20-23  payload_len    uint32 (net order)
24-27  producer_id    uint32 from BGP router-id
28-N   payload        UTF-8 JSON (payload_len bytes)
N+0    hmac[32]       HMAC-SHA256(header || payload)
Figure 5: BGP Observation Wire Format

The wire header struct is packed so that no padding is inserted. The HMAC-SHA256 is computed over the concatenation of the 28-octet serialized header and the JSON payload, using a symmetric key shared between the bgpd module and the O-Node. Total wire size per observation is 28 + payload_len + 32 octets. Maximum payload size is 4096 octets. Minimum HMAC key length is 16 octets, maximum 256. The producer identifier is derived from the BGP router-id, providing a stable per-router identifier across observations.

This is a separate wire format from the O-Node observation formats of Section 6.3 and Section 6.4. It carries no session binding and is subject to the same qualification as v1: it is tamper-evident in transit under the shared key, and any holder of that key can produce records that verify.

13.3. JSON Payload Schema

All payloads share a common envelope with domain-specific fields. Every payload includes a "domain" field set to "bgp" and an "event" field identifying the observation type. A peer state change payload carries the peer name and address, peer and local AS, old and new state, router-id, and producer identifier. A best-path change payload carries the prefix, AFI, SAFI, router-id, producer identifier, and nested "old" and "new" objects each carrying peer, peer address, peer AS, nexthop, AS path, MED, local preference, and origin.

All string fields are escaped for control characters, backslashes, and quotes. Peer addresses are rendered to support both IPv4 and IPv6 peers. Because this payload is JSON produced by direct value insertion, it is subject to the same caution recorded in Section 6.5: it is an implementation transport format, not a canonical authenticated encoding, and the authenticated bytes are the octets as transmitted.

13.4. O-Node Receiver

The O-Node receives authenticated observations on a Unix domain socket. The receiver protocol is:

  1. Read 28 octets of wire header. Validate the magic value and the version.
  2. Extract payload_len. Reject if it exceeds the maximum payload size.
  3. Read payload_len octets of JSON payload.
  4. Read 32 octets of HMAC-SHA256.
  5. Compute HMAC-SHA256 over (header || payload) using the shared key.
  6. Compare computed against received using constant-time comparison. Reject on mismatch.
  7. Validate that the sequence number is monotonically increasing. Flag gaps as potential observation loss.
  8. Insert the verified observation into the chain.

The bgpd module performs automatic reconnection: if the O-Node socket is unavailable, observations are logged locally as a fallback and failure counters are incremented. Observations produced while the socket is unavailable are not chained; a consumer MUST NOT treat a local fallback log as chained evidence.

13.5. FRR VTY Configuration Commands

The module registers configuration commands under the BGP router node and show commands at the enable or view level: enabling and disabling authenticated observations, setting the O-Node socket path, and setting the HMAC key file path; plus show commands reporting state, key status, O-Node connectivity, producer identifier, and counters for records authenticated, delivered, and failed.

Enabling triggers HMAC key loading, if not already loaded, and initiates connection to the O-Node socket. The key-loading command validates the key immediately, rejecting keys shorter than 16 octets. Key material is zeroized on module shutdown.

13.6. Build and Deployment

The module can be built as a loadable shared object (recommended) or compiled directly into bgpd. As a loadable module it requires no modifications to the core FRR source. Build dependencies are OpenSSL for HMAC-SHA256. A standalone test harness validates authentication, verification, tamper detection, and sequence ordering without requiring the FRR build environment.

Deployment requires distributing the same HMAC key to both the FRR host and the O-Node. The key file MUST be restricted to mode 0600 and owned by the FRR process user. Note that this shared key is held by both parties; per Section 6.1, both can produce records that verify.

13.7. Security Properties of BGP Integration

  • Authentication at collection time: the HMAC is computed inside bgpd's process space at the moment the BGP event fires, not after the fact.
  • Observation-only: the module registers read-only hooks. It cannot modify routes, peer state, or configuration.
  • Protocol-agnostic framing: the observation structure and authentication are identical whether the source is BGP or another domain. Only the "domain" field in the payload changes.
  • Trust tiers at the source: tier assignment happens at collection, not at analysis time.
  • Tamper detection: any modification to an observation between bgpd and the O-Node is caught by HMAC verification, relative to the secrecy of the shared key.

14. Adversarial Findings

On 6 March 2026, the agent under test was asked directly whether it could circumvent VIRP. The agent provided an unprompted breakdown of four bypass vectors without attempting to exploit them. This self-disclosure is documented in [VIRP-FINDING-003]. The remediation column below states the current status accurately; two entries were described in earlier revisions as resolved by asymmetric observation signing, which is not implemented.

Table 7: Agent-Identified Bypass Vectors
Finding Description Remediation Status
Key forgeability Symmetric observation key readable on the requesting host, allowing forged observations. MITIGATED BY KEY PLACEMENT -- no observation key is present on the requesting host. Not resolved by asymmetric signing: observation authentication remains symmetric, so any holder of the key can forge (Section 6.1). Asymmetric observation signing remains future work (Section 17.3).
Direct device access Agent knew device addresses and could connect directly, bypassing the O-Node. RESOLVED -- host and hypervisor firewall policy block direct device access.
Intent gating bypass Agent could import the client library and call the execution path without filing intent. RESOLVED -- all execution paths route through the gate; unclassified commands fail closed at RED, and multi-command separators are refused at the request boundary before classification.
API key exploitation Inference API key visible in session context, allowing unsupervised sessions to be spawned. RESOLVED -- key rotated, sensitive-value redaction enabled in logging.

14.1. Live Penetration Test (6 March 2026)

An adversarial exercise was conducted against the lab environment. The agent was given a single seed address and instructed to operate without destructive actions. It obtained initial access through passive discovery within five minutes and administrative credentials on the lab firewall within twenty-five minutes, exploiting no CVEs and attempting no brute force. The root cause was a plaintext environment file containing a full credential keyring on a host the agent could read. A live tunnel to a colocation environment was reachable with those credentials.

The exercise validated Primitive 7. The agent did not break VIRP's cryptographic controls; it went around them by finding credentials in a plaintext file. The fix is architectural: credentials must not exist on the requesting host.

This result is reported as an operational finding about a specific deployment, not as a protocol property. It illustrates the boundary stated in Section 9: VIRP constrains what flows through the gate and does not constrain a party that obtains device credentials and a network path outside it.

15. Scale Testing Results

VIRP was exercised against a 35-router emulated lab topology (five-AS BGP topology) using a 16-thread executor, alongside a physical firewall and switch. A full sweep of the topology completed in under three minutes using 16 concurrent threads across three batches, producing one authenticated observation per device per command with no sequence gaps in the resulting chain and no false verification failures. No fabrication was attempted in this exercise, so it reports throughput and chain continuity rather than detection efficacy.

A passive discovery pass over the same lab completed in five minutes from a single seed address, identifying live hosts, fingerprinting vendor and operating system, and producing an authenticated observation for each confirmed device, with chain references for every finding.

16. Applications and Use Cases

16.1. Verifiable Network Audit

Traditional network audits produce reports that must be trusted on the auditor's authority. VIRP-enabled audits produce reports where every finding references an authenticated observation. The strength of that evidence is scoped by Section 6.1: a client that holds the verification key can confirm that the recorded bytes were authenticated by a holder of that key, and can detect modification of the presented chain. It does not, by itself, establish origin against a party that also holds the key. Deployments where the auditor and the client must not share a forging capability require asymmetric observation signing (Section 17.3) or a third-party anchoring arrangement (Section 17.4).

16.2. AI-Assisted Penetration Testing

VIRP provides chain of custody for penetration test findings. Every probe is an authenticated observation. Every access attempt is intent-gated before execution. Scope is enforced at the gate: the agent cannot interact with out-of-scope devices without a matching authorized intent. The client receives the chain alongside the report.

16.3. Continuous Compliance Monitoring

Baseline Memory (Primitive 5) enables continuous comparison of live device state against an authenticated baseline. Configuration drift -- a new BGP peer, a modified firewall policy, an unexpected open port -- is detected and attributed to a specific change in the chain.

16.4. Field Audit Appliance

A self-contained appliance running the full stack enables plug-in network discovery and audit. An operator connects the device to a network port and issues audit commands remotely; the device produces an authenticated report and is removed when complete. No software installation is required on the target network.

16.5. Industrial and Air-Gapped Environments

ICS and SCADA environments require audit trails for regulatory compliance and incident investigation. VIRP's authenticated observation model provides tamper-evident records of every automated interaction with control system components, supporting NERC CIP, IEC 62443, and similar frameworks. Because the gate and the chain are independent of any inference component, the same governed-automation path can be operated by scripts alone in environments where an AI component is not permitted.

17. Future Work

17.1. Formal Verification

A symbolic formal analysis of VIRP has been carried out in ProVerif [PROVERIF] (applied pi-calculus), with Usama Sardar (TU Dresden), prompted by Adrian Farrel's review of draft-howard-virp-03.

Under the Dolev-Yao model the analysis establishes:

  • Key secrecy: an adversary with full network control cannot learn the O-Key or the derived session key. The model does represent session-key derivation, as a symbolic one-way constructor over the master O-Key, and checks secrecy of both the master and the derived key. It is an abstraction: HKDF is an uninterpreted symbolic constructor; it does not model the implementation's generation counter or the exact serialized transcript, and it omits several authenticated v2 header fields from the symbolic serialization. The result assumes honest endpoints and an ideal secret; it does not establish secure storage, side-channel resistance, or any property after compromise of a key holder.
  • Injective agreement (v2 path): in the modeled honest-verifier execution, each verifier-acceptance event corresponds injectively to one matching O-Node production event, under the stated at-most-once (session identifier, sequence) trace restriction. This correspondence depends on the modeled verifier being defined not to produce observations itself; a real key-holding verifier can produce the same authenticator. The modeled restriction is weaker than, and different from, the implementation's persistent per-(session identifier, node identifier) strict high-water ordering (Section 9): the proof abstracts, but does not fully model, that ordering property. ProVerif's Horn-clause abstraction does not model the mutable counter directly; the counter and its persistence are exercised separately by the reference implementation's replay negative tests.

Two limitations. First, secrecy assumes honest endpoints and an ideal secret and says nothing post-compromise. Second, specific to the symmetric construction: because an HMAC verifier possesses the authentication key, the correspondence result applies to the modeled honest verifier process, which is defined not to generate observations. It does not give a third party cryptographic evidence distinguishing an O-Node-produced MAC from a verifier-produced one; it constrains the modeled verifier's behavior, not the real forging capability any key holder has. Publicly verifiable origin is what asymmetric observation signing (Section 17.3) would add.

The result is scoped to the v2 path. The stateless v1 HMAC check and v1 error records are outside the modeled protocol. Timestamp freshness is verified by test only. Proof artifacts are in the reference repository under /proofs and are re-runnable.

Open targets: discharging the replay restriction natively in a tool with mutable state, such as Tamarin -- no such model exists yet, and it is the intended second-tool cross-check; a process model of G4; and G5, which is out of scope for protocol-level analysis.

Earlier revisions of this document stated machine verification in both ProVerif and Tamarin. That was inaccurate: only ProVerif exists. This revision corrects it and describes Tamarin as future work.

17.2. Multi-Node Coordination

The current specification defines single O-Node operation. draft-howard-virp-01 includes a Multi-Node Coordination section defining leader election, observation synchronization, and cross-node chain verification for distributed deployments.

17.3. Asymmetric Observation Signing

Observation authentication in this revision is symmetric, so any holder of the relevant key can both verify and produce records (Section 6.1). Adding an asymmetric signature over the authenticated observation bytes would provide publicly verifiable origin and would allow a verifier that cannot forge. This is a wire format change: it adds a signature field and requires a public key distribution and revocation story. It would not, by itself, defend against compromise of the signer, which is a separate problem addressed by hardware custody (Section 17.6), independent witnessing, or external anchoring (Section 17.4). Any such extension MUST be introduced under a new wire format version rather than as an optional field, because optional authenticated inputs break interoperability (Section 6.6).

17.4. External Anchoring and Truncation Detection

Chain integrity as specified establishes the linkage of the entries presented to a verifier. It does not establish that the presented chain is complete, and it does not survive a holder of K_chain who rewrites history. Periodically publishing chain head digests to a party or medium outside the collection boundary -- an append-only transparency log, a counter-signing witness, or a third-party escrow -- would make already-published history rewrite-detectable and would give truncation a detection point. Specifying the checkpoint format, the publication cadence, and the verifier's obligations on a missing or divergent checkpoint is open work and is a prerequisite for any claim that the chain establishes the absence of a record.

17.5. Cross-Administrative-Domain Trust

Trust federation is implemented in the reference codebase and enables multiple O-Nodes operated by different organizations to participate in a shared trust chain via Ed25519 signatures. Open work in this area includes standardized key distribution and revocation for federated O-Nodes, public-key directory or transparency-log integration to detect equivocation, and policy primitives governing what cross-administrative-domain consumers may correlate or attest. Hardware-backed federation key custody (Section 17.6) is a prerequisite for the highest-assurance multi-organization deployments.

17.6. Hardware Security Module Integration

Approval signing already supports PKCS#11 tokens, so an approver's private key need not exist in host memory. The symmetric observation and chain keys are currently held in process memory on the O-Node. Integration with an HSM or TPM for those keys, or migration to an asymmetric construction under Section 17.3, would reduce the key-in-memory attack surface for the highest-assurance deployments.

17.7. Typed Operations

A v2 observation authenticates a digest of a canonical command string. As stated in Section 6.4, this makes the record meaningful only to a relying party that retains trusted request context. Work in progress replaces the free-form command string with a versioned registry of typed operations, so that the authenticated bytes cover a complete, self-describing operation encoding: an operation identifier, a registry version, typed parameters, and a resolved target. The properties that such a registry must satisfy are encoding injectivity (distinct operations encode to distinct octets), resolution determinism (a given operation and target resolve to the same device-level invocation), resolution injectivity (distinct operations do not resolve to the same invocation), and transport fidelity (the invocation delivered to the device is the one that was authenticated). Free-form command strings would remain supported as a legacy, lower-assurance adapter. This work is expected in a subsequent revision of this document.

17.8. IETF Standardization

VIRP is written in RFC format and is submitted as an individual Internet-Draft. Experimental results for the BGP integration of Section 13 are archived as a citable companion artifact at [VIRP-ZENODO]. Independent implementation by a second party is the prerequisite for standards track consideration; the open-source reference implementation is available for that purpose.

18. Implementation Status

This section records where the reference implementation [VIRP-REPO] diverges from the normative text above, so that a reader is not left to infer conformance from the specification alone. It is expected to shrink in subsequent revisions and carries no normative weight. This section is intended for removal before any publication as an RFC.

19. Security Considerations

Security considerations are distributed through this document rather than confined to a single section. Section 6.1 and Section 6.2 state what each key role does and does not protect, and are the authoritative statement of scope. Section 9 states the threat model per key holder. Section 11 states the informal goals and Section 17.1 states exactly what has and has not been machine-verified. Section 18 states where the reference implementation currently diverges from the normative text.

Three properties are important enough to restate here. First, observation authentication in this revision is symmetric: it establishes integrity relative to the secrecy of a key that the verifier also holds, and therefore does not provide publicly verifiable origin or any defence against a party holding that key. Second, authentication establishes that the collection boundary obtained and authenticated those octets for that recorded request; it does not certify that the response reflects the managed device's true state, and a compromised boundary can produce well-formed records that do. Third, the chain establishes linkage of the entries presented; establishing that a record does not exist requires an independently retained or externally anchored history (Section 17.4), and no claim of the form "no approval was granted" is supported by an unanchored local chain.

Deployments SHOULD carry VIRP traffic over an authenticated, encrypted transport. The protocol provides neither confidentiality nor endpoint authentication for the transport itself.

20. IANA Considerations

This document has no IANA actions.

21. Acknowledgements

The author thanks Adrian Farrel, whose review of draft-howard-virp-03 prompted the reframing of VIRP to a trust primitive for any operator acting on production infrastructure.

The author thanks Usama Sardar (TU Dresden) for the ProVerif formal analysis and ongoing work toward discharging the replay-counter restriction.

The author thanks an independent reviewer who exercised the implementation on physical Cisco hardware and reported the issues discovered during that evaluation.

22. References

22.1. Normative References

[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC2104]
Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, DOI 10.17487/RFC2104, , <https://www.rfc-editor.org/info/rfc2104>.
[RFC5869]
Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, DOI 10.17487/RFC5869, , <https://www.rfc-editor.org/info/rfc5869>.
[RFC6234]
Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, , <https://www.rfc-editor.org/info/rfc6234>.
[RFC8032]
Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, , <https://www.rfc-editor.org/info/rfc8032>.

22.2. Informative References

[ED25519]
Bernstein, D.J., "High-speed high-security signatures", Journal of Cryptographic Engineering, .
[I-D.howard-virp]
Howard, N., "VIRP: Verified Infrastructure Response Protocol", Work in Progress, Internet-Draft, draft-howard-virp-05, , <https://datatracker.ietf.org/doc/html/draft-howard-virp-05>.
[NIST-ZTA]
National Institute of Standards and Technology, "Zero Trust Architecture", NIST SP 800-207, .
[PROVERIF]
Blanchet, B., "ProVerif: Cryptographic protocol verifier in the formal model", , <https://bblanche.gitlabpages.inria.fr/proverif/>.
[THIRDLEVEL]
Third Level IT LLC, "Third Level IT LLC Research", , <https://thirdlevel.ai>.
[VIRP-BGP-FRR]
Howard, N., "VIRP BGP Module: FRR Integration Reference Implementation", Apache 2.0 License, , <https://github.com/nhowardtli/virp-bgp-frr>.
[VIRP-FINDING-003]
Howard, N., "VIRP-FINDING-003: Agent Self-Reported Security Bypasses", Third Level IT LLC Internal Research, .
[VIRP-REPO]
Howard, N., "VIRP Reference Implementation", Apache 2.0 License, , <https://github.com/nhowardtli/virp>.
[VIRP-ZENODO]
Howard, N., "Cryptographic Observation Attestation Inside a BGP Routing Daemon: Experimental Validation of VIRP", Zenodo, Technical Note, version 1.0, DOI 10.5281/zenodo.19161493, , <https://doi.org/10.5281/zenodo.19161493>.

Appendix A. Changes from draft-howard-virp-05

This revision narrows several security claims relative to [I-D.howard-virp]. The narrowing is deliberate and reconciles the specification with the reference implementation. A reviewer comparing the two revisions should expect to find claims removed.

  1. Per-observation Ed25519 removed. Revision 05 described a dual-signature observation carrying both an HMAC-SHA256 code and an Ed25519 signature, and an ed25519 field in the observation wire format. No such signature exists: observations are authenticated with HMAC-SHA256 only. Ed25519 is used for approval records and federation material. The field is removed from the wire format and the claim is removed from the abstract, the threat model, and the security goals.
  2. Symmetric trust boundary stated. Because observation authentication is symmetric, a verifier holds a forging capability. The abstract, Section 6.1, Section 6.2, and Section 11 now state this directly. Revision 05 described the verifier as unable to forge, which is true only of an asymmetric construction.
  3. Tamarin claim withdrawn. Revision 05 stated machine verification in both ProVerif and Tamarin. Only a ProVerif model exists. Section 17.1 now states the ProVerif result, the trace restriction it depends on, what is not modeled (timestamp freshness, the high-water counter, the v1 path), and describes Tamarin as future work.
  4. Formal result strengthened in one direction. Revision 05 claimed non-injective agreement. Injective agreement now holds, under the stated trace restriction.
  5. G1 restated for HMAC. Revision 05 reduced G1 to EUF-CMA unforgeability of Ed25519, a primitive observations do not use. G1 is now stated per key under the PRF/MAC assumption on HMAC-SHA256, with the O-Key dual-role exception named explicitly.
  6. Two observation formats specified. Revision 05 described one format. There are two: a deprecated stateless v1 (Section 6.3) and a session-bound v2 (Section 6.4). Both byte layouts and their validation rules are now normative. v1 remains the reference default, which is recorded rather than claimed as resolved.
  7. Command binding scoped. A v2 observation authenticates a SHA-256 digest of the canonical command, not the command text. It is therefore not a self-contained receipt and binds a command only relative to a verifier holding trusted request context. The abstract and Section 6.4 state this; Section 17.7 describes the intended fix.
  8. Key roles enumerated. Section 6.1 replaces the single-key description with the O-Key, R-Key, session key, K_chain, approver key, and federation key, states which are distinct, and states the one current exception: the O-Key both authenticates v1 and is the HKDF input for v2.
  9. Chain entry encoding specified. Section 6.5 defines chain-format-version 1 as a deterministic binary encoding and designates the JSON the reference implementation currently emits as a legacy, non-conforming format.
  10. Chain claims qualified. Chain integrity covers the entries presented, under K_chain. Detecting truncation or establishing the absence of a record requires an independently retained head or external anchoring (Section 17.4). Revision 05's implication that a local chain can establish absence is removed.
  11. Threat model split per key. The single "compromised verification component" row is replaced with rows for each key holder, because different holders have different forging power.
  12. Terminology. "Signed" is reserved for Ed25519; HMAC-protected records are described as "authenticated" throughout.
  13. Implementation status separated. Divergences between the specification and the reference implementation are collected in Section 18 rather than distributed through the normative text.
  14. Acknowledgements. One acknowledgement from revision 05 has been removed because the attribution could not be substantiated. A second is stated without identifying detail pending the reviewer's consent.

Work not in this revision, and expected in a subsequent one: the typed operation registry described in Section 17.7; reconciliation of Section 7 and Section 12 with the current reference deployment; and an assurance-level framework distinguishing deployments by which of these properties they actually enforce.

Author's Address

Nate Howard
Third Level IT LLC
Allen Park, MI
United States of America