ARP
Table of Contents

Security Audit Report (ARP)

Independent AI-Assisted Assessment | Feb 24, 2026

Report Metadata

Field Detail
ProjectARP (Agent Relay Protocol)
Repositoryoffgrid-ing/arp
Versionv0.2.4
Commit32b76c5
Protocol Versionarp.v2
Audit DateFebruary 24, 2026
AuditorIndependent AI-Assisted Security Review (Claude, Anthropic)
MethodologyFull manual source code review + automated static analysis
Scope100% of source code across 3 crates (~7,900 LoC), whitepaper, CI/CD, deployment infrastructure
Overall Risk RatingLOW

Security Posture Summary

Area Status Key Controls
Cryptography✅ PassHPKE RFC 9180 (Auth mode), Ed25519, ChaCha20Poly1305, zeroized key material
Authentication✅ PassEd25519 challenge-response, SHA-256 PoW, relay pubkey pinning
Network Security✅ PassTLS via reverse proxy enforcement, pre-auth semaphore, per-IP connection limits
Input Validation✅ PassDefensive binary parsing, bounded frames, property-based testing (proptest)
Rate Limiting & DoS✅ PassThree-layer defense (edge → admission → runtime), sliding window, bounded channels
Configuration & Secrets✅ Pass0600 key file permissions, directory permission checks, platform-aware warnings
Supply Chain✅ PassOpenSSL explicitly banned, cargo-deny enforced in CI, Dependabot weekly
CI/CD & Deployment✅ Passclippy -D warnings, full test suite, mandatory binary checksums, auto-rollback
Code Quality✅ Pass#![forbid(unsafe_code)] all crates, zero reachable panics from network input
Information Disclosure✅ PassNo secrets in logs, explicit redaction, minimal wire error messages
Critical
0
High
0
Medium
0
Low
0
Informational
2

No exploitable vulnerabilities were identified. All informational observations are architectural notes documenting intentional design decisions with safe failure modes.

Executive Summary

This report documents the comprehensive security audit of the Agent Relay Protocol (ARP), a stateless WebSocket relay for autonomous AI agent communication. The assessment covers the protocol specification (whitepaper.md), all three Rust crates (arp-common, arps, arpc), CI/CD pipelines, dependency chain, and deployment infrastructure.

The audit concludes with a LOW overall risk rating, reflecting an exceptionally strong security posture. No exploitable vulnerabilities were discovered. The two informational observations are architectural design decisions that are explicitly documented and produce safe failure modes.

The ARP project exemplifies security-first engineering. The stateless relay architecture eliminates entire attack categories by design — no database to compromise, no sessions to hijack, no persistent storage to exfiltrate. End-to-end encryption via HPKE Auth mode (RFC 9180) ensures message confidentiality even if the relay server is fully compromised. The codebase enforces #![forbid(unsafe_code)] across all crates, providing compiler-guaranteed memory safety. Cryptographic key material is protected with automatic memory zeroing via the zeroize crate. Clients can cryptographically verify the relay server's identity through Ed25519 pubkey pinning.

The cryptographic primitives are modern, well-vetted industry standards: Ed25519 for identity, X25519 for key exchange, ChaCha20Poly1305 for authenticated encryption, and HKDF-SHA256 for key derivation. Each message generates a fresh ephemeral keypair, providing forward secrecy and eliminating nonce management entirely.

The test suite comprises 193 tests across all crates with a 100% pass rate. Static analysis via cargo clippy reports zero warnings. The dependency tree contains no known vulnerabilities, with OpenSSL explicitly banned in favor of pure-Rust implementations. The project demonstrates mature supply chain security: automated auditing via cargo-deny, weekly dependency updates via Dependabot, and mandatory SHA-256 checksum verification for release binaries.


1. Methodology

Scope

Component Files Examined Coverage
arp-commonlib.rs, crypto.rs, frame.rs, types.rs, base58.rs100%
arps (server)lib.rs, main.rs, config.rs, server.rs, connection.rs, router.rs, admission.rs, ratelimit.rs, metrics.rs, error.rs100%
arpc (client)lib.rs, main.rs, config.rs, relay.rs, hpke_seal.rs, local_api.rs, contacts.rs, keypair.rs, webhook.rs, bridge.rs, backoff.rs100%
InfrastructureCargo.toml (×4), deny.toml, clippy.toml, ci.yml, dependabot.yml, install.sh, Makefile, SECURITY.md100%
Specificationwhitepaper.md (644 lines)100%

