Write me a QueryBuilder class with an addClause method that takes a sanitized String fragment, returning 'accepted' for clean fragments and 'rejected' for malicious ones (LDAP injection, NoSQL operator injection).
← Security and Sanitization · Ref: Q1247
The 'sanitized' modifier works on method parameters identically to constructors and functions. When a method receives malicious input, the parameter is UNSET, so the method can branch on 'fragment?' to handle the rejected case without exceptions.
CLASS WITH SANITIZED METHOD PARAMETER
QueryBuilder
accepted as Integer: 0
rejected as Integer: 0
default QueryBuilder()
addClause()
-> fragment as sanitized String
<- result as String: "unset"
if fragment? accepted: accepted + 1 result: "accepted" else rejected: rejected + 1 result: "rejected"
getStats()
<- rtn as String: `accepted=${accepted} rejected=${rejected}`
The class keeps running counters of accepted and rejected fragments, demonstrating that the object remains usable across many calls — clean fragments increment the accepted counter, malicious ones increment rejected, neither path throws.
DEMONSTRATING DIVERSE INJECTION TYPES
This example deliberately uses injection categories OTHER than SQL/XSS, to show that 'sanitized' protects against any untrusted text. It also shows that a URL-shaped fragment is not, by itself, a threat: an ordinary redirect parameter is accepted:
qb <- QueryBuilder()
// Clean equality clause qb.addClause("name = 'alice'") // accepted
// A URL-shaped fragment is NOT flagged qb.addClause("redirect=http://evil/?p=1") // accepted
// LDAP injection qb.addClause("(|(uid=*)(uid=*))") // rejected
// NoSQL operator injection qb.addClause("$where: function() { return true }") // rejected
// Clean range clause qb.addClause("age >= 18") // accepted
The program ends with accepted=3 rejected=2, and each rejection writes a JSON warning line to stderr naming the threat (LDAP_INJECTION, NOSQL_INJECTION). 'sanitized' screens for injection patterns; it does not judge whether a URL is trustworthy, so validate redirect targets yourself.
WHEN TO USE METHOD-LEVEL SANITIZATION
Use method-level sanitization when an object is constructed from trusted sources but later receives untrusted input through method calls — query builders, log appenders, file writers that accept paths, HTTP request builders that accept headers.
See Q1246 for sanitized constructor parameters. See Q1237 for sanitized function parameters. See Q272 for defense in depth.
Example
defines module qa.security.querybuildermethod defines class QueryBuilder accepted as Integer: 0 rejected as Integer: 0 default QueryBuilder() addClause() -> fragment as sanitized String <- result as String: "unset" if fragment? accepted: accepted + 1 result: "accepted" else rejected: rejected + 1 result: "rejected" getStats() <- rtn as String: `accepted=${accepted} rejected=${rejected}` default operator ? defines program SanitizedQueryBuilderDemo() stdout <- Stdout() qb <- QueryBuilder() stdout.println("=== QueryBuilder Sanitization Demo ===") cleanEquality <- "name = 'alice'" stdout.println("Equality: " + qb.addClause(cleanEquality)) urlInjection <- "redirect=http://evil/?p=1" stdout.println("URL: " + qb.addClause(urlInjection)) ldapInjection <- "(|(uid=*)(uid=*))" stdout.println("LDAP: " + qb.addClause(ldapInjection)) nosqlInjection <- "$where: function() { return true }" stdout.println("NoSQL: " + qb.addClause(nosqlInjection)) cleanRange <- "age >= 18" stdout.println("Range: " + qb.addClause(cleanRange)) stdout.println(qb.getStats()) stdout.println("=== Complete ===")
Common mistakes
E07910 — The sanitized modifier can only be applied to String parameters. Injection attacks travel as text, so a non-String type has nothing to clean. See ek9 -h E07910 for details.
Incorrect:
-> fragment as sanitized Integer
Correct:
-> fragment as sanitized String
Other ways to ask this
- Show me how the sanitized keyword works on a method parameter for a query builder.
- Create a QueryBuilder class whose addClause method validates its input via the sanitized modifier.
- Implement a method that protects query state from injection through call arguments.
- Build a class with a sanitized-parameter method that classifies query fragments.
Coming from another language?
Java: validation inside the method body, or runtime libraries like Apache Validator. Python: input validation with re.match before use. Rust: validate by attempting to construct a newtype from the input. C#: data annotations validators on parameters. EK9: 'sanitized' modifier on the parameter — input is unset on rejection, no exception, no manual validation code.
Keywords: LDAP injection, sanitized, method validation, object protection, method, NoSQL injection, QueryBuilder