UNPKG

@sun-asterisk/sunlint

Version:

☀️ SunLint - Multi-language static analysis tool for code quality and security | Sun* Engineering Standards

148 lines 4.32 kB
{ "rule": { "id": "S056", "name": "Protect against Log Injection attacks", "description": "Protect against Log Injection attacks. Log injection occurs when user-controlled data is written to log files without proper sanitization, potentially allowing attackers to manipulate log entries, inject malicious content, or exploit log processing systems.", "category": "security", "severity": "error", "languages": ["typescript", "javascript"], "frameworks": ["express", "nestjs", "node"], "version": "1.0.0", "status": "stable", "tags": ["security", "logging", "injection", "owasp", "crlf"], "references": [ "https://owasp.org/www-community/attacks/Log_Injection", "https://cwe.mitre.org/data/definitions/117.html", "https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html", "https://portswigger.net/kb/issues/00200200_log-injection" ] }, "configuration": { "enableLogInjectionDetection": true, "checkUserInputSources": [ "req", "request", "params", "query", "body", "headers", "cookies", "session" ], "vulnerableLogMethods": [ "log", "info", "warn", "error", "debug", "trace", "write", "writeSync" ], "vulnerableLogLibraries": [ "winston", "bunyan", "pino", "log4js", "console", "morgan", "debug" ], "dangerousCharacters": [ "\\r", "\\n", "\\r\\n", "\\u000a", "\\u000d", "%0a", "%0d", "\\x0a", "\\x0d" ], "secureLogPatterns": [ "sanitize", "escape", "clean", "filter", "validate", "replace", "strip" ] }, "examples": { "violations": [ { "description": "Direct user input in log message", "code": "logger.info('User login: ' + req.body.username);" }, { "description": "Template literal with user input", "code": "console.log(`User ${req.query.user} attempted login`);" }, { "description": "User input containing CRLF in log", "code": "winston.error('Authentication failed for: ' + req.headers['user-agent']);" }, { "description": "Session data in log message", "code": "logger.debug('Session: ' + JSON.stringify(req.session));" } ], "fixes": [ { "description": "Sanitize user input before logging", "code": "const sanitizedUser = sanitize(req.body.username);\nlogger.info('User login: ' + sanitizedUser);" }, { "description": "Use structured logging with safe values", "code": "logger.info('User login', { username: sanitize(req.body.username) });" }, { "description": "Filter dangerous characters", "code": "const cleanInput = req.query.user.replace(/[\\r\\n]/g, '_');\nconsole.log(`User ${cleanInput} attempted login`);" }, { "description": "Validate input before logging", "code": "if (validateInput(req.headers['user-agent'])) {\n winston.error('Authentication failed for: ' + req.headers['user-agent']);\n}" } ] }, "testing": { "testCases": [ { "name": "log_injection_direct_input", "type": "violation", "description": "Direct user input in log message" }, { "name": "log_injection_template_literal", "type": "violation", "description": "Template literal with user input" }, { "name": "log_injection_crlf", "type": "violation", "description": "User input containing CRLF characters" }, { "name": "log_injection_json_stringify", "type": "violation", "description": "JSON.stringify with user input" }, { "name": "secure_log_sanitized", "type": "clean", "description": "Sanitized user input in log" }, { "name": "secure_log_structured", "type": "clean", "description": "Structured logging with safe values" } ] }, "performance": { "complexity": "O(n)", "description": "Linear complexity based on number of function calls and expressions in the source code" } }