NL Protocol Specification v1.0 -- Chapter 05: Audit Integrity
Status: Draft Version: 1.0.0 Date: 2026-02-08
Note: This document is a SPECIFICATION. It defines required behaviors, data formats, and protocols — not specific products or CLI commands. For implementations of this specification, see IMPLEMENTATIONS.md.
1. Introduction
This chapter defines the Audit Integrity layer of the NL Protocol. Every interaction between an agent and a secret -- whether the interaction succeeds, is denied, or is blocked -- MUST produce a tamper-evident audit record. The audit trail provides the cryptographic proof required to answer four fundamental questions:
- What did Agent X do? (agent attribution)
- Who accessed Secret Y? (secret access history)
- What happened between T1 and T2? (temporal analysis)
- Can I prove this log has not been tampered with? (integrity verification)
The audit trail is the foundation for compliance, forensic analysis, and anomaly detection. If an attacker can modify, delete, or reorder audit records undetected, every other security layer becomes unverifiable. The hash chain defined in this chapter ensures that any tampering is mathematically detectable.
1.1 Critical Constraint: No Secret Values in Audit Records
Secret VALUES MUST NEVER appear in audit entries -- not in plaintext, not encoded, not hashed in a way that is reversible or subject to brute-force. Audit entries record WHAT was done (the action), TO WHAT (the secret's name or reference), and BY WHOM (the agent), but NEVER the secret's content. If audit records contained secret values, the audit log itself would become an exfiltration vector.
1.2 Multi-Platform Scope
The audit schema and integrity mechanisms defined in this chapter are designed to be implementable across any platform:
- Local vaults (file-based, SQLite-based)
- Cloud secret managers (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault)
- SaaS platforms (Stripe, GitHub, Twilio)
- CI/CD systems (GitHub Actions, GitLab CI, Jenkins)
- Custom agent orchestration frameworks
Each platform produces audit entries in the schema defined here. Cross-platform correlation is achieved through shared correlation_id values (Section 8).
2. Audit Entry Schema
2.1 Required Fields
Every audit entry MUST contain the following fields:
{
"entry_id": "01953f2a-7b3c-7def-8a12-4b5c6d7e8f90",
"sequence": 1,
"timestamp": "2026-02-08T10:30:00.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_example",
"session_id": "session_abc123"
},
"delegated_by": "human:admin@example.com",
"action": "exec",
"target": "api/API_KEY",
"result": "success",
"secrets_used": ["api/API_KEY"],
"correlation_id": "req-abc-123",
"platform": "acme-secrets",
"chain": {
"prev_hash": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
"hash": "sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"hmac": "sha256:f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5"
}
}
2.2 Field Definitions
| Field | Type | Required | Description |
|---|---|---|---|
entry_id |
string | MUST | A globally unique identifier. UUID v7 is RECOMMENDED for time-ordered uniqueness. |
sequence |
integer | MUST | A monotonically increasing integer starting at 1. Each new entry MUST have a sequence number exactly one greater than the previous entry. Gaps indicate deletion. |
timestamp |
string | MUST | ISO 8601 timestamp with millisecond precision and UTC timezone (e.g., 2026-02-08T10:30:00.000Z). Implementations MUST use synchronized time sources (NTP). |
nl_version |
string | MUST | The version of the NL Protocol specification this entry conforms to (e.g., "1.0"). |
agent |
object | MUST | The agent that performed the action. See Section 2.3. |
delegated_by |
string | MUST | The principal (human or agent) who authorized the agent to act. Format: human:<email> or agent:<agent_uri>. |
action |
string | MUST | The action type performed. One of: exec, template, inject_stdin, inject_tempfile, list, search, create, update, delete, rotate, blocked, denied, verify. |
target |
string | MUST | The secret reference or resource that was the target of the action. MUST be the secret's name or path, NEVER its value. Format: <name> or <category>/<name> or <project>/<environment>/<name>. |
result |
string | MUST | The outcome. One of: success, denied, blocked, error, timeout. |
secrets_used |
string[] | MUST | List of secret references used in this action. MUST contain only names or paths, NEVER values. Empty array [] for actions that do not involve secrets. |
correlation_id |
string | MUST | A unique identifier linking related actions across platforms and systems. Used for cross-platform tracing. |
platform |
string | MUST | The platform or system that produced this audit entry (e.g., acme-vault, aws-secrets-manager, braincol-vault, stripe-proxy). |
chain |
object | MUST | Hash chain integrity data. See Section 3. |
2.3 Agent Object
The agent field MUST contain:
| Field | Type | Required | Description |
|---|---|---|---|
uri |
string | MUST | The agent's NL Protocol identity URI (Chapter 01). Format: nl://<authority>/<path>. |
organization_id |
string | MUST | The organization the agent belongs to. |
session_id |
string | MUST | A unique identifier for the agent's current session. Sessions are bounded by authentication events. |
2.4 Optional Fields
Implementations MAY include additional fields in audit entries:
| Field | Type | Description |
|---|---|---|
detail |
string | Additional human-readable detail about the action (e.g., "Command executed: curl -H 'Auth: Bearer {{nl:API_KEY}}' ..."). Secret values MUST NOT appear. |
source_ip |
string | The IP address from which the action originated. |
user_agent |
string | The user agent or client identifier. |
duration_ms |
integer | Execution duration in milliseconds (for exec and similar actions). |
rule_id |
string | For blocked results, the ID of the deny rule that triggered the block (Chapter 04). |
error_code |
string | For error results, a machine-readable error code. |
scope_id |
string | The scope ID under which the action was authorized (Chapter 02). |
metadata |
object | An extensible key-value map for implementation-specific data. MUST NOT contain secret values. |
2.5 Prohibited Content
The following MUST NOT appear in any field of an audit entry:
- Secret values in any encoding (plaintext, base64, hex, URL-encoded, hashed with weak algorithms).
- Passwords, tokens, API keys, certificates, or private keys.
- Partial secret values (e.g., first/last N characters).
- Data that could be used to reconstruct or brute-force a secret value.
Implementations MUST scan audit entries for potential secret leakage before writing them to storage. If a secret value is detected in an audit entry, the entry MUST be sanitized (value replaced with [REDACTED]) and a security incident MUST be logged.
3. Hash Chain
3.1 Purpose
The hash chain provides cryptographic proof that audit entries have not been modified, deleted, or reordered after they were written. Each entry includes the hash of the previous entry, creating a chain where any alteration to a single entry invalidates all subsequent entries.
3.2 Chain Object
The chain field in each audit entry MUST contain:
| Field | Type | Required | Description |
|---|---|---|---|
prev_hash |
string | MUST | The hash value of the immediately preceding entry. For the genesis entry (sequence 1), this MUST be sha256: followed by 64 zeros. |
hash |
string | MUST | The SHA-256 hash of this entry's canonical content. See Section 3.3 for the hash calculation. |
hmac |
string | SHOULD | An HMAC-SHA256 of this entry's hash, keyed with the vault's HMAC key. Provides additional integrity assurance. See Section 3.5. |
3.3 Hash Calculation
The hash field is calculated as follows:
hash = SHA-256(canonical_input)
Where canonical_input is the concatenation of the following fields, separated by the newline character (\n), in the exact order specified:
<sequence>\n<timestamp>\n<agent.uri>\n<action>\n<target>\n<result>\n<prev_hash>
Example calculation:
Input:
sequence = 1
timestamp = 2026-02-08T10:30:00.000Z
agent.uri = nl://anthropic.com/claude-code/1.5.2
action = exec
target = api/API_KEY
result = success
prev_hash = sha256:0000000000000000000000000000000000000000000000000000000000000000
Canonical string:
"1\n2026-02-08T10:30:00.000Z\nnl://anthropic.com/claude-code/1.5.2\nexec\napi/API_KEY\nsuccess\nsha256:0000000000000000000000000000000000000000000000000000000000000000"
hash = SHA-256(canonical_string)
= sha256:a1b2c3... (64 hex characters)
Implementations MUST prefix hash values with sha256: to indicate the algorithm used. This enables future algorithm agility.
3.4 Genesis Entry
The first entry in the audit chain (sequence = 1) is the genesis entry. Its prev_hash MUST be:
sha256:0000000000000000000000000000000000000000000000000000000000000000
This is a string of 64 ASCII zeros, prefixed with sha256:. The genesis entry establishes the root of the hash chain.
3.5 HMAC Calculation
The optional hmac field provides an additional layer of integrity by signing the hash with a key that is not stored alongside the audit log. This prevents an attacker who gains write access to the audit log from rewriting the hash chain with valid hashes.
hmac = HMAC-SHA256(key=vault_hmac_key, message=hash)
Where:
vault_hmac_keyis a secret key managed by the vault or audit system. This key MUST be stored separately from the audit log.hashis thechain.hashvalue of the current entry (including thesha256:prefix).
The HMAC value MUST be prefixed with sha256: to indicate the algorithm.
Implementations that support HMAC SHOULD store the HMAC key in an HSM or key management service. The HMAC key MUST be rotated periodically (RECOMMENDED: every 90 days). When the HMAC key is rotated, the audit entry at the rotation point MUST include a metadata.hmac_key_rotated flag set to true.
3.6 Hash Chain Continuity Across Log Rotation
When audit logs are rotated (Section 7), the hash chain MUST continue across rotations:
- The last entry in the old log file has hash
H_last. - The first entry in the new log file MUST have
prev_hash = H_last. - The rotation event itself SHOULD be recorded as an audit entry with
action = "log_rotation".
This ensures that the hash chain is a single, continuous sequence across all log files.
4. Tamper Detection
4.1 Types of Tampering
The hash chain is designed to detect four types of tampering:
4.1.1 Modification
An attacker modifies the content of an existing audit entry (e.g., changing result from "blocked" to "success").
Detection: Recalculate the hash of the modified entry from its fields. The recalculated hash will not match the stored chain.hash. Additionally, all subsequent entries will have invalid prev_hash references.
4.1.2 Deletion
An attacker deletes one or more audit entries from the log.
Detection: A gap in the sequence field indicates deletion. If entry with sequence N exists and the next entry has sequence N+2, an entry has been deleted. Additionally, the prev_hash of entry N+2 will not match the hash of entry N.
4.1.3 Reordering
An attacker changes the order of audit entries (e.g., to make a blocked action appear to have occurred after an authorization change).
Detection: Reordering breaks the hash chain because each entry's hash is calculated using prev_hash, which depends on the previous entry's content and position. Swapping two entries invalidates the hashes of both entries and all subsequent entries.
4.1.4 Truncation
An attacker deletes the most recent entries from the end of the log to remove evidence of recent actions.
Detection: The last known sequence number (from checkpoints or external references) is compared against the current last sequence number. A decrease indicates truncation. External checkpoints (Section 4.3) provide an independent anchor for this comparison.
4.2 Chain Reconstruction Attack
A sophisticated attacker with write access to the audit log could delete entries and then recalculate the hash chain to produce valid hashes. This attack is mitigated by:
- HMAC protection (Section 3.5): Without the HMAC key, the attacker cannot produce valid HMAC values, even if they can recalculate SHA-256 hashes.
- External checkpoints (Section 4.3): Checkpoint hashes published to an external, append-only store cannot be retroactively modified.
- Sequence number gaps: Even with a reconstructed chain, gaps in sequence numbers reveal deletion.
4.3 External Checkpoints
Implementations SHOULD publish periodic checkpoints to an external, append-only store that is independent of the audit log. Checkpoints provide an independent anchor that an attacker cannot modify even if they compromise the audit system.
A checkpoint MUST contain:
{
"checkpoint_id": "chk-2026-02-08-001",
"timestamp": "2026-02-08T11:00:00.000Z",
"last_sequence": 1247,
"last_hash": "sha256:a1b2c3d4...",
"last_hmac": "sha256:f6e5d4c3...",
"entry_count": 1247,
"platform": "acme-vault",
"signature": "ES256:MEUCIQDf...base64..."
}
| Field | Type | Required | Description |
|---|---|---|---|
checkpoint_id |
string | MUST | Unique identifier for the checkpoint. |
timestamp |
string | MUST | ISO 8601 timestamp of checkpoint creation. |
last_sequence |
integer | MUST | The sequence number of the last entry included in this checkpoint. |
last_hash |
string | MUST | The chain.hash of the last entry. |
last_hmac |
string | SHOULD | The chain.hmac of the last entry. |
entry_count |
integer | MUST | Total number of entries in the chain at checkpoint time. |
platform |
string | MUST | The platform that produced the checkpoint. |
signature |
string | MUST | A digital signature over the checkpoint, produced by the audit system's signing key. |
Checkpoint publication targets MAY include:
- Append-only databases or ledgers
- Signed timestamping services (RFC 3161)
- Transparency logs (Certificate Transparency-style)
- Immutable cloud storage (e.g., AWS S3 Object Lock, Azure Immutable Blob Storage)
- Version control systems (as signed commits)
Checkpoint frequency MUST be at least once per hour during active operation. Implementations SHOULD support configurable checkpoint intervals.
5. Verification Protocol
5.1 Full Chain Verification
Full verification recalculates the entire hash chain from the genesis entry. This is the most thorough verification method but is also the most computationally expensive.
Procedure:
- Load all audit entries, ordered by
sequence. - Verify that entry with sequence 1 has
prev_hashequal to the genesis value (64 zeros). - For each entry from sequence 1 to N:
a. Reconstruct the canonical input string from the entry's fields.
b. Calculate
expected_hash = SHA-256(canonical_input). c. Compareexpected_hashwith the storedchain.hash. If they differ, the entry has been modified. Report the sequence number and stop. d. If the entry has sequence > 1, verify thatchain.prev_hashequals thechain.hashof the previous entry. If they differ, the chain has been broken at this point. Report and stop. e. If HMAC is present, verify the HMAC using the vault's HMAC key. If it does not match, report and stop. - Verify that the sequence numbers are contiguous (no gaps).
- If all checks pass, the chain is verified as intact.
Result schema:
{
"verification": "full",
"status": "valid",
"entries_verified": 1247,
"first_sequence": 1,
"last_sequence": 1247,
"timestamp": "2026-02-08T12:00:00.000Z",
"duration_ms": 340
}
Failure result schema:
{
"verification": "full",
"status": "tampered",
"entries_verified": 892,
"tamper_detected_at": {
"sequence": 893,
"type": "hash_mismatch",
"expected_hash": "sha256:a1b2c3...",
"actual_hash": "sha256:d4e5f6...",
"detail": "Entry content has been modified after writing."
},
"timestamp": "2026-02-08T12:00:00.000Z",
"duration_ms": 210
}
5.2 Incremental Verification
Incremental verification starts from the last known-good entry and verifies only entries added since then. This is suitable for periodic verification and is significantly faster than full verification for large audit logs.
Procedure:
- Load the last verification result to determine the
last_verified_sequenceandlast_verified_hash. - Load all entries with sequence >
last_verified_sequence, ordered by sequence. - Verify that the first new entry's
chain.prev_hashequalslast_verified_hash. - For each new entry, apply the same verification steps as full verification (Section 5.1, step 3).
- If all checks pass, update the last verification result.
Incremental verification SHOULD be performed automatically at a configurable interval (RECOMMENDED: every 5 minutes during active operation).
5.3 Cross-Platform Verification
When actions span multiple platforms (e.g., an agent uses an NL Provider to inject a secret into an AWS Lambda function), the audit entries on each platform are linked by correlation_id. Cross-platform verification ensures that the entries are consistent.
Procedure:
- Given a
correlation_id, retrieve all audit entries with thatcorrelation_idfrom all participating platforms. - Verify that the entries form a logically consistent sequence:
a. Timestamps are in plausible order (allowing for clock skew up to a configurable tolerance, RECOMMENDED: 5 seconds).
b. The agent URI is consistent across entries.
c. The action types form a valid workflow (e.g., an
execon the vault corresponds to an invocation on the target platform). - Verify the hash chain integrity on each individual platform (per Sections 5.1 or 5.2).
- Report any inconsistencies.
Cross-platform verification result:
{
"verification": "cross_platform",
"correlation_id": "req-abc-123",
"status": "consistent",
"platforms": [
{
"platform": "acme-vault",
"entries": 1,
"chain_status": "valid"
},
{
"platform": "aws-lambda-proxy",
"entries": 1,
"chain_status": "valid"
}
],
"timestamp": "2026-02-08T12:05:00.000Z"
}
5.4 Verification Triggers
Implementations MUST support the following verification triggers:
| Trigger | Verification Type | Required |
|---|---|---|
| On-demand by administrator | Full or incremental | MUST |
| Scheduled (periodic) | Incremental | SHOULD |
| After log rotation | Full (on rotated log) | SHOULD |
| After checkpoint publication | Incremental (since last checkpoint) | SHOULD |
| After security incident | Full | SHOULD |
| Via API endpoint | Full or incremental | SHOULD |
6. Audit Queries
6.1 Query Capabilities
Implementations MUST support querying the audit log by the following dimensions:
6.1.1 By Agent
"What did Agent X do?"
{
"query": "by_agent",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"time_range": {
"from": "2026-02-08T00:00:00.000Z",
"to": "2026-02-08T23:59:59.999Z"
},
"results": [
{
"sequence": 42,
"timestamp": "2026-02-08T10:30:00.000Z",
"action": "exec",
"target": "api/API_KEY",
"result": "success"
},
{
"sequence": 57,
"timestamp": "2026-02-08T11:15:00.000Z",
"action": "exec",
"target": "database/DB_PASSWORD",
"result": "blocked",
"detail": "Direct secret access attempted (NL-4-DENY-001)"
}
]
}
6.1.2 By Secret
"Who accessed Secret Y?"
{
"query": "by_secret",
"target": "api/API_KEY",
"time_range": {
"from": "2026-02-01T00:00:00.000Z",
"to": "2026-02-08T23:59:59.999Z"
},
"results": [
{
"sequence": 42,
"timestamp": "2026-02-08T10:30:00.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "exec",
"result": "success"
},
{
"sequence": 103,
"timestamp": "2026-02-08T14:20:00.000Z",
"agent_uri": "nl://example.com/deploy-bot/2.0.0",
"action": "inject_stdin",
"result": "success"
}
]
}
6.1.3 By Time Range
"What happened between T1 and T2?"
{
"query": "by_time",
"time_range": {
"from": "2026-02-08T10:00:00.000Z",
"to": "2026-02-08T10:30:00.000Z"
},
"results": [
{
"sequence": 40,
"timestamp": "2026-02-08T10:05:12.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "list",
"target": "project:myapp/env:production",
"result": "success"
},
{
"sequence": 41,
"timestamp": "2026-02-08T10:15:33.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "exec",
"target": "api/STRIPE_KEY",
"result": "blocked"
},
{
"sequence": 42,
"timestamp": "2026-02-08T10:30:00.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "exec",
"target": "api/API_KEY",
"result": "success"
}
]
}
6.1.4 By Correlation ID
"Trace the full chain for request Z across all platforms."
{
"query": "by_correlation",
"correlation_id": "req-abc-123",
"results": [
{
"platform": "acme-vault",
"sequence": 42,
"timestamp": "2026-02-08T10:30:00.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "exec",
"target": "api/API_KEY",
"result": "success"
},
{
"platform": "aws-lambda-proxy",
"sequence": 891,
"timestamp": "2026-02-08T10:30:00.150Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "api_call",
"target": "https://api.stripe.com/v1/charges",
"result": "success"
}
]
}
6.1.5 By Result
"Show all blocked actions" or "Show all denied access attempts."
{
"query": "by_result",
"result": "blocked",
"time_range": {
"from": "2026-02-08T00:00:00.000Z",
"to": "2026-02-08T23:59:59.999Z"
},
"count": 7,
"results": [
{
"sequence": 41,
"timestamp": "2026-02-08T10:15:33.000Z",
"agent_uri": "nl://anthropic.com/claude-code/1.5.2",
"action": "exec",
"target": "api/STRIPE_KEY",
"result": "blocked",
"rule_id": "NL-4-DENY-001"
}
]
}
6.2 Query Requirements
| Requirement | Level |
|---|---|
| Query by agent URI | MUST |
| Query by secret target | MUST |
| Query by time range | MUST |
| Query by correlation ID | MUST |
| Query by result type | MUST |
| Pagination support for large result sets | MUST |
| Query by platform | SHOULD |
Full-text search on detail field |
MAY |
| Cross-platform aggregated query | MAY (see Section 8.2) |
6.3 Query Access Control
Access to audit queries MUST be controlled:
- Agents MUST NOT be able to query their own audit entries (to prevent them from understanding what is and is not being logged, which could inform evasion strategies).
- Human administrators MUST be able to query all audit entries within their organizational scope.
- Query access MUST be governed by the same RBAC model as other vault operations.
- Audit query actions themselves MUST be logged in the audit trail (meta-auditing).
7. Log Rotation
7.1 Rotation Policy
Audit logs MUST support rotation to manage storage and ensure performance. Rotation MUST NOT break the hash chain (see Section 3.6).
7.2 Rotation Triggers
Rotation SHOULD be triggered by one or more of the following conditions:
| Trigger | Default | Configurable |
|---|---|---|
| File size | 10 MB | MUST |
| Entry count | 100,000 entries | SHOULD |
| Time period | 30 days | SHOULD |
| Manual trigger | N/A | MUST |
7.3 Rotation Procedure
When a log rotation is triggered:
- Write a rotation marker entry to the current log:
{ "entry_id": "...", "sequence": 1248, "timestamp": "2026-02-08T12:00:00.000Z", "nl_version": "1.0", "agent": { "uri": "nl://system/audit-manager", "organization_id": "org_example", "session_id": "system" }, "delegated_by": "system:audit-rotation", "action": "log_rotation", "target": "audit-log-2026-02-08-001.json", "result": "success", "secrets_used": [], "correlation_id": "rotation-2026-02-08-001", "platform": "example-sm", "chain": { "prev_hash": "sha256:...", "hash": "sha256:...", "hmac": "sha256:..." } } - Close the current log file and mark it as read-only.
- Create a new log file.
- The first entry in the new log file MUST have
chain.prev_hashequal to thechain.hashof the rotation marker entry. - Publish a checkpoint for the rotated log file.
7.4 Rotated Log Naming
Rotated log files SHOULD follow the naming convention:
audit-<platform>-<start_sequence>-<end_sequence>-<date>.json
Example: audit-example-sm-0001-1248-2026-02-08.json
7.5 Rotated Log Access
Rotated log files MUST remain accessible for the duration of the retention period (Section 8). They MAY be compressed (gzip RECOMMENDED) and MAY be moved to archival storage after a configurable period (RECOMMENDED: 30 days of hot storage, then cold storage for the remainder of retention).
8. Retention and Federation
8.1 Retention Requirements
Audit records MUST be retained for a minimum period determined by the deployment's conformance level and compliance requirements:
| Conformance Level | Minimum Retention | Description |
|---|---|---|
| NL Protocol Basic (Levels 1-3) | 90 days | Suitable for development teams and small organizations. |
| NL Protocol Standard (Levels 1-5) | 1 year | Suitable for organizations with security policies and regulatory requirements. |
| NL Protocol Advanced (Levels 1-7) | 7 years | Suitable for enterprises with SOC2, ISO 27001, HIPAA, or GDPR compliance requirements. |
Retention periods are minimums. Organizations MAY retain records for longer periods based on their compliance requirements.
Records MUST be retrievable throughout the retention period. Archived records MUST be restorable within a defined SLA (RECOMMENDED: 24 hours for cold storage).
8.2 Federation
Federation enables audit entries from multiple platforms to be correlated and queried as a unified dataset. This is essential for organizations that use multiple secret managers, cloud platforms, or agent orchestration systems.
8.2.1 Standard Federation (via Correlation ID)
At the Standard conformance level, federation is achieved through correlation_id:
- When an agent initiates an action that spans multiple platforms, a single
correlation_idis generated and propagated to all platforms. - Each platform records its own audit entries with the shared
correlation_id. - Querying by
correlation_idon each platform independently reveals the cross-platform trace.
This approach requires no centralized infrastructure. Each platform maintains its own audit log with its own hash chain.
Example flow:
Agent -> NL Provider (correlation_id: req-abc-123)
|
v
Resolve {{nl:API_KEY}} -> Execute curl -> Stripe API
| |
v v
Audit entry on Audit entry on
acme-vault stripe-proxy
(correlation_id: req-abc-123) (correlation_id: req-abc-123)
8.2.2 Advanced Federation (Centralized Audit Aggregator)
At the Advanced conformance level, organizations MAY deploy a centralized audit aggregator that:
- Collects audit entries from all participating platforms via push (webhook) or pull (API polling).
- Indexes entries by
correlation_id,agent.uri,target,timestamp, andplatform. - Provides unified queries across all platforms through a single API.
- Verifies chain integrity independently for each platform's chain.
- Detects cross-platform anomalies (e.g., an action recorded on platform A with no corresponding entry on platform B).
Aggregator entry format:
{
"aggregator_id": "agg-entry-001",
"source_platform": "acme-vault",
"source_entry_id": "01953f2a-7b3c-7def-8a12-4b5c6d7e8f90",
"source_sequence": 42,
"received_at": "2026-02-08T10:30:01.000Z",
"chain_verified": true,
"entry": { "...": "full audit entry from source platform" }
}
The aggregator MUST NOT modify source entries. It MUST store the original entry alongside its own metadata.
8.2.3 Correlation ID Generation
Correlation IDs MUST be:
- Globally unique: UUIDs or ULID format RECOMMENDED.
- Propagated: When an action on platform A triggers an action on platform B, the same
correlation_idMUST be used on both platforms. - Immutable: Once generated, a
correlation_idMUST NOT be changed. - Non-secret: Correlation IDs MUST NOT contain secret values or information that could be used to derive secrets.
Correlation ID format: req-<uuid> (e.g., req-7f3a2b1c-d4e5-6f78-9a0b-c1d2e3f4a5b6).
9. Compliance Mapping
9.1 Purpose
The NL Protocol audit trail is designed to support compliance with major security and privacy frameworks. This section maps the audit capabilities to specific compliance requirements.
9.2 SOC 2
| SOC 2 Trust Service Criteria | NL Protocol Audit Mapping |
|---|---|
| CC6.1: Logical access security | Agent identity (Chapter 01) recorded in every audit entry via agent.uri. Scope-based access control (Chapter 02) recorded via scope_id and result. |
| CC6.2: Restricting access to system resources | result: "denied" and result: "blocked" entries demonstrate access restriction enforcement. |
| CC6.3: Restricting access to infrastructure | Platform integration (Chapter 04, Section 10) demonstrates infrastructure-level access control. |
| CC7.1: Detecting unauthorized activities | result: "blocked" entries with deny rule IDs (Chapter 04) demonstrate detection of unauthorized activities. Threat scoring (Chapter 06) provides risk assessment. |
| CC7.2: Monitoring system activities | Continuous audit logging with hash chain integrity provides tamper-evident monitoring of all system activities. |
| CC7.3: Evaluating detected security events | Cross-platform correlation (correlation_id) and audit queries (Section 6) enable evaluation of security events. |
| CC8.1: Managing changes | action: "create", action: "update", action: "delete", and action: "rotate" entries track all changes to secrets. |
9.3 ISO 27001
| ISO 27001 Control | NL Protocol Audit Mapping |
|---|---|
| A.8.15: Logging | All agent actions are logged with timestamps, agent identity, action type, target, and result. |
| A.8.16: Monitoring activities | Hash chain integrity verification (Section 5) provides continuous monitoring of log integrity. |
| A.8.17: Clock synchronization | timestamp field requires UTC with millisecond precision from NTP-synchronized sources. |
| A.5.23: Information security for cloud services | Platform integration points (Chapter 04, Section 10) cover AWS, GCP, and Azure. Federation (Section 8.2) provides cross-platform visibility. |
| A.8.4: Access to source code | Audit entries for action: "exec" with code-related targets provide source code access tracking. |
| A.8.10: Information deletion | Retention policies (Section 8.1) define minimum retention periods and controlled deletion procedures. |
9.4 GDPR
| GDPR Article | NL Protocol Audit Mapping |
|---|---|
| Article 5(2): Accountability | The hash-chained audit trail provides provable, tamper-evident records of all data processing activities involving secrets. |
| Article 30: Records of processing activities | Audit entries document what processing occurred (action), on what data (target), by whom (agent.uri), and when (timestamp). |
| Article 32: Security of processing | The hash chain, HMAC, and external checkpoints demonstrate integrity measures for the processing activity log. |
| Article 33: Notification of data breach | result: "blocked" and security incident entries provide evidence for breach detection and notification timeline reconstruction. |
| Article 35: Data protection impact assessment | Audit queries by agent, secret, and time range support impact assessment of any data processing operation. |
9.5 Additional Frameworks
The audit data model is extensible via the metadata field to support additional compliance frameworks, including but not limited to:
- HIPAA: Use
metadata.phi_involved: trueto flag entries involving protected health information. - PCI DSS: Use
metadata.cardholder_data: trueto flag entries involving payment card data. - FedRAMP: Use
metadata.impact_level: "high"to categorize entries by FIPS 199 impact level.
10. Audit Entry Examples
10.1 Successful Secret Injection
An agent successfully injects a secret into a command execution:
{
"entry_id": "01953f2a-7b3c-7def-8a12-4b5c6d7e8f90",
"sequence": 42,
"timestamp": "2026-02-08T10:30:00.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_braincol",
"session_id": "session_abc123"
},
"delegated_by": "human:andre@braincol.com",
"action": "exec",
"target": "api/API_KEY",
"result": "success",
"secrets_used": ["api/API_KEY"],
"correlation_id": "req-7f3a2b1c-d4e5-6f78-9a0b-c1d2e3f4a5b6",
"platform": "braincol-vault",
"detail": "Command: curl -H 'Authorization: Bearer {{nl:api/API_KEY}}' https://api.stripe.com/v1/charges",
"duration_ms": 1250,
"chain": {
"prev_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"hash": "sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"hmac": "sha256:f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5"
}
}
Note: The detail field shows the command template with the placeholder {{nl:api/API_KEY}}, NOT the resolved secret value.
10.2 Blocked Action
An agent attempts a direct secret retrieval and is blocked by the pre-execution interceptor:
{
"entry_id": "01953f2a-8c4d-7abc-9012-5d6e7f8a9b0c",
"sequence": 43,
"timestamp": "2026-02-08T10:32:15.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_acme",
"session_id": "session_abc123"
},
"delegated_by": "human:admin@acme.com",
"action": "blocked",
"target": "api/API_KEY",
"result": "blocked",
"secrets_used": [],
"correlation_id": "req-8g4b3c2d-e5f6-7a89-0b1c-d2e3f4a5b6c7",
"platform": "acme-vault",
"detail": "Blocked command: vault get API_KEY (rule: NL-4-DENY-001, category: direct_secret_access)",
"rule_id": "NL-4-DENY-001",
"chain": {
"prev_hash": "sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"hash": "sha256:b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3",
"hmac": "sha256:e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4"
}
}
10.3 Denied Access
An agent attempts to access a secret outside its scope:
{
"entry_id": "01953f2a-9d5e-7bcd-0123-6e7f8a9b0c1d",
"sequence": 44,
"timestamp": "2026-02-08T10:35:00.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://example.com/ci-pipeline/3.1.0",
"organization_id": "org_example",
"session_id": "session_def456"
},
"delegated_by": "agent:nl://example.com/orchestrator/1.0.0",
"action": "exec",
"target": "production/database/DB_ADMIN_PASSWORD",
"result": "denied",
"secrets_used": [],
"correlation_id": "req-9h5c4d3e-f6a1-8b90-1c2d-e3f4a5b6c7d8",
"platform": "example-sm",
"detail": "Agent scope limited to environment:staging. Requested resource is in environment:production.",
"scope_id": "scope-ci-staging-001",
"chain": {
"prev_hash": "sha256:b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3",
"hash": "sha256:c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"hmac": "sha256:d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3"
}
}
10.4 Multiple Secrets in a Single Action
An agent injects multiple secrets into a single command:
{
"entry_id": "01953f2a-ae6f-7cde-1234-7f8a9b0c1d2e",
"sequence": 45,
"timestamp": "2026-02-08T10:40:00.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_example",
"session_id": "session_abc123"
},
"delegated_by": "human:admin@example.com",
"action": "exec",
"target": "database/DB_USER,database/DB_PASSWORD",
"result": "success",
"secrets_used": ["database/DB_USER", "database/DB_PASSWORD"],
"correlation_id": "req-0i6d5e4f-a1b2-9c01-2d3e-f4a5b6c7d8e9",
"platform": "example-sm",
"detail": "Command: psql 'postgresql://{{nl:database/DB_USER}}:{{nl:database/DB_PASSWORD}}@localhost/mydb'",
"duration_ms": 3400,
"chain": {
"prev_hash": "sha256:c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"hash": "sha256:d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5",
"hmac": "sha256:c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2"
}
}
10.5 Evasion Attempt
An agent attempts to evade deny rules using base64 encoding:
{
"entry_id": "01953f2a-bf70-7def-2345-8a9b0c1d2e3f",
"sequence": 46,
"timestamp": "2026-02-08T10:45:00.000Z",
"nl_version": "1.0",
"agent": {
"uri": "nl://anthropic.com/claude-code/1.5.2",
"organization_id": "org_acme",
"session_id": "session_abc123"
},
"delegated_by": "human:admin@acme.com",
"action": "blocked",
"target": "unknown",
"result": "blocked",
"secrets_used": [],
"correlation_id": "req-1j7e6f5a-b2c3-0d12-3e4f-a5b6c7d8e9f0",
"platform": "acme-vault",
"detail": "Evasion attempt detected: base64-encoded command piped to shell (rule: NL-4-DENY-030, category: encoding_evasion)",
"rule_id": "NL-4-DENY-030",
"metadata": {
"evasion_type": "base64_decode_pipe_shell",
"threat_score_delta": "+10"
},
"chain": {
"prev_hash": "sha256:d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5",
"hash": "sha256:e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6",
"hmac": "sha256:b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1"
}
}
11. Security Considerations
The audit system is a high-value target. Compromise of the audit system undermines every other security layer because actions can no longer be verified. Implementations MUST treat the audit system as critical infrastructure with its own access controls, monitoring, and redundancy.
Hash chaining detects tampering but does not prevent it. An attacker with write access can modify the log and rewrite the chain. HMAC protection (Section 3.5) and external checkpoints (Section 4.3) provide additional layers that make undetected tampering significantly harder.
Clock accuracy is critical. Audit records with inaccurate timestamps undermine temporal analysis and cross-platform correlation. Implementations MUST use NTP-synchronized time sources and SHOULD monitor for clock skew. Clock skew greater than 1 second SHOULD trigger an alert.
Secret values in audit entries. The prohibition on secret values in audit entries (Section 2.5) is the most critical constraint in this chapter. Implementations MUST scan entries before writing them and MUST sanitize any detected secret content. A leaked secret in the audit log is worse than no audit log at all, because it creates a persistent, searchable record of the secret.
Audit log as a denial-of-service vector. A compromised agent could generate a high volume of actions to fill the audit log, triggering rotation and potentially consuming storage. Implementations SHOULD apply rate limiting to audit entry generation and SHOULD alert on unusual audit volume.
Query side channels. Audit query patterns themselves can reveal sensitive information (e.g., which secrets are accessed most frequently). Query access MUST be controlled (Section 6.3) and query activity MUST be logged.
Retention and data minimization. Long retention periods increase the value of the audit log as a target. Organizations MUST balance compliance retention requirements against the risk of storing a detailed record of all secret access activity. Encryption at rest for audit log storage is RECOMMENDED.
12. Conformance Requirements
An implementation conforms to NL Protocol Level 5 if it satisfies all MUST-level requirements. Full conformance includes satisfying all MUST and SHOULD requirements.
| Requirement ID | Description | Level |
|---|---|---|
| NL-5.1 | Every action produces an audit entry with all required fields (Section 2) | MUST |
| NL-5.2 | Audit entries are linked in a SHA-256 hash chain (Section 3) | MUST |
| NL-5.3 | Genesis entry uses the defined prev_hash value (Section 3.4) | MUST |
| NL-5.4 | Secret values NEVER appear in audit entries (Section 2.5) | MUST |
| NL-5.5 | Hash chain integrity is verifiable on demand (Section 5) | MUST |
| NL-5.6 | Tamper detection covers modification, deletion, reordering, and truncation (Section 4) | MUST |
| NL-5.7 | Sequence numbers are monotonically increasing with no gaps (Section 2.2) | MUST |
| NL-5.8 | Audit entries use UTC timestamps with millisecond precision from NTP-synchronized sources (Section 2.2) | MUST |
| NL-5.9 | Agents cannot modify or delete their own audit entries (Section 6.3) | MUST |
| NL-5.10 | Audit queries by agent, secret, time, correlation ID, and result are supported (Section 6) | MUST |
| NL-5.11 | Log rotation does not break the hash chain (Section 7) | MUST |
| NL-5.12 | Minimum retention periods are enforced per conformance level (Section 8.1) | MUST |
| NL-5.13 | HMAC-SHA256 is supported for additional integrity (Section 3.5) | SHOULD |
| NL-5.14 | External checkpoints are published periodically (Section 4.3) | SHOULD |
| NL-5.15 | Incremental verification runs automatically on a schedule (Section 5.2) | SHOULD |
| NL-5.16 | Cross-platform correlation via correlation_id is supported (Section 8.2.1) | SHOULD |
| NL-5.17 | Audit entries are scanned for secret leakage before writing (Section 2.5) | SHOULD |
| NL-5.18 | Centralized audit aggregator for cross-platform queries (Section 8.2.2) | MAY |
| NL-5.19 | Compliance mapping metadata extensions are supported (Section 9.5) | MAY |
| NL-5.20 | Full-text search on audit entry detail field (Section 6.2) | MAY |
13. References
- RFC 2119 -- Key words for use in RFCs
- RFC 6234 -- US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)
- RFC 8785 -- JSON Canonicalization Scheme (JCS)
- RFC 3161 -- Internet X.509 PKI Time-Stamp Protocol (TSP)
- NIST SP 800-92 -- Guide to Computer Security Log Management
- SOC 2 Trust Service Criteria
- ISO/IEC 27001:2022 -- Information Security Management Systems
- GDPR -- General Data Protection Regulation