The Web Attack Surface
A web application's attack surface is every place it accepts input and every trust boundary it crosses — URL parameters, form fields, headers, cookies, file uploads, APIs, and the browser-to-server and server-to-database lines. The single root cause behind most web vulnerabilities is trusting input that came from outside that boundary.
This topic frames the chapter: it maps app.meridian.example's surface and states the discipline — validate input, encode output, authenticate and authorize every request — that the specific defenses all instantiate.
Where Input Enters
Every parameter, header, cookie, JSON field, and uploaded file is attacker-controllable. "Input" is far more than the visible form fields — a user-agent header, a cookie value, and a JSON key are all input, and each entry point is a potential injection or logic-abuse vector. Counting only the form fields is how the widest surfaces go unguarded.
The Client Is Not Trusted
Anything enforced only in the browser — JavaScript validation, hidden fields, a disabled button — is advisory. The attacker controls the client entirely and can talk to the server directly with any values they like, so every check must be re-done server-side. A price validated only in JavaScript is a price the attacker sets.
The Trust Boundaries
Two boundaries carry most of web security. At browser-to-server, untrusted input arrives and must be validated. At server-to-sink — the database, the OS, another service — that input can turn into injection unless it is encoded for the specific sink. Web security is largely validating at the first boundary and encoding at the second, over and over.
The Browser Security Model
The same-origin policy, cookies, and CORS define what one site can do to another, and understanding this model is prerequisite to CSRF, XSS, and SSRF later in the chapter. The browser is both the attacker's tool and, through the same-origin policy, one of the defender's — which is why so many web defenses are about what the browser will and will not allow across origins.
Validate input — treat all client-supplied data as hostile and check it server-side.
Encode output — encode data for the sink it lands in (HTML, SQL, shell, URL) so it cannot be reinterpreted as code.
Authenticate every request — never rely on the client to prove identity.
Authorize every object — check that this user may access this specific resource, on every access.
- Enforcing security in client-side JavaScript and assuming the server can trust the result — the attacker bypasses the browser entirely.
- Counting only visible form fields as input while headers, cookies, JSON, and file uploads go unvalidated.
- Treating the database or OS as a trusted sink and passing user input into it unencoded, which is the root of injection.
- Misunderstanding the browser security model — origins, cookies, CORS — leading to CSRF, XSS, and CORS misconfigurations later.
- Hiding functionality by not linking to it rather than authorizing it, so it remains reachable by direct request.
- Validate and canonicalize every input server-side, treating all client-supplied data as hostile regardless of client checks.
- Encode output for the specific sink so data can never be reinterpreted as code.
- Authenticate and authorize on the server for every request and every object, never relying on the client to hide things.
- Map the full input surface — headers, cookies, APIs, uploads — not just forms, and apply the four defenses everywhere.
- Understand the same-origin policy and set CORS deliberately rather than permissively.
Knowledge Check
Why is client-side validation never sufficient on its own?
- The attacker controls the client and can send any values directly
- Client-side JavaScript runs too slowly to be trusted for validation
- Browsers randomly skip validation code
- Server-side validation is impossible for web forms
Beyond visible form fields, what else counts as attacker-controllable input?
- Headers, cookies, JSON, and uploads
- Only the URL path and query string, nothing else
- Nothing — form fields are the entire input surface
- Only fields the developer marked as required
What are the two trust boundaries where most web defenses concentrate?
- Browser-to-server to validate and server-to-sink to encode
- The database-to-backup and backup-to-cloud storage boundaries
- The DNS-to-browser and browser-to-DNS boundaries
- The CPU-to-memory and memory-to-disk boundaries
You got correct