Input Validation and Output Encoding
Input validation constrains untrusted data to what the application expects, while context-appropriate output encoding keeps that data from being interpreted as executable content. Together they reduce injection risks such as XSS, but neither replaces the other.
Treat all externally supplied data as untrusted, including HTTP parameters, headers, cookies, request bodies, and data retrieved from other systems. Validation should enforce the expected type, length, range, format, and allowed values for each field.
Prefer allowlists when the valid set is known. For example, an account status might accept only `ACTIVE` or `DISABLED`, while an age field might require an integer within an application-defined range. Validation is primarily about preserving application invariants; it is not a substitute for encoding.
Output encoding depends on where data is inserted. HTML text, an HTML attribute, a JavaScript string, a URL, and SQL each have different interpretation rules, so one generic escaping routine is not appropriate for every context. For Java web applications, use a well-tested encoder or framework facility designed for the specific output context rather than writing ad hoc escaping code.
Validation can reject malformed or unexpected input, but valid input can still contain characters that are dangerous in a particular output context. Conversely, encoding data for display does not ensure that the data satisfies the application's business rules. Apply validation at trust boundaries and encode as close as possible to the output sink.
Key points
- Validate untrusted input against the expected type, format, range, length, and allowed values.
- Prefer allowlist validation when the accepted values can be enumerated.
- Encode output according to its destination context rather than using one universal escaping function.
- Validation and encoding solve different problems and should normally be used together.
- Use established security libraries for contextual encoding instead of custom escaping in production code.
Interview questions
Where should validation happen in a Java backend application?
The server should validate data at trust boundaries because clients cannot be trusted to enforce security rules. Validation can also be repeated at domain boundaries when invariants need protection from multiple callers. Framework-level validation can handle common structural constraints, while business rules belong in the appropriate application or domain layer. Database constraints can provide another layer of integrity, but they should not replace application-level validation.
Why do we need both input validation and output encoding?
They address different security properties. Validation checks whether input matches what the application expects, such as an identifier containing only permitted characters. Output encoding prevents otherwise valid data from being interpreted as code when inserted into a particular context. For example, a value can pass business validation and still require HTML encoding before being rendered in a page.
What is allowlist validation, and why is it preferred to a blacklist?
An allowlist explicitly describes the values or patterns the application accepts. For example, an enum field might accept only `ACTIVE` and `DISABLED`. A blacklist instead tries to identify every dangerous value or pattern, which is difficult because attackers can use alternate representations and unexpected syntax. When the valid domain is known, an allowlist gives the application a clearer security boundary.
Why does output encoding have to be context-specific?
Different interpreters assign different meanings to the same characters. HTML text, HTML attributes, JavaScript, CSS, and URLs therefore require different handling rules. HTML encoding does not automatically make a value safe inside a JavaScript expression or URL. The application should use an encoder appropriate to the exact output sink and context.
A user name passes validation but contains `<` and `>`. Should it be rejected or encoded?
The answer depends on the field's defined contract and its output context. If those characters are not valid according to the application's username specification, validation should reject them. If they are legitimate data for another field, they should generally be preserved and encoded when rendered into the relevant context. Security should not depend on rejecting every potentially special character because different contexts have different interpretation rules.