From harness-claude
Implements structured security logging and monitoring with Pino to detect attacks, log auth events, redact sensitive data, and support incident response and compliance audits.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Implement security logging and monitoring to detect attacks, support incident response, and maintain audit trails
Implements structured security audit logging for compliance, forensics, and SIEM integration in Node.js, Python, and Java. Use for audit trails and monitoring.
Designs structured, tamper-evident audit logs for security events like authentication, authorization, and data access. Useful for new apps, adding logs to existing systems, SOC2/HIPAA/PCI-DSS compliance, or incident investigation.
Implements tamper-evident audit logging, SIEM integration, vulnerability scanning, and compliance reporting for Python, Go, TypeScript apps.
Share bugs, ideas, or general feedback.
Implement security logging and monitoring to detect attacks, support incident response, and maintain audit trails
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL ?? 'info',
formatters: {
level: (label) => ({ level: label }),
},
redact: ['req.headers.authorization', 'password', 'ssn', 'creditCard'],
timestamp: pino.stdTimeFunctions.isoTime,
});
// Authentication events
logger.info({ event: 'auth.login.success', userId, ip, userAgent }, 'User logged in');
logger.warn({ event: 'auth.login.failure', email, ip, reason: 'invalid_password' }, 'Login failed');
logger.warn(
{ event: 'auth.login.locked', email, ip, attempts },
'Account locked after failed attempts'
);
logger.info({ event: 'auth.logout', userId }, 'User logged out');
logger.info({ event: 'auth.password.changed', userId }, 'Password changed');
// Authorization events
logger.warn({ event: 'authz.denied', userId, resource, action }, 'Access denied');
logger.warn(
{ event: 'authz.escalation', userId, fromRole, toRole },
'Privilege escalation attempt'
);
// Data access events
logger.info({ event: 'data.export', userId, recordCount }, 'Data exported');
logger.info({ event: 'data.delete', userId, resourceType, resourceId }, 'Record deleted');
// Input validation events
logger.warn({ event: 'input.validation', ip, field, reason }, 'Suspicious input rejected');
// System events
logger.error({ event: 'system.error', error: err.message, stack: err.stack }, 'Unhandled error');
logger.info({ event: 'system.startup', version, environment }, 'Application started');
// Pino redaction
const logger = pino({
redact: {
paths: [
'password',
'token',
'req.headers.authorization',
'req.headers.cookie',
'creditCard',
'ssn',
'*.password',
'*.token',
],
censor: '[REDACTED]',
},
});
// Manual redaction for dynamic fields
function sanitizeForLogging(obj: Record<string, unknown>): Record<string, unknown> {
const sensitive = new Set(['password', 'token', 'secret', 'ssn', 'creditCard']);
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, sensitive.has(k) ? '[REDACTED]' : v])
);
}
import { randomUUID } from 'node:crypto';
app.use((req, res, next) => {
req.requestId = (req.headers['x-request-id'] as string) ?? randomUUID();
req.log = logger.child({
requestId: req.requestId,
userId: req.user?.id,
ip: req.ip,
method: req.method,
path: req.path,
});
res.setHeader('X-Request-Id', req.requestId);
next();
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
const logFn =
res.statusCode >= 500 ? req.log.error : res.statusCode >= 400 ? req.log.warn : req.log.info;
logFn(
{
event: 'http.request',
status: res.statusCode,
duration,
contentLength: res.getHeader('content-length'),
},
`${req.method} ${req.path} ${res.statusCode} ${duration}ms`
);
});
next();
});
Set up alerting for suspicious patterns. Define alert rules for:
Ship logs to a centralized aggregation service. Do not rely on local log files — use Datadog, Elastic/ELK, Splunk, or CloudWatch for centralized storage, search, and alerting.
Implement audit logs for compliance-sensitive operations. Audit logs are immutable, timestamped records of who did what and when.
interface AuditEntry {
timestamp: string;
actor: { userId: string; ip: string; userAgent: string };
action: string;
resource: { type: string; id: string };
changes?: { field: string; from: unknown; to: unknown }[];
result: 'success' | 'failure';
}
async function auditLog(entry: AuditEntry): Promise<void> {
// Write to append-only store (database, S3, dedicated audit service)
await db.auditLogs.create({ data: entry });
logger.info({ event: 'audit', ...entry }, `Audit: ${entry.action}`);
}
Set log retention policies. Balance storage costs with compliance requirements. Common retention periods: 90 days for general logs, 1 year for security events, 7 years for financial audit logs.
Test your logging and alerting. Regularly verify that security events generate the expected logs and that alerts fire correctly. Include logging verification in security testing.
OWASP Top 10 A09 — Security Logging and Monitoring Failures: Insufficient logging delays detection of breaches. The average time to detect a breach is 200+ days. Proper logging reduces this to hours or days.
Log levels for security events:
ERROR: System failures, unhandled exceptions, security control failuresWARN: Failed authentication, authorization denials, input validation failures, rate limiting triggeredINFO: Successful authentication, significant user actions, configuration changesDEBUG: Detailed request/response data (never in production for security events)Log injection prevention: User-controlled data in log messages can inject fake log entries. Use structured logging (JSON fields) instead of string interpolation. Never do logger.info('User logged in: ' + username) — use logger.info({ username }, 'User logged in').
Compliance requirements:
Common mistakes:
console.log instead of a structured loggerhttps://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html