VNX-1121: Excessive McCabe Cyclomatic Complexity
Reports a Python top-level function or method whose McCabe cyclomatic complexity is 26 or more (one plus every if, elif, for, while, except and case statement and every and/or in their conditions). Simpler functions, comprehension decisions, docstring prose and test files are not counted or reported.
| Field | Value |
|---|---|
| Rule ID | VNX-1121 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | Python |
| CWE | CWE-1121 |
| 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 | excessive-mccabe cwe-1121 maintainability |
| Source | internal/sast/rules/vnx-1121.rego |
Overview
VNX-1121 maps to CWE-1121: Excessive McCabe Cyclomatic Complexity. For every Python top-level function and method it computes an approximation of McCabe complexity:
- one, plus
- every
if,elif,for,async for,while,exceptandmatchcasestatement in the body (nested functions included), plus - every
and/orin those statements’ headers.
The function is reported on its def line when the result is 26 or more. Decisions inside comprehensions and conditional expressions are not counted, so the measure errs low. Docstring prose and comments are not counted, and test files are skipped.
Why This Matters
Cyclomatic complexity counts independent paths through a function. Above about 25 there are more paths than anyone tests or reviews, and the paths that are skipped are where a missing authorisation check, an unvalidated branch or an unhandled error lives.
What Gets Flagged
# FLAGGED: 13 if-statements, each with an `and` -> complexity 27
def validate_order(order, user):
errors = []
if order.get("qty") is None and not user.is_admin:
errors.append("qty")
if order.get("price") is None and not user.is_admin:
errors.append("price")
...
# FLAGGED: a 26-branch elif dispatch ladder
def dispatch(self, cmd, args):
if cmd == "help":
return self.help()
elif cmd == "op1":
...
Remediation
- Replace long
if/elifdispatch ladders with a lookup table of handlers. - Extract validation steps into small named functions, or describe them as data (a schema) and validate in one loop.
- Return early on guard conditions instead of nesting.
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-1121
// nosec vnx-1121
Or record an ignore rule: vulnetix ignore add --rule vnx-1121 --reason "...". See Suppressing findings.