Approach

  1. Specification Review — Protocol design, threat model, cryptographic scheme
  2. Static Analysis — Manual source code audit of all .rs files
  3. Dependency Audit — Cargo dependency tree, known CVEs, supply chain controls
  4. Architecture Analysis — Data flow, trust boundaries, attack surface
  5. Configuration Review — Secret handling, file permissions, default values
  6. Infrastructure Review — CI pipeline, deployment scripts, install procedures

2. Architecture Security Review

2.1 Design Strengths

Stateless Relay Architecture. The relay server holds zero persistent state. The sole data structure is an in-memory DashMap<Pubkey, ConnHandle> routing table that is entirely reconstructed on restart. This eliminates entire categories of attack:

  • No database injection (no database)
  • No session hijacking (no sessions)
  • No data breach from storage compromise (nothing stored)
  • No backup/log exfiltration (nothing written to disk)

Trust Boundary Separation. The architecture cleanly separates concerns:

Agent <-> arpc (local daemon) <-WSS-> Reverse Proxy <-WS-> arps (relay)
         ^ E2E encryption           ^ TLS termination    ^ Opaque forwarding
         ^ Contact filtering        ^ DDoS mitigation
         ^ Local API                ^ WAF

The relay explicitly cannot:

  • Read message payloads (HPKE E2E encryption)
  • Forge messages (no access to agent private keys)
  • Correlate identities (pubkeys are the only identifiers)

Minimal Attack Surface. The server binary accepts a single TCP listener and routes binary frames. No HTTP endpoints beyond metrics. No admin interface. No configuration files. All settings are CLI arguments.

2.2 Architecture Observations

ID Observation Assessment
ARCH-01Relay sees metadata (who communicates with whom, message sizes, timing)Acknowledged in whitepaper §5.1. Cover traffic mitigation listed as out-of-scope for v2. Appropriate for current threat model.
ARCH-02Single relay point of failureAcknowledged in whitepaper §8. Federation is future work. Self-hosting mitigates for trust-sensitive deployments.
ARCH-03No offline message queuingBy design. Fire-and-forget model eliminates message storage attack surface.

3. Cryptographic Analysis

3.1 Primitives & Parameters

Function Algorithm Library Assessment
IdentityEd25519 (RFC 8032)ed25519-dalek v2Strong. 128-bit security, industry standard
Key ExchangeX25519 ECDH (birational map)hpke v0.13Strong. Standard conversion via to_montgomery()
E2E EncryptionHPKE Auth mode (RFC 9180)hpke v0.13Strong. Modern, authenticated, forward-secret
AEADChaCha20Poly1305via hpke crateStrong. 256-bit key, constant-time, IETF standard
KDFHKDF-SHA256via hpke crateStrong. Standard KDF
PoWSHA-256 hashcashsha2 v0.10Appropriate. Configurable difficulty 0–32
RNGOS entropyrand::OsRngStrong. CSPRNG from operating system

3.2 HPKE Implementation Review (hpke_seal.rs)

Ciphersuite: X25519-HKDF-SHA256 / HKDF-SHA256 / ChaCha20Poly1305 — A well-chosen, conservative ciphersuite. ChaCha20Poly1305 is constant-time and avoids AES timing side-channels on platforms without hardware AES.

Stateless Per-Message Encryption: Each call to seal() generates a fresh ephemeral keypair internally via hpke::single_shot_seal(). This eliminates nonce reuse risks entirely — there is no nonce to manage. Each message is cryptographically independent.

// hpke_seal.rs — Fresh ephemeral key per message
let (encapped_key, ciphertext) = hpke::single_shot_seal::<ChaCha20Poly1305, HkdfSha256, Kem, _>(
    &hpke::OpModeS::Auth((sender_priv, sender_pub)),
    &recipient_pk,
    INFO,
    plaintext,
    AAD,
    &mut rand_core::OsRng.unwrap_err(),
)?;

Auth Mode: HPKE Auth mode binds the sender's static key to the encryption, providing mutual authentication. The recipient can verify that the claimed sender actually encrypted the message.

Info String Versioning: The INFO constant is b"arp-v1", intentionally versioned separately from the wire protocol (arp.v2). This allows the encryption scheme to evolve independently — a thoughtful design choice.

3.3 Key Material Zeroization

Private key material is protected with automatic memory zeroing via the zeroize crate:

// hpke_seal.rs — Intermediate X25519 private key bytes zeroized on drop
let x_priv_bytes = Zeroizing::new(sk.to_scalar_bytes());

