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.

Overview

When performing security testing on Python code, a simple cyclomatic complexity check is one of the fastest and most effective early risk indicators you can apply.

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

Python Code Audit implements a Cyclomatic Complexity check, operating on the principle that secure systems are simple systems.

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: