Input validation is the process of checking incoming data for compliance with the expected format, type, and value range before the application processes it. According to OWASP Input Validation Cheat Sheet (2025), the absence of validation is the root cause of most critical vulnerabilities. Checking incoming data is the first line of defense, preventing invalid or malicious data from entering the system.
Key points
Input validation is the check that data entering the application from a user, an external service, or another component meets the expected criteria. These criteria include the data type (string, number, date), the format (email, URL, phone), the value range (age from 18 to 120), the length (password from 8 to 128 characters), and the allowed characters (only Latin letters, digits, hyphen). Without validation, the application may process data that causes runtime errors, data corruption, or security vulnerabilities.
The absence of input validation is the root cause of vulnerabilities such as SQL Injection, XSS, Command Injection, Path Traversal, and Buffer Overflow. According to MITRE CWE (2025), CWE-20 (Improper Input Validation) ranks second among the most dangerous software weaknesses. Validation is the first line of defense in the Defense in Depth security model: it cuts off invalid data before it reaches other system components.
Validation rejects data that does not meet the criteria. Sanitization (cleaning) modifies data by removing or escaping dangerous parts. For example, when HTML content is entered, validation can check the text length, while sanitization can remove script tags using the HTML Purifier or DOMPurify library. Sanitization does not replace validation: they work in tandem. Validation is an "allowed/forbidden" policy, while sanitization is "cleaned before use".
Validation is classified by the depth of checking. Format validation is the simplest and fastest, while business validation is the most complex and context-dependent. All three levels must be applied in sequence: first format, then semantics, then business logic. Skipping any level can lead to incorrect system behavior or vulnerabilities.
| Level | What it checks | Example |
|---|---|---|
| Format | Data type, length, regular expression | Email contains @, length 5-100 |
| Semantic | Logical correctness of the value | Date of birth is not in the future |
| Business validation | Compliance with business rules | Transfer amount does not exceed the balance |
Checking the data type, size, format, and allowed characters. It is implemented using regular expressions, built-in language types, and validation libraries. Examples: checking a UUID (format of 8-4-4-4-12 hexadecimal digits), checking a phone number (only digits, + at the start, from 7 to 15 characters), checking an integer (value within the Integer.MIN_VALUE — Integer.MAX_VALUE range). Format validation is the minimum required level for any input field.
Checking the logical correctness of data in the context of the domain. For example: the start date is not later than the end date, the age is within reasonable limits for the system, the coordinates are within the service area. Semantic validation requires understanding of the business context and cannot be performed based on format alone. For example, the "number of tickets" field may pass format validation (integer, > 0) but semantically cannot exceed the number of available seats.
The most complex level — checking data for compliance with the application's business rules. Examples: a user cannot delete the only administrator, the order total does not exceed the credit limit, an item can be ordered only if it is in stock. Business validation often requires database queries or external services and is performed after format and semantic checks. Business validation errors are the most common cause of user dissatisfaction.
Client-side validation (in a browser or mobile application) is needed for user convenience: instant feedback without sending data to the server. However, server-side validation is the only reliable one, since client-side code can always be bypassed. Send requests via developer tools, Postman, or a proxy (Burp Suite) — and client-side validation ceases to exist. According to PortSwigger Research (2025), more than 90% of tested web applications rely solely on client-side validation for at least one field.
Client-side validation can disable the submit button, highlight errors, and show hints. Server-side validation is a mandatory check of every parameter, even if the client has already checked it. Duplicating validation at both levels is standard practice. The server must check data as if the client did not exist. This guarantees protection against modified requests, automated attacks, and malicious clients.
In the web — HTML5 attributes (required, pattern, min/max, type="email") and JavaScript. In mobile applications — native text field validators (InputFilter in Android, textField(:shouldChangeCharactersIn:) in iOS). React Hook Form and Formik for React, Vuelidate for Vue, Angular Reactive Forms — popular libraries for client-side validation. They all support custom rules and asynchronous validation (checking login uniqueness on the server).
// Example of server-side validation with Express and Joi
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string()
.email()
.required()
.max(255),
age: Joi.number()
.integer()
.min(18)
.max(120)
.required(),
password: Joi.string()
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,128}$/)
.required()
});
app.post('/api/users', async (req, res) => {
const { error, value } = userSchema.validate(req.body);
if (error) {
return res.status(400).json({
error: error.details[0].message
});
}
// value — already validated and safe data
const user = await User.create(value);
res.status(201).json(user);
});
Mobile applications place special requirements on data validation. The screen is smaller — errors should be concise, the keyboard contextual (numeric for entering numbers), and the check asynchronous so as not to block the UI. Native platforms provide built-in validation mechanisms that should be used by default. The Material Design Guidelines for Android and the Human Interface Guidelines for iOS contain detailed recommendations for displaying validation errors.
Jetpack Compose offers a declarative approach to validation through state management. Each input field is bound to a state (MutableState), and the error is computed based on the current value. The Compose Validator library simplifies creating rules: required, email, min/max length, pattern. Validation triggers on text change (onValueChange) or when the form is submitted. It is recommended to show the error only after the first submit or after the user has finished typing (debounce 300-500ms).
SwiftUI has no built-in form validation mechanism, but it makes it easy to implement one through Combine and property wrappers. Use @State for the field value and a computed property for the error. The ValidatedPropertyKit framework provides ready-made decorators: @Validated().email(), @Validated().range(18...120). An iOS recommendation — use keyboard types (UIKeyboardType.emailAddress, .numberPad) and auto-capitalization to reduce the number of input errors.
Flutter provides the Form and TextFormField classes with built-in validation through a validator callback. Each field returns an error as a string or null if the data is correct. FormState.validate() runs validation of all form fields. The reactive_forms package for complex cases: custom validators, asynchronous validation, dynamic rules. Flutter Web and the mobile version use the same API, which simplifies maintenance.
// Example of Flutter form validation
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return 'Enter a valid email';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Process valid data
}
},
child: Text('Submit'),
),
],
),
)
Modern frameworks provide built-in validators that cover 80% of needs. The remaining 20% require custom rules, regular expressions, or composition of existing ones. The key principle is that validation should be declarative so it can be easily read, tested, and maintained. Avoid validation logic spread across controllers and screens — move it into separate classes or schemas.
| Tool | Platform | Features |
|---|---|---|
| Joi | Node.js | Declarative schemas, custom messages |
| Pydantic | Python | Type hints, automatic model validation |
| Zod | TypeScript | Type inference, strict typing |
| javax.validation | Java | Bean Validation, @NotNull, @Size, @Pattern |
| FluentValidation | .NET | Fluent API, rulesets, conditional rules |
A white-list defines which data is allowed; everything else is rejected. A black-list defines which data is forbidden; everything else is allowed. A white-list is always more reliable: you know exactly which data will pass. A black-list requires anticipating all possible attacks, which is impossible. Example: when checking age, use a white-list (only numbers from 18 to 120) rather than a black-list (forbid "0", "-1", "999999").
Regular expressions are an effective tool for format validation, but they can be a source of ReDoS attacks (Regular Expression Denial of Service). Some patterns (for example, (a+)+b) lead to catastrophic backtracking on long strings, fully loading the server CPU. Use proven regex libraries and limit the string length before applying a regular expression. For complex cases (email, URL), use the built-in parsers of languages rather than homemade regexes.
Even experienced developers make mistakes when implementing validation. The most common ones: validation only on the client, overly strict rules (password "Must contain uppercase, lowercase, digit, special char, >= 12 chars, must not repeat characters"), uninformative error messages ("Error: invalid input"), and ignoring edge cases (leading/trailing spaces, Unicode characters, empty strings). Each of these mistakes worsens the UX and can lower form conversion.
if (value) does not distinguish an empty string from zero, false, or "0"Best practice is a centralized validation system covered by unit tests. Each rule should be tested separately: boundary values, correct data, typical attacks (SQLi attempts, XSS payloads, very long strings). Regression tests on validation prevent accidental weakening of rules during refactoring. Use property-based testing (QuickCheck, fast-check) to generate random data and verify that validation does not fail with an exception.
Frequently asked questions
Validation rejects invalid data, while sanitization cleans it. For example, when HTML text is entered, validation checks the maximum length, while sanitization removes script tags via DOMPurify. Both processes are mandatory: validation for format control, sanitization for output security.
No, never. Client-side validation is easy to bypass through request interception and modification. Use tools like Burp Suite or simply curl. Server-side validation is the only reliable way to protect the system. Client-side validation only serves to improve the user experience.
Check the MIME type (not just the extension), the file size, and the signature (magic bytes at the beginning of the file) through file signature validation. Never trust the extension — rename the file when saving. For images, re-encode them with a server library (ImageMagick, Sharp), which removes embedded code from EXIF data.
ReDoS (Regular Expression Denial of Service) is an attack in which an attacker sends a specially crafted string that causes catastrophic backtracking in a regular expression. As a result, the server CPU is loaded at 100% and no response is produced. Protection: limit string length, regex timeouts, and use proven patterns.
Yes, if the data is displayed in a WebView or used in an HTML context. If the backend is compromised, the data may contain malicious code. Validate and sanitize any data displayed to the user, regardless of the source. In mobile applications, this is especially important for hybrid components.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also