
Python is one of the most popular programming languages in the world. It’s a powerhouse in the machine learning world, a capable backend for web development, and well-suited to data infrastructure. Because it’s a dynamically typed language, many type mismatches, missing attributes, and related errors aren’t caught until runtime unless teams use static type-checking tools.
A solid Python code review checklist catches these issues while improving readability and identifying vulnerabilities, dependency risks, and quality problems that manual review alone may miss. The stakes for failing to do this are high. In March 2026, two versions of the popular Python package LiteLLM were backdoored through a supply chain compromise.
Sadly, the attack on LiteLLM wasn’t an isolated incident. FortiGuard Labs reported that its automated threat-detection platform scanned more than 400,000 packages from PyPI during one quarter and uncovered a substantial number of malicious packages. This guide will walk through a practical Python code review checklist, showing you what to check manually, what to automate, and how to maintain both security and quality.
Use this checklist before approving a Python pull request.
There are some things humans do well, and others that are better suited to automated SAST tools. The key to a good code review is finding the right balance between the two. Here’s a guide for doing that.
Python has an official style guide called PEP 8. It recommends standards such as four spaces for indentation, a 79-character line limit for code, lowercase names with underscores for variables and functions, and CapWords for classes. Using a consistent style means developers can scan the code without having to learn unnecessary team-specific conventions.
Proper function design and naming also improve readability. A function should generally do one thing and do it well. If multiple unrelated things are occurring in the function, it’s often better to split it into two. Function names should be specific and tied to what they do. A function named validate_patient_record() is much more descriptive than process_data(). Developers shouldn’t have to read the entire function to understand its purpose.
Thankfully, much of this can be automated. Formatters such as Black and Ruff enforce consistent formatting, while linters such as Ruff, Flake8, and Pylint catch common style and semantic problems. Black and the Ruff formatter use an 88-character line length by default, so teams should configure their tools to match their chosen standard. Editor integrations can also surface these problems as developers write code—these automated checks free human reviewers to focus on logic, architecture, and security.
Python applications can contain many of the same security vulnerabilities as applications written in other languages. SQL injection can creep in through string formatting instead of parameterized queries. When subprocess is called with shell=True, unsanitized input can result in unauthorized shell commands. Insecure deserialization can occur when pickle is used with data from untrusted sources. Another common and preventable problem is hardcoded secrets, such as API keys and credentials.
A common contributor to many of these vulnerabilities is insufficient input validation. Data that comes from user input, an HTTP request, or another external source should be validated and, where appropriate, sanitized before it reaches sensitive operations. Using allowlists instead of denylists can help ensure that only expected values reach code that may be vulnerable to these attacks.
These are the patterns that static application security testing is designed to identify. A manual reviewer may catch an obvious SQL injection flaw in a small function, but as the codebase grows, it becomes easier to overlook vulnerable data flows. SAST tools can apply the same checks consistently across large amounts of code. However, no SAST tool detects every vulnerability, so automated analysis should supplement, rather than replace, manual review and security testing.
Most major Python projects rely on third-party packages from PyPI. These dependencies are a common attack surface. LiteLLM and Telnyx were both compromised after attackers obtained exposed PyPI API tokens and used them to publish malicious package releases.
Because of this, dependency hygiene should be its own pass during review. Check that new dependencies use appropriate version constraints and, for applications, are captured in a lock file or another reproducible dependency management process. This allows reviewers and automated tools to determine whether the selected version is affected by a known CVE. Other considerations include license compatibility, package maintenance, provenance, and whether the code still needs each dependency.
Software composition analysis is an automated approach to handling much of this work. SCA tools analyze supported dependency manifests and resolved dependency trees, then match identified components against vulnerability databases. They can also identify declared licenses, support license-policy reviews, and generate an SBOM to improve compliance and supply chain visibility. Performing these tasks entirely by hand is not practical at scale.
Good code includes appropriate exception handling, but Python makes it easy to swallow exceptions silently. Code that uses a bare except: clause or includes an except Exception: pass block can hide bugs that should be surfaced.
Prefer specific exceptions when possible. Broader exception handling may be appropriate at application boundaries, but it should be intentional and include a clear logging, recovery, or failure path.
Test coverage is another area where developers can become lax. New functionality should include corresponding tests, including tests for edge cases such as empty inputs, None values, boundary conditions, and unexpected types.
The type hints defined in PEP 484 also pay off during review. With them, function signatures are self-documenting, and tools such as mypy can perform static type checking. This helps close one of the gaps inherent in a dynamically typed language, although the effectiveness of type checking depends on how completely the codebase is annotated.
Logic errors, architecture issues, and readability problems are all prime candidates for manual review. For systematic security checks, automated tools can provide more consistent coverage.
Human reviewers can spot important patterns, but attention doesn’t scale well. That’s why SQL injection may be easier to notice in a three-line function than in a 200-line module. Automated tools don’t become fatigued, and SAST tools with interprocedural taint analysis can trace untrusted input through supported function and data flows, potentially identifying problems that manual reviewers miss.
Dependency risk is another area where manual review falls short. A pull request adding a specific package version to requirements.txt may look harmless to most reviewers. SCA tools can determine whether that version has a known vulnerability or introduces a potential licensing issue. Depending on their threat-intelligence capabilities, they may also detect known malicious or typosquatted packages.
Manual security testing relies heavily on both a reviewer’s attention to detail and their knowledge of application security. That’s why teams increasingly rely on cybersecurity testing tools alongside human oversight.
The most effective Python review process combines manual review with automated checks. Here are the areas where automation is most useful:
To get the most from these tools, integrate them into your CI/CD pipeline instead of requiring reviewers to run them manually. This helps teams identify problems before code is merged. AI-assisted static code analysis can also help teams prioritize findings and provide remediation context, supporting better code quality and governance.
Kiuwan’s SAST, SCA, and code quality tools support more than 30 programming languages, including Python. Kiuwan has documented more than 50 rules for Python analysis.
Across its supported languages, Kiuwan Code Security can identify vulnerability categories such as injection flaws, XSS, CSRF, broken authentication, insecure cryptography, access control flaws, and security misconfigurations. Findings can be mapped to standards and frameworks including the OWASP Top 10, CWE, CERT, PCI DSS, and the CWE/SANS Top 25.
Kiuwan Insights handles the dependency side, identifying known vulnerabilities and license risks in third-party and open-source components. It can also export SBOMs that follow the CycloneDX specification in JSON or XML format, providing additional supply chain visibility.
The Kiuwan Local Analyzer runs within your infrastructure, so your source code doesn’t leave the local machine. Analysis results, including defects and metrics, are encrypted and securely uploaded to the Kiuwan Cloud for display in its dashboards. Organizations that need the complete platform within their own environment can also evaluate Kiuwan On-Premises.
Kiuwan integrates with common CI/CD providers, including Jenkins, Azure DevOps, GitLab, GitHub Actions, Bamboo, and TeamCity. Configurable audits and quality gates can fail a pipeline or build step when defined security and quality requirements aren’t met.
Kiuwan also generates action plans based on factors such as finding priority, remediation effort, defined targets, and the amount of effort a team can allocate to remediation.
Try Kiuwan free today to see how it can help with your Python code analysis.
A checklist only works if your team actually follows it. To reduce workload, automate everything that can be reliably automated and limit the manual checklist to items that require human judgment.
What to cover manually:
What to automate:
Run the automated checks in CI so the results are available before a human reviewer evaluates the pull request. With scan results available when reviewers open the PR, they can focus their attention more effectively. Kiuwan supports this process through direct integration with CI/CD workflows.
We invite you to read our introduction to Kiuwan and start your free trial to see how the platform can support Python code reviews.