VNX-223: Omission of Security-relevant Information
Detects Python code that discards the record of a security event: a failed token, signature or permission check swallowed by an except clause that only passes or by contextlib.suppress(), logging.disable(), a disabled security/audit logger, and Django's django.security loggers routed to the null handler.
| Field | Value |
|---|---|
| Rule ID | VNX-223 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Python |
| CWE | CWE-223 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | omission-logging security-logging error-handling cwe-223 |
| Source | internal/sast/rules/vnx-223.rego |
Overview
VNX-223 maps to CWE-223: Omission of Security-relevant Information. Detection and incident response depend on the system recording security events: forged tokens, bad signatures, refused permissions, suspicious requests. CWE-223 is a property of what a system records, which no single line shows; the rule reports the concrete places where Python code throws that record away.
- An
exceptclause whose whole body ispass,...orcontinue, when the exception is a security one (InvalidTokenError,ExpiredSignatureError,DecodeError,BadSignature,SignatureExpired,InvalidSignature,PermissionDenied,SuspiciousOperation,AuthenticationFailed,CSRFError,VerifyMismatchError, …) or thetryblock performs a verification (jwt.decode,.verify(),verify_*(),check_password,authenticate,hmac.compare_digest,.unsign,bcrypt.checkpw,validate_csrf,has_perm,check_permissions). Such a handler also tends to fail open. logging.disable()with no argument or a level aboveDEBUG.- A security, auth, audit, access or login logger set
disabled = True, also through a variable (audit_log = logging.getLogger("app.audit")thenaudit_log.disabled = True). - Django
LOGGINGsending adjango.securitylogger to thenullhandler (or to no handler) withpropagate: False.
What Gets Flagged
try:
claims = jwt.decode(token, SECRET, algorithms=["HS256"])
except Exception: # FLAGGED
pass
logging.disable(logging.CRITICAL) # FLAGGED
"django.security.DisallowedHost": { # FLAGGED
"handlers": ["null"],
"propagate": False,
},
What Is Not Flagged
- Handlers that log, raise or return a failure.
- A
continuethat tries the next key in a loop which raises once every key has failed (key rotation). - Swallowed exceptions unrelated to security (
FileNotFoundErroraroundos.remove, a bareexceptaroundconn.close()). logging.disable(logging.NOTSET), anddjango.securitysent to real handlers.- Comments and test code (including
conftest.py).
Remediation
try:
claims = jwt.decode(token, SECRET, algorithms=["HS256"])
except jwt.InvalidTokenError:
security_log.warning("rejected token", extra={"ip": request.remote_addr})
raise PermissionDenied
References
- CWE-223: Omission of Security-relevant Information
- OWASP Top 10 A09:2021 Security Logging and Monitoring Failures
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-223
// nosec vnx-223
Or record an ignore rule: vulnetix ignore add --rule vnx-223 --reason "...". See Suppressing findings.