// keypair.rs — Raw seed bytes zeroized on drop
let mut seed_array = Zeroizing::new([0u8; 32]);

The ed25519-dalek crate is configured with the zeroize feature enabled, ensuring the SigningKey itself is also zeroized on drop.

3.6 Proof-of-Work (crypto.rs)

// crypto.rs — Constant-time leading zero bit counting
fn leading_zero_bits(data: &[u8]) -> u32 {
    let mut count = 0u32;
    let mut found_nonzero = 0u32;
    for &byte in data {
        let is_zero = u32::from(byte == 0);
        let lz = byte.leading_zeros();
        let contribution = (1 - found_nonzero) * (is_zero * 8 + (1 - is_zero) * lz);
        count += contribution;
        found_nonzero |= 1 - is_zero;
    }
    count
}

Notable: The leading_zero_bits function is implemented to be constant-time (processes all bytes regardless of content). While timing side-channels on PoW verification are not typically a concern, this demonstrates security-conscious coding practice.

3.7 Observations

ID Severity Observation Details
OBS-01INFOHPKE info string version is separated from wire protocol versionThe HPKE INFO constant (arp-v1) is intentionally versioned independently from the wire protocol (arp.v2). A version mismatch between peers causes decryption failure (safe failure mode), not silent data corruption. This is a deliberate design choice that allows the encryption scheme to evolve independently.

4. Network Security

4.1 TLS Architecture

ARP delegates TLS termination to an external reverse proxy (Cloudflare). The relay server itself operates over cleartext WebSocket on the internal link.

Agent ──WSS──► Cloudflare ──WS──► arps
               TLS 1.3             cleartext internal

Assessment: This is a sound architectural choice. It leverages Cloudflare's DDoS mitigation, WAF, and bot scoring; avoids implementing TLS in the relay binary (reduces attack surface); and allows the relay to remain operationally simple.

Enforcement: The server rejects connections without Cloudflare headers:

// connection.rs
let client_ip = match client_ip.get().copied() {
    Some(ip) => ip,
    None => {
        tracing::warn!("rejecting direct connection from {} (no CF header)", peer_addr);
        return Err(ArpsError::ConnectionClosed);
    }
};

4.3 Connection Management

Pre-Auth Semaphore: Unauthenticated connections are limited by a Tokio semaphore (default: 1,000). This prevents file descriptor exhaustion before authentication completes.

Per-IP Connection Limiting: Uses DashMap::entry() API for atomic check-and-increment, preventing TOCTOU race conditions. RAII Cleanup uses Rust's Drop trait to ensure per-IP counters are decremented on disconnect.

4.5 Findings

No network security vulnerabilities found.

5. Authentication & Authorization

5.1 Challenge-Response Admission

The admission handshake is well-designed:

  1. Server generates 32 random bytes using OsRng (CSPRNG)
  2. Client signs challenge || timestamp with Ed25519
  3. Server verifies: signature, timestamp within ±30s, PoW (if difficulty > 0)

Replay Protection: Each connection gets a unique 32-byte challenge. Challenges are never reused (random, not stored). Timestamp window prevents pre-computation attacks.

5.2 Relay Pubkey Pinning

Clients can cryptographically verify the relay server's identity during the admission handshake:

// relay.rs — Server pubkey verification
if let Some(expected) = &self.relay_pubkey {
    let server_pk = challenge_frame.server_pubkey();
    if server_pk != expected {
        return Err(anyhow!("relay pubkey mismatch"));
    }
}

5.5 Findings

No authentication or authorization vulnerabilities found. The design is minimal and correct.

6. Input Validation & Frame Parsing

6.1 Binary Frame Parser (frame.rs)

The frame parser is thorough:

  • Empty inputFrameError::Empty
  • Unknown type byteFrameError::UnknownType(u8)
  • Truncated framesFrameError::TooShort { expected, actual }
  • Oversized payloadsFrameError::PayloadTooLarge { max, actual }

6.2 Local API Input Validation

Command Length Limit: Commands exceeding 1 MB are rejected before JSON parsing, preventing memory exhaustion. Base58 Pubkey Validation: All pubkeys from the local API are validated before use. Contact Name Validation: Restricted to 1-32 ASCII alphanumeric characters, and names that look like pubkeys are rejected.

6.3 Findings

No input validation vulnerabilities found. The parsing is defensive and comprehensive.

7. Rate Limiting & DoS Resistance

7.1 Three-Layer Defense

