Skip to main content

Audit Logging

Claw GRC maintains a comprehensive, tamper-evident audit log that records every state change in the system. The audit log uses cryptographic chain hashing to provide mathematical proof that no entries have been modified or deleted.

What Gets Logged​

Every action by every actor (human or agent) is recorded:

Action CategoryExamples
EvidenceUpload, validate, reject, soft-delete
PoliciesCreate, update, approve, archive
RisksCreate, update score, change treatment
FindingsCreate, update status, resolve
TicketsCreate, assign, update status, close
AgentsRegister, update, deregister, key rotation
MCPSession create, tool invocations, session close
MembersInvite, role change, deactivate
TrustScore recalculation, threshold violations

Audit Log Schema​

Each audit log entry contains:

FieldTypeDescription
idUUIDUnique entry identifier
org_idUUIDOrganization (tenant) scope
actor_typestringuser or agent
actor_idUUIDWho performed the action
actionstringWhat happened (e.g., evidence.created, agent.key_rotated)
resource_typestringType of affected resource (evidence, agent, policy, etc.)
resource_idUUIDID of the affected resource
metadataJSONBAction-specific details (changes, previous values, etc.)
chain_hashstringSHA-256 chain hash linking to previous entry
created_attimestampWhen the action occurred

Chain Hashing Algorithm​

Each audit log entry includes a chain_hash that links it to the previous entry:

chain_hash_N = SHA-256(chain_hash_{N-1} + ":" + JSON(entry_N))

The first entry in the chain uses "genesis" as the previous hash.

Verification​

To verify the audit log integrity:

  1. Fetch all entries in chronological order
  2. Starting from the first entry, compute the expected hash using "genesis" as the previous hash
  3. Compare the computed hash with the stored chain_hash
  4. Use the stored chain_hash as the previous hash for the next entry
  5. If any computed hash does not match the stored hash, the chain is broken at that point

What Tampering Looks Like​

If someone modifies entry #500 in a chain of 1,000 entries:

  • The hash of entry #500 would change
  • Entry #501's hash depends on entry #500's hash, so it would also be invalid
  • This cascade continues through entries #502, #503, ..., #1000
  • Running verification would immediately detect the break at entry #500

Immutability Enforcement​

The audit_log table is protected by database triggers that prevent modification:

-- Block UPDATE operations
CREATE OR REPLACE FUNCTION prevent_audit_log_update()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'audit_log rows are immutable and cannot be updated';
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER no_audit_log_update
BEFORE UPDATE ON audit_log
FOR EACH ROW EXECUTE FUNCTION prevent_audit_log_update();

-- Block DELETE operations
CREATE OR REPLACE FUNCTION prevent_audit_log_delete()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'audit_log rows are immutable and cannot be deleted';
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER no_audit_log_delete
BEFORE DELETE ON audit_log
FOR EACH ROW EXECUTE FUNCTION prevent_audit_log_delete();

-- Block TRUNCATE
REVOKE TRUNCATE ON audit_log FROM PUBLIC;

Combined with FORCE ROW LEVEL SECURITY, this means:

  • No one can modify an existing entry (trigger blocks UPDATE)
  • No one can delete an entry (trigger blocks DELETE)
  • No one can truncate the table (TRUNCATE privilege revoked)
  • Even the table owner is subject to these restrictions

Exporting Audit Logs​

CSV Export​

Generate a CSV export for your auditors:

curl -X POST https://api.clawgrc.com/api/v1/reports \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "audit_trail",
"start_date": "2025-01-01T00:00:00Z",
"end_date": "2025-01-31T23:59:59Z",
"format": "csv"
}'

The CSV includes all columns including chain_hash, allowing independent verification.

Direct Query (Admin)​

For database administrators:

-- Set tenant context (required due to FORCE RLS)
SELECT set_config('app.current_org', 'YOUR_ORG_UUID', true);

-- Query audit log
SELECT id, actor_type, actor_id, action, resource_type,
resource_id, metadata, chain_hash, created_at
FROM audit_log
WHERE created_at >= '2025-01-01'
AND created_at < '2025-02-01'
ORDER BY created_at ASC;

Dual Audit System​

Claw GRC maintains two chain-hashed logs:

LogTablePurposeWhat It Tracks
Audit Logaudit_logCompliance auditingAll state changes (CRUD operations)
Agent Interactionsagent_interactionsAgent governanceAll MCP tool invocations and agent-to-agent calls

Both use the same chain hashing algorithm and the same immutability protections.

Compliance Framework Coverage​

The audit logging system satisfies requirements across multiple frameworks:

FrameworkControlRequirement
SOC 2CC7.2Monitor system components for anomalies
SOC 2CC7.3Evaluate security events
ISO 27001A.12.4.1Event logging
ISO 27001A.12.4.3Administrator and operator logs
NIST 800-53AU-2Auditable events
NIST 800-53AU-3Content of audit records
NIST 800-53AU-9Protection of audit information
NIST 800-53AU-10Non-repudiation
HIPAA164.312(b)Audit controls
PCI DSS10.1Audit trails for system components
PCI DSS10.5Secure audit trails

Best Practices​

  • Export monthly -- Download audit trail CSVs monthly and store them in an independent, immutable storage system (e.g., AWS S3 with Object Lock).
  • Verify quarterly -- Run chain hash verification quarterly to confirm no tampering has occurred.
  • Retain for compliance -- SOC 2 requires 1 year minimum; PCI DSS requires 1 year online + 1 year archived; HIPAA requires 6 years.
  • Monitor gaps -- Alert on time gaps in the audit trail that might indicate issues.
  • Correlate across logs -- Use both the audit log and agent interactions table to build a complete picture of activity.