Skip to content

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.

Updated 02 Nov 2026Checked against cli@de9b52a
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 except clause whose whole body is pass, ... or continue, when the exception is a security one (InvalidTokenError, ExpiredSignatureError, DecodeError, BadSignature, SignatureExpired, InvalidSignature, PermissionDenied, SuspiciousOperation, AuthenticationFailed, CSRFError, VerifyMismatchError, …) or the try block 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 above DEBUG.
  • A security, auth, audit, access or login logger set disabled = True, also through a variable (audit_log = logging.getLogger("app.audit") then audit_log.disabled = True).
  • Django LOGGING sending a django.security logger to the null handler (or to no handler) with propagate: 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 continue that tries the next key in a loop which raises once every key has failed (key rotation).
  • Swallowed exceptions unrelated to security (FileNotFoundError around os.remove, a bare except around conn.close()).
  • logging.disable(logging.NOTSET), and django.security sent 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

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.

Edit this pageSources: cli/internal/sast/rules/vnx-223.rego, cli/internal/sast/docs/vnx-223.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.