Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Why Performing a Complexity Check

In Python development, complexity — whether in code, dependencies, or architecture — is a silent but significant security risk. Conducting regular complexity checks (code complexity, cognitive complexity, and dependency complexity) is an essential part of a mature security posture.

Key Reasons for a complexity checks from a security point of view:

In today’s threat landscape, relying on vulnerability scanning is by far not enough. A complexity check adds a critical layer of proactive defence by addressing the root causes of many security weaknesses in Python projects.

Complex code has a lot of disadvantages when it comes to managing security risks. Making corrections is difficult and errors are easily made.

What is it?

Cyclomatic complexity is a software metric used to indicate the complexity of a program. It was developed by Thomas J. McCabe, Sr. in 1976.

Cyclomatic complexity measures the number of independent execution paths through a function or module.

Calculating the cyclomatic complexity for Python source code is difficult to do accurately. Most implementations aiming for a thorough complexity score eventually become somewhat subjective or opinionated.

The complexity is determined per file, and not per function within a Python source file. I have worked with companies that calculated function points for systems that needed to be created or adjusted. Truth is: Calculating exact metrics about complexity for software code projects is a lot of work, is seldom done correctly and are seldom used with nowadays devops or scrum development teams.

Importance for Security Auditing

Complexity directly impacts security. Simple systems are:

Python Code Audit tool calculates the complexity per file and provides a module-level overview to help you track this metric.

High cyclomatic complexity is strongly correlated with security risk for several reasons:

  1. Hidden Logic Paths The more branches a function has, the harder it becomes to reason about all possible execution paths. Security vulnerabilities often hide in rarely executed branches.

  2. Incomplete Testing Coverage Each independent path ideally requires at least one test case. As complexity grows, full path coverage becomes impractical, increasing the chance that:

    • Authentication checks are bypassed

    • Error handling leaks sensitive data

    • Validation logic is skipped in edge cases

  3. Inconsistent Input Validation Complex conditional structures frequently lead to inconsistent sanitization or validation across branches, creating injection or authorization flaws.

  4. Exception Handling Risks Multiple try/except blocks can unintentionally swallow security-critical exceptions, masking failures in cryptographic checks, permission validation, or deserialization logic.

Cyclomatic complexity is an early-warning system. Python Code Audit makes it simple to automate this check and consistently highlight high-risk areas.

Python security testing involves analysing intricate execution paths where vulnerabilities—which often elude automated testing tools—can remain undetected.

How does Code Audit calculates the Complexity?

Every function, method, or script starts with a base complexity of 1 (i.e., one execution path with no branching).

It adds 1 for each control structure or branching point:

AST Node TypeReason for Increasing Complexity
IfConditional branch (if/elif/else)
For, WhileLoop constructs (create additional paths)
TryPotential for exception handling (adds branch)
ExceptHandlerEach except adds a new error-handling path
WithContext manager entry/exit paths
BoolOpand / or are logical branches
MatchMatch statement (like switch in other langs)
MatchCaseEach case adds an alternative path
AssertIntroduces an exit point if the condition fails

Python Code Audit calculates the cyclomatic complexity of Python code using Python’s built-in Python ast (Abstract Syntax Tree) module.

Example:

"""complexity of code below should count to 4
Complexity breakdown:
1 (base)


+1 (if)


+1 (and) operator inside if


+1 (elif) — counted as another If node in AST
 = 4


"""
def test(x):
    if x > 0 and x < 10:
        print("Single digit positive")
    elif x >= 10:
        print("Two digits or more")
    else:
        print("Non-positive")

You can verify the complexity of a single Python file with the command:

 codeaudit filescan <filename.py>

Summary:

Checking Python Code Complexity with Python Code Audit

Check complexity for a Package or local directory

To check the complexity of e.g. the requests package:

codeaudit overview requests

This gives:

And per file security relevant statistics that are equal when running the command:

codeaudit filescan request

Check complexity for a single local Python file

To analyze the complexity of a single Python file:

 codeaudit filescan <myfilename.py>

This command generates detailed security-relevant statistics for the file.

For every Python file the following security relevant statistics are determined: