This implementation addresses SOC2 traceability requirements for admin actions by ensuring audit logs capture both IP addresses and user-agent strings for all admin actions.
- Added
userAgent?: stringfield toAuditLogEntryinterface - Modified
createAdminAuditMiddleware()to capturereq.get('user-agent') - Implemented IP hashing with daily salt when
AUDIT_HASH_IP=trueenvironment variable is set
- Added IP hashing function for consistency with the in-memory audit log
- Updated
recordAdminAuditLog()to use hashed IP addresses whenAUDIT_HASH_IP=true
- Tests IP address capture with and without hashing
- Tests user-agent capture
- Verifies functionality persists through the
/admin/audit-logsendpoint - Tests edge cases (missing headers, forwarded IPs, etc.)
When AUDIT_HASH_IP=true is set in the environment:
- Privacy Protection: IP addresses are hashed using SHA-256 with a daily salt
- Traceability: Same IP produces same hash on the same day, enabling correlation
- Format: Hashed IPs follow format
sha256:[first_16_chars_of_hash]
function hashIpIfNeeded(ip) {
if (AUDIT_HASH_IP !== 'true') return ip;
const today = new Date().toISOString().split('T')[0];
const salt = `audit-ip-${today}`;
const hash = crypto.createHash('sha256').update(`${ip}:${salt}`).digest('hex');
return `sha256:${hash.slice(0, 16)}`;
}The AdminAuditLog Prisma model already includes the required fields:
ipAddress(String)userAgent(String)
No database migration was needed as the schema already supported these fields.
- ✅ Added to in-memory audit log (
auditLog.ts) - ✅ Added to database audit log (
adminAudit.ts) - ✅ Both capture IP from
req.ipand user-agent fromreq.get('user-agent')
- ✅ Implemented in both audit log systems
- ✅ Uses daily salt that changes every 24 hours
- ✅ Same IP produces same hash on same day for correlation
- ✅ Created comprehensive test suite
- ✅ Tests capture with and without IP hashing
- ✅ Tests edge cases (missing headers, forwarded IPs)
- ✅ Verifies data appears in
/admin/audit-logsresponse
Run the audit log tests:
cd backend
npm test auditLog.test.tsOr run all tests:
cd backend
npm test| Variable | Default | Description |
|---|---|---|
AUDIT_HASH_IP |
false |
When true, IP addresses are hashed with daily salt for privacy |
AUDIT_LOG_RETENTION |
500 |
Maximum number of in-memory audit log entries to retain |
ADMIN_AUDIT_LOG_STORAGE |
hybrid |
Storage mode: memory, prisma, or hybrid |
- Traceability: All admin actions now include network identity (IP) and client identification (user-agent)
- Privacy: Optional IP hashing protects user privacy while maintaining audit trail
- Tamper Resistance: Hashed IPs cannot be reversed to original IPs without the daily salt
- Correlation: Same IP produces same hash on same day, enabling incident investigation
- Retention: Audit logs are retained per
AUDIT_LOG_RETENTIONsetting
backend/src/auditLog.ts- In-memory audit log with IP/user-agentbackend/src/adminAudit.ts- Database audit log with IP hashingbackend/src/__tests__/auditLog.test.ts- Comprehensive test suiteAUDIT_LOG_SOC2_IMPLEMENTATION.md- This documentation file