Client-side validation runs on a device the attacker controls, so any rule that exists only in the browser or the mobile app is a suggestion, not a control. That is well known, yet CWE-602 (Client-Side Enforcement of Server-Side Security) still turns up in coupon limits, price fields, role flags and upload filters, because teams validate thoroughly in the user interface and assume the API behind it is only reached through that interface. This guide compares the two layers as security architecture: the threat model each faces, how bypass works in principle, what client-side checks are genuinely good for, why API clients, mobile apps and integrations change the picture, and how to keep one set of rules enforced in the right place. It is for application security engineers, API owners, front-end and mobile leads, and assessors. Rule design and encoding are covered in the Input Validation and Output Encoding Guide; this page is about where validation lives.
Key takeaways
- The server is the only enforcement point. OWASP ASVS 5.0 requirement V2.2.2 asks that input validation is enforced at a trusted service layer and says client-side validation must not be relied upon as a security control; V8.3.1 says the same for authorisation.
- Client-side validation is a UX and cost feature. It gives instant feedback, reduces round trips for honest mistakes and can surface suspicious tampering in logs, which is worth having, but it never decides what is allowed.
- Every API is a client-free interface. Mobile apps, partner integrations, scripts and AI agents call the same endpoints without your front end, so rules must live with the endpoint, ideally in a schema the gateway and service both enforce.
- Validation includes business rules. Type and length checks are the easy part; price, quantity, ownership, state transitions and which fields a caller may set are where client-only enforcement causes the most damage.
- Share rule definitions, not trust. Generate client and server checks from one schema so they cannot drift, but treat the client copy as a convenience and test the server as if the client did not exist.
Two layers, two threat models
The difference is not where the code runs but who controls the environment it runs in.
Client-side validation
Client-side validation is any check performed in code delivered to the user: HTML constraint attributes such as required, minlength, maxlength, min, max, step, type and pattern; the browser's Constraint Validation API (checkValidity(), reportValidity(), setCustomValidity() and the ValidityState flags such as patternMismatch and rangeOverflow); JavaScript form libraries; and the equivalent checks in native mobile and desktop apps. Its threat model is simple: the user and anything running on the user's device are fully trusted to run it. That assumption holds for honest users making typing errors and fails for everyone else. MDN's form validation guide puts it plainly: never trust data passed to your server from the client, because a malicious user can alter the network request even when the form validates correctly.
Server-side validation
Server-side validation is any check performed in an environment the organisation controls: an API gateway enforcing an OpenAPI or JSON Schema contract, framework model binding with validation annotations, explicit checks in the service layer, and database constraints. Its threat model assumes every request may be crafted by an adversary who has read the client code, knows every field name and can send any value in any order at any rate. OWASP's Input Validation Cheat Sheet states the rule directly: validate on the server even when the browser checks the same fields. NIST SP 800-53 control SI-10 (Information Input Validation) frames the same requirement as checking the syntax and semantics of system inputs, including character set, length, numerical range and acceptable values.
Side-by-side comparison
| Property | Client-side validation | Server-side validation |
|---|---|---|
| Who controls execution | The user's device, browser, extensions, proxies | The organisation |
| Can be bypassed by the caller | Yes, always | Only through a flaw in the server logic |
| Security control? | No (ASVS V2.2.2, CWE-602) | Yes (ASVS V2.2.1, SI-10) |
| Main value | Immediate feedback, fewer failed submissions, accessibility of error messages | Enforcement of type, range, structure, business rules and authorisation |
| Applies to API clients | No; scripts, partners, mobile and agents skip it | Yes, every caller |
| Sees the full context | Only what the client was sent | User identity, object ownership, current state, stock, prices, limits |
| Typical tooling | HTML constraints, Constraint Validation API, form libraries, generated validators | Gateway schema validation, framework validators, DTOs, domain checks, database constraints |
| Failure impact if missing | Worse user experience, more server-side rejections | Injection, tampering, privilege escalation, business logic abuse, crashes |
| Logging value | Little (client logs are untrusted) | High: a server-side rejection of input the client would have blocked is a tampering signal |
How bypass works, and why it is unavoidable
Assessors do not need special skill to defeat client-side checks; the mechanisms are part of how the web and mobile platforms work. Understanding them explains why no amount of client hardening changes the conclusion.
- Direct requests: any HTTP client can send a request to the endpoint without loading the page at all. The form, its JavaScript and its constraints never execute.
- Intercepting proxies and browser developer tools: a request can be edited after the client has validated it and before it reaches the server. Hidden fields, disabled inputs and read-only values are just as editable as visible ones.
- Turning validation off: the
novalidateattribute, removing attributes in the DOM or disabling scripts all stop browser checks. MDN notes thatnovalidateis a normal feature for custom error display, which shows how little the browser treats these checks as a boundary. - Modified or repackaged mobile apps: apps can be decompiled, patched or instrumented. OWASP MASVS notes that authentication and authorisation enforcement must be on the remote endpoint, and its resilience category states that security must rely on verifiable design, strong cryptography and server-side validation; obfuscation and anti-tampering raise cost but do not move enforcement.
- Replay and sequencing: requests can be replayed, reordered or sent in parallel, skipping steps a wizard enforces in the interface. ASVS V2.3.1 asks that business logic flows are processed only in the expected step order without skipping steps, which only the server can check.
CWE-602's observed examples show the pattern across product types: a coupon limit enforced only in the front end (CVE-2024-50653), a SCADA product with client-side-only authentication (CVE-2022-33139) and an upload filter bypassed to place server-side script files (CVE-2006-6994). The common thread is a protection designed for the server but implemented on the client.
What client-side validation is genuinely for
Dropping client-side checks because they are not security would be a mistake. CWE-602's own mitigation keeps them: duplicate client-side checks on the server, and keep the client checks for user feedback, intrusion detection and a small reduction in server load from accidental errors.
- Feedback at the point of entry: constraint attributes and custom messages tell a user immediately that a postcode is malformed, rather than after a round trip. Pair them with accessible error text linked to the field.
- Reducing noise: catching honest mistakes in the client means server-side rejections are rarer and therefore more meaningful as signals.
- Tamper indicators: if a request arrives with a value the client would have blocked (a quantity of minus five, a 10,000-character name), either the client is outdated or someone bypassed it. That is worth a security log event, as ASVS V16.3.3 asks applications to log attempts to bypass controls such as input validation and business logic.
- What not to put in the client: secrets, pricing logic the user should not see, authorisation decisions, and full rule sets that reveal fraud thresholds. Client-side code is readable by anyone.
API clients change the question
For a server-rendered form, it is tempting to think of the browser as "the client". For an API, there are many clients, most of which are not yours.
| Caller | Runs your client validation? | What the server must enforce |
|---|---|---|
| Your single-page web app | Yes, unless bypassed | Everything; the SPA is just one consumer of the API |
| Your mobile app (older versions in the field) | Only the rules shipped in that version | Everything, including rules added after old versions shipped |
| Partner or customer integrations | No | Schema, business rules, rate and quantity limits, per-client authorisation |
| Internal services and batch jobs | No | Schema and business rules; internal callers can be compromised or buggy |
| AI agents and automation using API tools | No | Schema, business rules, scopes and limits; agents generate inputs no form would |
| Attackers | No | Everything, at any rate and in any order |
- Property-level authorisation: APIs that bind request bodies straight onto objects let callers set fields the interface never shows. The OWASP API Security Top 10 2023 entry API3 Broken Object Property Level Authorization includes a scenario where a guest can set an internal
total_stay_priceproperty. See OWASP API Top 10 API3 Broken Object Property Level Authorization Guide. - Mass assignment: OWASP's Mass Assignment Cheat Sheet (CWE-915) recommends allowlisting bindable fields or binding to data transfer objects that contain only user-editable fields, and warns that blocklists are fragile because a new sensitive field stays bindable. ASVS V15.3.3 asks for per-controller and per-action field limits.
- Schema strictness: JSON Schema allows properties that are not listed by default, and properties listed under
propertiesare not required by default. SetadditionalProperties: false(orunevaluatedProperties: falsewhere subschemas are composed withallOf) and an explicitrequiredlist, or the contract validates almost anything. - Business flows and volume: limits that the interface enforces by design (one coupon per order, a human pace through checkout) need server-side equivalents. See OWASP API Top 10 API6 Unrestricted Access to Sensitive Business Flows Guide and ASVS V2.4.1 and V2.4.2 on anti-automation and realistic timing.
Where server-side validation should sit
"Server-side" is not one place. A layered design puts each check where it has the context to decide.
| Layer | Checks it can make well | Checks it cannot make |
|---|---|---|
| API gateway or edge | Contract validation against OpenAPI or JSON Schema, size limits, content type, unknown fields, rate limits | Ownership, prices, state, cross-field business rules |
| Framework binding and DTOs | Type coercion, required fields, field allowlists, formats, ranges | Rules that need a database lookup |
| Service or domain layer | Business rules, cross-field consistency (ASVS V2.2.3), state transitions, authorisation, recomputing totals | Nothing should be missing here; this is the authoritative layer |
| Data layer | Constraints (not null, unique, foreign keys, check constraints), parameterised queries | User-facing error messages; context of the caller |
- Recompute, do not accept: never take a price, total, discount, role or owner identifier from the request when the server can derive it. Look it up, calculate it, or bind it from the authenticated session.
- Validate after decoding, before use: canonicalise encodings once, then validate. The OWASP cheat sheet adds that normalisation is not sanitisation and does not replace output encoding.
- Bound regex work: limit input length before pattern matching, require a whole-value match and treat a timeout as a validation failure. See the Regular Expression Denial of Service (ReDoS) Guide.
- Gateways do not replace services: a gateway schema is a useful first filter but an internal caller that reaches the service directly skips it. Keep authoritative checks in the service. See WAF vs API Gateway for what each edge layer can and cannot do.
Choosing how much to put on each side
- Simple internal forms: HTML constraint attributes plus server-side framework validation are enough. Do not build a parallel JavaScript rule engine.
- Public consumer apps: rich client-side feedback for conversion and accessibility, generated from the same schema the server enforces, with server-side business checks and tamper logging.
- Public or partner APIs: no assumption of any client. Strict contract validation at the gateway, DTO binding, domain checks, rate and business flow limits, and published error formats so integrators can handle rejections.
- Mobile apps: the server must enforce rules for every app version still in use. Version-gating old clients helps UX but is not a control. Client resilience measures (obfuscation, attestation) are worth adding where fraud economics justify them, as extra signals, not as enforcement.
- Offline-first and edge clients: where clients work offline and sync later, validate every synced change on the server as if it were new input; conflicts and rejected changes need a user-facing reconciliation path.
Worked scenario: a checkout that trusted the basket
A retailer's single-page checkout calculates line totals, applies a promotion code and sends the basket, including unit prices and the discounted total, to an order API. The interface limits quantity to between 1 and 10 and allows one promotion code per order. A mobile app built later reuses the same API.
- Finding: an assessment shows the order API accepts the submitted unit price and total, accepts negative quantities, and applies a promotion code each time it appears in the request. None of this is reachable through the interface, all of it through the API.
- Immediate containment: the team adds a gateway schema with integer ranges,
additionalProperties: falseand a single promotion code field, and starts logging rejections. This blocks the obvious abuse within a day. - Proper fix: the order service stops accepting prices and totals. It reads prices from the catalogue, validates quantity and stock, applies promotions through a rules service that enforces single use per order and per customer, and recomputes the total. The API contract changes to accept only product identifiers, quantities and a promotion code.
- Shared rules: quantity ranges and field formats move into the OpenAPI document, from which the web and mobile client validators are generated, so the user experience matches the server.
- Verification: automated API tests now send requests that bypass the interface (out-of-range values, unknown fields, repeated codes, skipped checkout steps) and assert rejection. A monitoring rule alerts when rejected-tampering events from a single account exceed a threshold.
Implementation approach
- Inventory client-only rules: for each form and app screen, list the constraints the client enforces, then confirm each has a server-side equivalent. Start with money, quantities, identity fields, roles and file uploads.
- Write the contract: define request schemas in OpenAPI or JSON Schema with explicit
required, types, ranges, lengths and no additional properties. Document business rules as ASVS V2.1.1 to V2.1.3 ask. - Enforce in report-only mode first: turn on gateway schema validation logging without blocking, review rejections for a release cycle to catch legitimate clients that send extra fields, then switch to blocking.
- Move derivable values server-side: remove prices, totals, owner identifiers and role flags from request contracts; bind DTOs with field allowlists.
- Generate client validation from the contract: use the same schema to drive web and mobile validators and error messages.
- Test without the client: add API-level negative tests to the pipeline, and include client bypass in assessment scope. See the Business Logic Vulnerabilities Guide.
- Roll back safely: keep gateway enforcement behind a configuration switch per route so a schema that rejects valid traffic can return to report-only without a redeploy.
Detection and measurement
- Server-side rejection rate by rule and route: a baseline of honest errors, with spikes investigated.
- Tamper events: requests containing values the current client could not produce (unknown fields, out-of-range values, skipped steps), counted per account and per client identifier.
- Client-only rule count: rules found in the inventory with no server equivalent; target zero for security-relevant fields.
- Schema strictness coverage: percentage of write endpoints with
additionalProperties: false, explicitrequiredand bounded lengths. - Negative test coverage: percentage of write endpoints with automated bypass tests in the pipeline.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| OWASP ASVS 5.0 | V2.2.1, V2.2.2, V2.2.3 | Positive validation; enforcement at a trusted service layer; combined data consistency |
| OWASP ASVS 5.0 | V2.3.1, V2.3.2, V2.4.1 | Step order, business logic limits, anti-automation |
| OWASP ASVS 5.0 | V8.3.1, V15.3.3, V16.3.3 | Authorisation at a trusted layer; mass assignment; logging bypass attempts |
| OWASP API Security Top 10 2023 | API3, API6 | Property-level authorisation; sensitive business flows |
| CWE | CWE-602, CWE-20, CWE-915 | Client-side enforcement; improper input validation; mass assignment |
| NIST SP 800-53 Rev 5 | SI-10, SA-11 | Information input validation; developer testing and evaluation |
| OWASP MASVS | MASVS-AUTH, MASVS-RESILIENCE | Enforcement on the remote endpoint; client resilience is defence in depth only |
Common failure patterns
- Trusting hidden and read-only fields: prices, user identifiers and role flags in hidden inputs are as editable as any other field.
- The API was "only for our app": endpoints designed for one front end are later reused by mobile apps and partners, carrying client-only assumptions with them.
- Permissive schemas: a contract without
additionalProperties: falseandrequiredpasses unknown and missing fields, giving false assurance. - Client and server rules drift: the client allows something the server rejects (frustrated users) or the server allows something the client blocks (an exploitable gap). Generate both from one source.
- Upload filters in the browser: extension checks in the file picker do not establish safe content; the OWASP cheat sheet notes that an allowed extension alone does not. See the File Upload Security Guide.
- Relying on app hardening: obfuscation and attestation in a mobile app treated as a substitute for server checks, until a patched or older app shows otherwise.
Practitioner checklist
- Inventory every client-side rule and confirm a server-side equivalent exists for each.
- Remove prices, totals, owner identifiers and role flags from request contracts; derive them server-side.
- Define strict request schemas with explicit required fields, bounds and no additional properties.
- Bind requests to DTOs with field allowlists per action.
- Enforce business rules, step order and limits in the service layer, not only at the gateway.
- Generate client validators from the same schema the server enforces.
- Log server-side rejections of values the client should have blocked as tamper events.
- Add automated API tests that bypass the client to every write endpoint.
- Include client bypass in the scope of every application and mobile assessment.
Standards and references
- OWASP: Application Security Verification Standard 5.0
- MITRE: CWE-602 Client-Side Enforcement of Server-Side Security
- OWASP: Input Validation Cheat Sheet
- OWASP: Mass Assignment Cheat Sheet
- OWASP: API Security Top 10 2023
- OWASP: Mobile Application Security Verification Standard
- MDN Web Docs: Client-side form validation
- JSON Schema: Object reference
Related NHI Mgmt Group resources: API Security Guide · Client-Side Security Guide · OWASP ASVS Guide · Mobile App Security Guide