Validate Input from Flow Builder

DataWeave processes any input structure that your connector receives from Flow. Validate every input before you process it to catch malformed data and avoid security issues.

Validate Input Before Processing

DataWeave transformations process any input structure. Without validation, runtime errors can leak schema details, or invalid input can corrupt downstream data.

Do: Check the shape and presence of every input field before use.

Don't: Assume Flow has already validated the input.

Example

Vulnerable

1payload.items map ((i) -> { id: i.id, qty: i.qty })

Secure

1if (!(payload.items is Array)) fail("invalid-items")
2else payload.items map ((i) -> { id: i.id, qty: i.qty })

Validate Type Coercion

The as operator performs type coercion. Out-of-range or malformed inputs can fail with a leaky error message or pass through with precision loss.

Do: Match the input against a regex or range check before you coerce it.

Don't: Use as Number or as String on user input without validation.

Example

Vulnerable

1{ amount: payload.amount as Number }

Secure

1if ((payload.amount as String) matches /^[0-9]{1,9}$/)
2  { amount: payload.amount as Number }
3else fail("invalid-amount")

Validate Types in Filter Conditions

Filters on mixed or unchecked types can trigger coercion errors or unintended logic paths. Non-numeric or malformed input can crash the transform or the transform can silently misinterpret it.

Do: Validate the format of each field in a filter expression before you compare the values.

Don't: Apply numeric or boolean comparisons in a filter without first checking that the input matches the expected format.

Example

Vulnerable

1payload.users filter ($.age > 18)

Secure

1payload.users filter ((u) -> ((u.age as String) matches /^[0-9]+$/) and ((u.age as Number) > 18))

Don't Default Sensitive Fields

A default on a sensitive field hides a missing-required-field error and bypasses your authentication check.

Do: Fail fast when a required field is missing.

Don't: Use default "guest" or similar placeholders in security-sensitive code paths.

Example

Vulnerable

1var userId = payload.userId default "guest"
2---
3{ userId: userId }

Secure

1if (isEmpty(payload.userId default "")) fail("missing-userId")
2else { userId: payload.userId }

URL-Encode User Input

The connector framework scopes outbound calls to the configured Named Credential's base URI, but path interpolation can still inject traversal sequences or break URL parsing.

Do: URL-encode every user-supplied value before you concatenate it into a URL.

Don't: Build URLs with raw string concatenation.

Example

Vulnerable

1"https://api.example.com/search?q=" ++ payload.q

Secure

1"https://api.example.com/search?q=" ++ dw::core::URL::encodeURIComponent(payload.q as String)

Allowlist Dynamic Output Keys

A user-controlled value as a DataWeave object key can introduce unauthorized fields such as isAdmin: true into the output. Downstream systems interpret these fields as privileged data.

Do: Validate the key against an explicit allowlist before you use it.

Don't: Use (payload.keyName): ... patterns without checking the key.

Example

Vulnerable

1{ (payload.keyName): payload.value }

Secure

1if ((payload.keyName as String) in ["firstName", "lastName", "email"])
2  { (payload.keyName): payload.value }
3else fail("invalid-key")

Guard Against Null and Out-of-Bounds Access

DataWeave selectors return null rather than raise an error for missing fields and out-of-range array indices. Chained operations on those null values can fail with leaky error messages or quietly produce wrong output.

Do: Check for null and array bounds before chained access.

Don't: Chain selectors or index into arrays without guarding the inputs.

Example

Vulnerable (null chain)

1{ emailDomain: (payload.user.email splitBy "@")[1] }

Secure (null chain)

1if ((payload.user default null) == null or (payload.user.email default null) == null)
2  fail("missing-email")
3else
4  { emailDomain: (payload.user.email splitBy "@")[1] }

Vulnerable (array index)

1{ item: payload.items[payload.index as Number] }

Secure (array index)

1if ((payload.index as Number) >= 0 and (payload.index as Number) < sizeOf(payload.items))
2  { item: payload.items[payload.index as Number] }
3else fail("invalid-index")

Validate Output Before Returning

Even after you validate inputs, the values that you compute or pass through can fail to match the schema that downstream consumers expect. Unvalidated output can corrupt downstream data or carry injection payloads through your connector.

Do: Validate output values against expected ranges, enums, and formats before you return them.

Don't: Trust input-side validation alone. Re-check values that flow to the output.

Example

Vulnerable

1{ status: payload.status, score: payload.score }

Secure

1if ((payload.status in ["OK", "FAILED"]) and ((payload.score as Number) >= 0 and (payload.score as Number) <= 100))
2  { status: payload.status, score: payload.score }
3else fail("invalid-output")