Why can sanitized only be used on incoming String parameters?

← Security and Sanitization · Ref: Q661

The 'sanitized' modifier can ONLY be applied to INCOMING String parameters. It works by injecting call-site sanitization code that creates defensive copies.

WHY ONLY STRING

Sanitization prevents injection attacks (SQL, XSS, command injection). These attacks exploit string interpolation into commands or markup. Non-string types like Integer or Boolean don't have this attack vector (E07910).

WHY ONLY INCOMING PARAMETERS

Sanitized works by injecting code at the CALL SITE. Fields have no call site (they're initialized directly). Return parameters flow OUT, not IN. Local variables are internal with no external data entry point (E07920).

CORRECT PATTERN

  processInput()
    -> userInput as sanitized String

The caller's string is copied and sanitized before the function body runs.

CONSTRUCTOR PATTERN

To sanitize data stored in fields, sanitize the constructor parameter:

  SafeRecord()
    -> input as sanitized String
    name :=? input

See Q215 for sanitized basics. See Q217 for sanitized with purity. See Q662 for safe copy patterns.

Example

defines module qa.sanitizeddeep.paramonly

  defines function

    <?-
      Sanitized on incoming String parameter.
      The compiler injects call-site sanitization code
      that creates a defensive copy before the body runs.
    -?>
    processUserInput()
      -> userInput as sanitized String
      <- result as String: ""

      safeCopy <- String(userInput)
      result: safeCopy

    <?-
      Sanitized in constructor parameter.
      Fields get sanitized data through constructor injection.
    -?>
    buildGreeting()
      -> userName as sanitized String
      <- greeting as String: ""

      greeting: "Hello, " + userName

  defines class

    <?-
      Class that accepts sanitized input through constructor.
      The field stores already-sanitized data.
    -?>
    SafeRecord
      storedName as String: String()

      SafeRecord()
        -> inputName as sanitized String
        storedName :=? inputName

      getName() as pure
        <- rtn as String: storedName

      default operator ?

  defines program

    SanitizedParameterDemo()
      stdout <- Stdout()

      cleaned <- processUserInput("safe text")
      stdout.println(`Processed: ${cleaned}`)

      message <- buildGreeting("Alice")
      stdout.println(message)

      record <- SafeRecord("Bob")
      stdout.println(`Stored: ${record.getName()}`)

Common mistakes

E07910 — The sanitized modifier can only be applied to String parameters. Non-string types like Integer have no injection attack vector. See ek9 -h E07910 for details.

Incorrect:

-> userInput as sanitized Integer

Correct:

-> userInput as sanitized String

E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.

Incorrect:

stdout.println(record.getName().toUpperCase())

Correct:

stdout.println(`Stored: ${record.getName()}`)
Other ways to ask this
  • What is E07910 sanitized on wrong type?
  • What is E07920 sanitized in wrong location?
  • Can I mark fields or return values as sanitized?

Coming from another language?

Java: manual InputValidation.sanitize(input). Python: bleach.clean(). Go: html.EscapeString(). Rust: ammonia::clean(). EK9: 'sanitized' modifier on String parameters with automatic call-site injection.

Keywords: sanitize, E07920, String, parameter, security, injection, E07910, sanitized, validate, call-site