How do sanitized parameters work with web service content binding?

← Security and Sanitization · Ref: Q665

Sanitized parameters combine naturally with service content binding. When a service operator receives request body content via :=: CONTENT, the parameter can be marked sanitized for automatic input cleaning.

SANITIZED CONTENT BINDING

  operator += :/
    -> body as sanitized String :=: CONTENT

The request body is both bound from HTTP content AND sanitized before the operator body runs.

SANITIZED PATH PARAMETERS

  byId() as GET for :/{resourceId}
    -> resourceId as sanitized String

Path parameters from URLs can also be sanitized.

PATTERN: SAFE API

Combine sanitized with copy constructor in service methods:

  operator += :/
    -> payload as sanitized String :=: CONTENT
    safeCopy <- String(payload)
    // Process safeCopy safely

See Q661 for sanitized basics. See Q662 for copy patterns. See Q657 for URI mapping. See Q658 for path parameters.

Example

defines module qa.sanitizeddeep.serviceintegration

  defines function

    <?-
      Standalone function demonstrating sanitized parameter
      in a function context, similar to how service methods work.
    -?>
    processPayload()
      -> payload as sanitized String
      <- result as String: ""

      safeCopy <- String(payload)
      result: "Received: " + safeCopy

    <?-
      Function that accepts sanitized input and delegates.
    -?>
    handleRequest()
      -> requestBody as sanitized String
      <- response as String: ""

      response: processPayload(requestBody)

  defines service

    <?-
      Service with sanitized content binding on POST.
      The request body is sanitized before the operator body runs.
    -?>
    SecureApi :/api open

      // GET /api/status — no sanitization needed for read
      status() :/status
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"status": "ok"}`
          override status() as pure
            <- rtn as Integer: 200
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "no-cache"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

      // POST /api — sanitized content binding
      operator += :/
        -> payload as sanitized String :=: CONTENT
        <- response as HTTPResponse: () with trait HTTPResponse
          override content()
            <- rtn as String: `{"accepted": true}`
          override status() as pure
            <- rtn as Integer: 201
          override contentType() as pure
            <- rtn as String: "application/json"
          override cacheControl() as pure
            <- rtn as String: "no-store"
          override contentLanguage() as pure
            <- rtn as String: "en"
          default operator ?

  defines application

    SecureApiApp
      register SecureApi()

  defines program

    SanitizedServiceDemo()
      stdout <- Stdout()

      stdout.println("Sanitized service integration:")
      stdout.println("  POST /api with sanitized CONTENT binding")
      stdout.println("  Automatic injection prevention on request body")

      processed <- processPayload("safe user data")
      stdout.println(processed)

Common mistakes

E07910 — The sanitized modifier can only be applied to String parameters. Injection attacks exploit string interpolation, so non-string types have no attack vector. See ek9 -h E07910 for details.

Incorrect:

-> payload as sanitized Integer :=: CONTENT

Correct:

-> payload as sanitized String :=: CONTENT

E07930 — Direct assignment from a sanitized parameter creates hidden aliasing. Use the copy constructor String(param) to create an independent copy that avoids shared mutable state. See ek9 -h E07930 for details.

Incorrect:

safeCopy <- payload

Correct:

safeCopy <- String(payload)
Other ways to ask this
  • Can I use sanitized with CONTENT binding in services?
  • How do I sanitize request bodies in EK9 services?
  • How does sanitized interact with service operators?

Coming from another language?

Java: Spring @RequestBody with manual validation. Python: Flask request.get_json() with schema validation. Go: manual sanitization after body read. Rust: actix extractors with validation. EK9: sanitized modifier on CONTENT-bound parameter provides automatic call-site sanitization.

Keywords: service, web, CONTENT, binding, security, E07930, E07910, sanitized, validate, sanitize