ASVS 5.0 V15.3.5 requires the application to explicitly check that variables have the right type and to use strict equality and comparison, so code never silently assumes a type. It is Level 2. Validate type at the boundary, then compare with operators that do not coerce.
Why it matters
Loosely typed languages convert values to make comparisons work. In PHP, comparing certain numeric looking strings with == can be true even when the strings differ. In JavaScript, "0" == false is true. Authentication checks, token comparisons and permission checks built on loose equality have been bypassed this way.
How to implement it
Parse input into the expected type once, rejecting anything else, then use strict operators.
declare(strict_types=1);
function isValidToken(string $supplied, string $expected): bool {
return hash_equals($expected, $supplied); // type safe and constant time
}
function parseId(value) {
if (typeof value !== "string" || !/^[0-9]{1,18}$/.test(value)) {
throw new TypeError("id must be a numeric string");
}
return Number(value);
}
if (user.role === "admin") { /* strict comparison */ }
In PHP use === and in_array($x, $list, true). Turn on a linter rule that bans loose equality.
How to test it
Send unexpected types: arrays where strings are expected, numbers instead of strings, null, true, 0, and strings like "0e123". Every one should be rejected or fail the check, never pass it. Add these cases to unit tests for login, token and role checks.
Common mistakes
- Using loose equality only in the security check, since it looks harmless.
- Comparing password hashes with an operator that coerces them.
- Trusting that JSON numbers arrive as numbers.
Quick check
Is a type declaration enough?
Not in languages that coerce at runtime. Declare strict mode and still validate input at the boundary.