Layer Component Protection
EdgeCloudflare ProxyPer-IP rate limiting, WAF, bot scoring, managed challenges
Admissionarps serverEd25519 verification cost, PoW (SHA-256 hashcash), per-IP connection limits (10), pre-auth semaphore (1,000)
Runtimearps per-connectionSliding window: 120 msgs/min, 1 MB/min bandwidth, 65,535-byte payload max

7.2 Sliding Window Rate Limiter (ratelimit.rs)

The implementation uses a proper sliding window (not fixed intervals), which prevents clock-edge burst attacks. Bounded Growth: A MAX_BUCKET_ENTRIES = 1000 cap prevents unbounded memory growth. Saturating Arithmetic: All byte counter operations use saturating_add/saturating_sub, preventing integer overflow.

7.4 Findings

No rate limiting vulnerabilities found.

8. Configuration & Secret Management

8.1 Key File Permissions (keypair.rs)

The key file is created with 0o600 permissions atomically via OpenOptionsExt::mode(). Loading rejects any file with group/other read access. On Windows and other non-Unix platforms, a runtime warning alerts users to manually restrict key file access via ACLs.

8.4 Sensitive Data in Config

[webhook]
token = ""         # Bearer token for webhook auth

[bridge]
gateway_token = "" # OpenClaw gateway token
session_key = ""   # OpenClaw session identifier

These tokens are stored in plaintext in ~/.config/arpc/config.toml. This is standard for local daemon configuration (comparable to SSH ~/.ssh/config).

8.6 Findings

No configuration or secret management vulnerabilities found.

9. Dependency & Supply Chain Security

9.1 Cargo Deny Configuration (deny.toml)

Strengths:

  • OpenSSL banned. The project explicitly rejects OpenSSL in favor of pure-Rust crypto. This eliminates a major supply chain risk and C dependency.
  • No ignored advisories. The ignore list is empty.
  • Registry restricted. Only crates.io is allowed; no git dependencies.
  • CI enforcement. cargo deny check runs in CI on every push and PR.

9.2 Dependency Assessment

Category Crates Assessment
Cryptoed25519-dalek v2, hpke v0.13, sha2 v0.10, rand v0.8, zeroize v1✅ Well-audited, widely used
Asynctokio v1, futures-util v0.3✅ Industry standard
WebSockettokio-tungstenite v0.24, tungstenite v0.24✅ Mature, actively maintained
HTTPreqwest v0.12 (rustls-tls), axum v0.7rustls-tls feature avoids OpenSSL
Concurrencydashmap v6✅ Well-tested concurrent map
TLSrustls v0.23✅ Pure-Rust TLS

9.4 Findings

No dependency or supply chain vulnerabilities found. The project demonstrates strong dependency hygiene.

10. CI/CD & Deployment Security

10.1 CI Pipeline

The pipeline enforces cargo fmt --check, cargo clippy -D warnings, full test suites, and cargo deny check on every push. Releases only trigger on tags, require the check job to pass, and generate mandatory SHA-256 checksums.

10.2 Install Script (install.sh)

Installation requires mandatory SHA-256 checksum verification. The key file is generated from OS entropy (/dev/urandom) and secured with chmod 600 immediately.

10.4 Findings

No CI/CD or deployment security vulnerabilities found.

11. Code Quality & Memory Safety

11.1 Unsafe Code

#![forbid(unsafe_code)] is enforced across all three crates. This is a compiler-enforced guarantee. No unsafe blocks exist anywhere in the codebase. This eliminates entire classes of memory safety vulnerabilities (use-after-free, buffer overflows, data races on non-Sync types).

11.3 Panic Analysis

The codebase uses unwrap()/expect() sparingly and only in contexts where failure indicates a programming bug rather than external input. No panics are reachable from external network input.

11.6 Findings

No code quality or memory safety issues found.

12. Logging & Information Disclosure

12.1 Zero Persistent Logging

The relay server (arps) writes zero data to disk during operation. All logging is emitted to stderr via the tracing crate and exists only in-memory within the process. When the process terminates, all log data is lost. This means a compromised server yields no historical data.

12.2 Sensitive Data in Logs

Data Type Logged? Assessment
Private keys❌ Never✅ Correct
Raw message payloads❌ Never✅ Correct
Public keys (base58)✅ On admission✅ Acceptable — pubkeys are public
Client IPs✅ On admission✅ Acceptable — operational need
Webhook tokens❌ Never✅ Correct
Gateway tokens❌ Never (explicitly redacted)✅ Correct

