Session operations logged immutably
Why it matters
Financial regulators, PCI-DSS Req 10.2, and NIST 800-63B (AU-2/AU-9) require that session lifecycle events — logins, logouts, timeouts, and extensions — be recorded in a tamper-resistant audit trail. Without immutable session logs, incident response is blind: there is no way to determine whether a specific session was active during a disputed transaction, whether a concurrent session was established from an unusual IP, or whether a session was extended unexpectedly. ISO 27001:2022 A.8.15 requires log integrity. Mutable logs stored in a writable database table are trivially altered to conceal unauthorized access.
Severity rationale
Info severity because the absence of session logging does not directly enable attack, but it removes the forensic record needed to detect, investigate, and prove unauthorized session activity after the fact.
Remediation
Wire session event logging via middleware in src/middleware/sessionLogger.ts using an append-only transport:
import pino from 'pino';
const auditLog = pino({
transport: {
target: 'pino-http-send',
options: { url: 'https://log-service.example.com/audit' }
}
});
export function logSessionEvent(userId: string, event: string, details: object) {
auditLog.info({
timestamp: new Date().toISOString(),
userId,
event, // 'login' | 'logout' | 'timeout' | 'extend' | 'concurrent_warning'
...details
});
}
Capture all four required event types: login, logout, timeout, and extension. Use an append-only destination — a WORM-compliant log service, an S3 bucket with object lock, or a Postgres table with no UPDATE/DELETE grants on the audit role.
Detection
- ID:
session-operations-logged - Severity:
info - What to look for: Count all session event types being logged (login, logout, timeout, extension, concurrent warning). Enumerate the log storage mechanism and classify as append-only or mutable. Quote the actual logger library and configuration found. Count every session-related event type in the codebase.
- Pass criteria: At least 4 session event types are logged (minimum: login, logout, timeout, extension). Logs are stored in an append-only format. Count all event types — report the ratio even on pass (e.g., "5 of 5 event types logged: login, logout, timeout, extension, concurrent_warning — stored via pino to append-only file").
- Fail criteria: Fewer than 4 session event types logged, or logs stored in a mutable format (regular database with UPDATE/DELETE, memory).
- Skip (N/A) when: The application is not subject to audit or compliance requirements — cite the actual compliance context found.
- Detail on fail:
"0 session event types logged — no session logging found"or"2 of 4 required event types logged (login, logout only — timeout and extension missing)" - Remediation: Add session event logging via middleware (in
src/middleware/sessionLogger.ts):// middleware/sessionLogger.ts import pino from 'pino'; const auditLog = pino({ transport: { target: 'pino-http-send', options: { url: 'https://log-service.example.com/audit' } // Or append-only file } }); export function logSessionEvent(userId: string, event: string, details: any) { auditLog.info({ timestamp: new Date().toISOString(), userId, event, // 'login', 'logout', 'timeout', 'extend' ...details }); }
External references
- nist:rev5 · AU-2 — Event Logging
- nist:rev5 · AU-9 — Protection of Audit Information
- pci-dss:4.0 · Req 10.2 — Audit log events for all system components
- iso-27001:2022 · A.8.15 — Logging
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-session-security·automated