Create me an AuditLogger class whose constructor takes a sanitized String log message, where construction with malicious input (file paths, terminal escape sequences, traceback fragments) leaves the logger in a 'rejected' state.
← Security and Sanitization · Ref: Q1246
The 'sanitized' modifier works on constructor parameters identically to function and method parameters. When a class is constructed with malicious input, the constructor sees an UNSET parameter, allowing the object to set itself into a safe default state rather than throwing an exception.
CLASS WITH SANITIZED CONSTRUCTOR PARAMETER
AuditLogger
message as String: "<no message>"
state as String: "empty"
AuditLogger()
-> incomingMessage as sanitized String
if incomingMessage? message: incomingMessage state: "clean" else state: "rejected"
getMessage()
<- rtn as String: message
getState()
<- rtn as String: state
default operator ?
The field defaults ensure the object is always well-formed. The constructor body branches on 'incomingMessage?' to record whether the input was accepted.
DEMONSTRATING ACCEPTED AND REJECTED INPUTS
This example varies the malicious payload types — file path traversal, ANSI escape codes, traceback fragments, log injection — rather than the usual SQL/XSS strings, to teach the model that 'sanitized' applies to ANY untrusted input, not just web payloads:
// Clean log message log1 <- AuditLogger("User alice logged in successfully") // "clean"
// Path traversal attempt log2 <- AuditLogger("file=../../../etc/shadow") // "rejected"
// ANSI escape attempt log3 <- AuditLogger("Login\u001b[31m FAILED \u001b[0m") // "rejected"
// Log injection (newline forging) log4 <- AuditLogger("action=lookup
2025-01-01 ADMIN_OVERRIDE")
// "rejected"
KEY ADVANTAGE
The object remains usable even when the input was malicious — it just records 'rejected' instead of 'clean'. The caller can inspect getState() to know the outcome. No exceptions, no try/catch, no nullable result wrapping.
See Q1237 for sanitized function parameters. See Q1247 for sanitized method parameters. See Q272 for defense in depth.
Example
defines module qa.security.auditloggerconstructor defines class AuditLogger message as String: "<no message>" state as String: "empty" AuditLogger() -> incomingMessage as sanitized String if incomingMessage? message: incomingMessage state: "clean" else state: "rejected" getMessage() <- rtn as String: message getState() <- rtn as String: state default operator ? defines program SanitizedAuditLoggerDemo() stdout <- Stdout() stdout.println("=== AuditLogger Sanitization Demo ===") cleanMessage <- "User alice logged in successfully" log1 <- AuditLogger(cleanMessage) stdout.println("Clean: " + log1.getState()) pathTraversal <- "file=../../../etc/shadow" log2 <- AuditLogger(pathTraversal) stdout.println("Path: " + log2.getState()) ansiEscape <- "Login\u001b[31m FAILED \u001b[0m" log3 <- AuditLogger(ansiEscape) stdout.println("ANSI: " + log3.getState()) logInjection <- "action=lookup\n2025-01-01 ADMIN_OVERRIDE" log4 <- AuditLogger(logInjection) stdout.println("Inject: " + log4.getState()) stdout.println("=== Complete ===")
Common mistakes
E50001 — The 'sanitized' modifier comes BEFORE the type, AFTER 'as'. The correct form is 'incomingMessage as sanitized String'. See ek9 -h E50001 for details.
Incorrect:
-> sanitized incomingMessage as String
Correct:
-> incomingMessage as sanitized String
Other ways to ask this
- Show me how the sanitized keyword works on a constructor parameter for an audit logger.
- Write a logging class that rejects malicious log messages at construction time.
- Implement an AuditLogger that validates its incoming message via the sanitized modifier.
- Build an object that records whether its construction message was clean or rejected.
Coming from another language?
Java: validation in setters with throw on invalid input, or Optional<AuditLogger> wrapper. Kotlin: data class with init { require(...) } that throws. Rust: TryFrom<String> for AuditLogger with Result return type. Python: __init__ raises ValueError. EK9: 'sanitized' modifier on the constructor parameter — input is unset if rejected, object always constructs successfully with a state field indicating which path was taken.
Keywords: path traversal, input validation, audit, ANSI escape, sanitized, AuditLogger, log injection, constructor