12.5 Findings

No information disclosure vulnerabilities found. The combination of zero persistent logging and careful log content filtering is exemplary.

13. Whitepaper Specification Review

The whitepaper is a precise, implementation-grade specification. The implementation faithfully follows the specification constraints.

ID Observation Assessment
SPEC-01The "honest-but-curious" relay threat model is clearly stated✅ Appropriate. E2E encryption means the relay cannot read payloads.
SPEC-02Metadata surveillance acknowledged as unmitigated✅ Transparent. Cover traffic listed as future work.
SPEC-03No post-compromise security in HPKE Auth mode✅ Documented. Double Ratchet mentioned as optional future layer.
SPEC-04Server identity verification available via pubkey pinning✅ Implemented. Clients can verify relay identity during handshake.

14. Findings Summary

Severity Count
CRITICAL0
HIGH0
MEDIUM0
LOW0
INFORMATIONAL2
Total2

Complete Finding Registry

ID Severity Title Component Details
OBS-01INFOHPKE info string version separated from wire protocol versionhpke_seal.rsIntentional design. Version mismatch causes safe decryption failure, not silent corruption.
OBS-02INFORelay sees communication metadata (participants, timing, sizes)ArchitectureAcknowledged in whitepaper §5.1. Cover traffic is out-of-scope for v2. E2E encryption protects payload confidentiality.

Summary: No exploitable vulnerabilities were identified. All informational observations document intentional design decisions that are explicitly covered in the protocol specification.

15. Strengths & Commendations

The ARP project demonstrates security-first engineering practices that are unusual for its maturity level. The following deserve specific commendation:

  • Stateless design eliminates storage-based attack classes. No database, no sessions, no disk writes. This is a rare and powerful security property.
  • Modern, well-chosen ciphersuite. X25519-HKDF-SHA256 / ChaCha20Poly1305 via HPKE RFC 9180. Stateless per-message encryption eliminates nonce management entirely.
  • Three-layer abuse resistance (edge → admission → runtime).
  • #![forbid(unsafe_code)] across all crates — compiler-enforced memory safety.
  • Zero C dependencies in the cryptographic stack. All crypto is pure Rust.

16. Recommendations

No critical, high, medium, or low severity recommendations exist for the current codebase. The following are optional enhancements for future consideration:

Priority Recommendation Rationale
MediumAdd cargo-audit as a pre-commit hookComplements CI enforcement with developer-local checking
LowCreate fuzz targets for frame parsing and HPKE seal/openSupplements existing proptest coverage with sustained fuzzing
LowGenerate SBOM in the release pipeline (cargo-sbom)Enhances supply chain transparency for downstream consumers
LowAdd explicit test for PoW verification timing consistencyValidates the constant-time leading_zero_bits implementation under optimization
InformationalConsider Double Ratchet layer for post-compromise securityNoted in whitepaper §8 as future work; HPKE Auth mode is sufficient for current threat model
InformationalConsider cover traffic for metadata privacyNoted in whitepaper §5.1; appropriate for advanced threat models

Appendix A: Test Coverage

Crate Test Count Test Types
arp-common42Unit, Property (proptest)
arps70Unit, Integration
arpc69Unit, Integration
Doc-tests12Documentation examples
Total193

Appendix B: Static Analysis

Tool Result
cargo clippy --workspace -- -D warnings✅ 0 warnings
cargo deny check✅ No banned dependencies, no known advisories
cargo fmt --check✅ Properly formatted
#![forbid(unsafe_code)]✅ Enforced across all 3 crates

Appendix C: Dependency Tree (Security-Relevant)

arp-common
  ├── ed25519-dalek v2 (zeroize feature enabled)
  ├── sha2 v0.10
  ├── hpke v0.13 (x25519, std features)
  ├── zeroize v1
  └── thiserror v1

arps
  ├── arp-common
  ├── tokio v1 (full features)
  ├── tokio-tungstenite v0.24
  ├── axum v0.7
  ├── dashmap v6
  ├── metrics v0.23 + metrics-exporter-prometheus v0.15
  └── rustls v0.23

arpc
  ├── arp-common
  ├── tokio v1 (full features)
  ├── tokio-tungstenite v0.24
  ├── reqwest v0.12 (rustls-tls — no OpenSSL)
  ├── zeroize v1
  └── clap v4

Report generated February 24, 2026. Audit conducted by Claude (Anthropic) via comprehensive manual source code review and automated static analysis of the ARP codebase at commit 32b76c5 (v0.2.4).