ASVS 5.0 V2.2.3 requires that the application ensures combinations of related data items are reasonable according to pre-defined rules. It is the code side of V2.1.2, and it sits at Level 2.
Why it matters
Individually valid fields can combine into an attack: a discount code with a negative quantity, an end date before the start date, a role value that the sender is not allowed to assign.
How to implement it
After field validation, run a cross field check in one place.
class Booking(BaseModel):
start: date
end: date
guests: int = Field(ge=1, le=10)
@model_validator(mode="after")
def check_dates(self):
if self.end <= self.start:
raise ValueError("end must be after start")
if (self.end - self.start).days > 30:
raise ValueError("stay too long")
return self
Look up reference data on the server, such as which regions a postal code belongs to, rather than trusting what the client claims.
How to test it
For each documented relationship, send a request where every field passes alone but the pair is wrong. Check that update requests re-validate against stored values.
Reference data
Some relationships need a lookup, such as a currency allowed for a country or a plan that includes a feature. Keep that data on the server and cached with an expiry, and refuse the request when the lookup fails instead of skipping the check.
Common mistakes
- Cross checks that run only on create.
- Trusting a derived field, like a total, sent by the client.
Quick check
Should a client supplied total be accepted?
No. Recompute totals on the server from trusted prices and quantities.