ASVS 5.0 V8.1.4 (Level 3) requires authentication and authorization documentation to explain how environmental and contextual factors are used in decisions, on top of function, data and field level rules. It must cover the attributes evaluated, the risk thresholds, and the action taken: allow, challenge, deny or step up.
Why it matters
V8.1.3 lists the inputs. This requirement documents the logic. Without it, a risk engine is a black box, and support cannot explain to a user why a login was challenged.
How to implement it
Write a decision table:
| Signal | Threshold | Action |
|---|---|---|
| New country for this account | First seen | Step up with MFA |
| Known bad IP range | Match | Deny, log |
| New device plus password reset | Both true | Challenge, email the owner |
| Payout over 10,000 | Any | Step up regardless of context |
Then mirror it in code as a single policy function, so the document and the behavior share one source of truth:
def decide(ctx):
if ctx.ip_reputation == "bad":
return "deny"
if ctx.new_country or (ctx.new_device and ctx.recent_reset):
return "step_up"
return "allow"
How to test it
Write one test case per row of the table, feeding a synthetic context and asserting the action. When the table changes, the tests change with it.
Common mistakes
- Thresholds that exist only in a vendor dashboard.
- No record of who may change them.
- Silent denies with no logged reason.
Quick check
Is this the same as V8.1.3?
No. V8.1.3 lists the attributes. V8.1.4 documents thresholds and the resulting actions.