InputSanitizer, Sensitive and the Privileged trait
The complete source of standardTypes_security.ek9, compiled by the EK9 compiler. Shown on standardTypes.html.
#!ek9 defines module site.standardTypes.security defines function processData() -> cleaned as String Stdout().println(`Processing ${cleaned}`) defines class DatabaseDriver with trait of Privileged connect() -> host as String port as Integer user as String password as Sensitive //reveal() is legal here - DatabaseDriver has the Privileged trait rawPassword <- password.reveal() internalConnect(host: host, port: port, user: user, secret: rawPassword) private internalConnect() -> host as String port as Integer user as String secret as String Stdout().println(`Connecting ${user}@${host}:${port} with a ${length secret} character secret`) default operator ? defines program SanitizerDemo() userInput <- "Some user supplied text" sanitizer <- InputSanitizer() //Sanitize input - returns unset if threat detected result <- sanitizer.sanitize(userInput) if result? processData(result) //With context for richer logging context <- SanitizationContext( timestamp: SystemClock().dateTime(), service: "UserService", operation: "getUser", fieldName: "userId", fieldSource: "PATH", sourceIp: "127.0.0.1", traceId: "trace-0001" ) richResult <- sanitizer.sanitize(userInput, context) if richResult? processData(richResult) SensitiveDemo() stdout <- Stdout() database <- DatabaseDriver() envVars <- EnvVars() //Load secret from environment variable if dbPassword <- envVars.sensitiveGet("DB_PASSWORD") //dbPassword is set, pass to database driver database.connect(host: "localhost", port: 5432, user: "app", password: dbPassword) //This prints "***REDACTED***" - never the real password stdout.println($dbPassword) else stdout.println("DB_PASSWORD is not set, so there is nothing to connect with")
Download standardTypes_security.ek9
Output
SanitizerDemo
Processing Some user supplied text Processing Some user supplied text
SensitiveDemo
DB_PASSWORD is not set, so there is nothing to connect with