Safeguard
Application Security•

What belongs on a secure coding checklist for Python teams?

A Python checklist: validate input, avoid pickle and shell=True, use the secrets module, pin dependencies with hashes, and check each item in code review.

Safeguard Security Team
4 min read

A useful Python checklist covers input validation, output encoding, safe handling of subprocesses and serialization, secure randomness, dependency integrity, and error handling. Each item should be checkable in a code review. Below is a checklist built from OWASP's coding practices and the Python documentation itself.

What does OWASP's guide organize things around?

OWASP's secure coding practices checklist groups items into input validation, output encoding, authentication and password management, session management, access control, cryptographic practices, error handling and logging, data protection, communication security, system configuration, database security, file management, memory management and general coding practices. Use those as the skeleton, then add language-specific traps below.

Which Python calls deserve an automatic second look?

Search for these in every review:

  • pickle load and loads. The Python documentation warns that the pickle module is not secure: only unpickle data you trust, since malicious pickle data can execute arbitrary code during unpickling. Use JSON for data from outside your trust boundary.
  • yaml.load with an unsafe loader. OWASP's deserialization guide says to use safe_load for untrusted YAML.
  • subprocess with shell=True. The subprocess documentation says that without shell=True, all characters, including shell metacharacters, can be passed safely to child processes. With it, quoting is the application's responsibility, and shlex.quote may help on some platforms. Prefer a list of arguments and no shell.
  • eval and exec on anything derived from input.

Constructed example. A report service builds a command string from a customer name and runs it with shell=True. A name containing a semicolon runs a second command. Rewriting it as a list of arguments with no shell removes the class of bug.

How do you generate secrets properly?

Python's documentation says the secrets module is for cryptographically strong random numbers suitable for passwords, authentication and security tokens, and should be used in preference to the random module, which is designed for modelling and simulation, not security. Tokens, reset links and API keys belong to secrets. Review any import of random near authentication code.

How do you keep dependencies honest?

pip's secure installs guide describes hash-checking mode: every requirement must be pinned and hashed, and a requirement that is not spelled out and hashed causes an error. It recommends sha256, and excludes md5 and sha1 to avoid a false sense of security. Hashes pulled from the index at download time protect against corruption, not tampering, because they come from the same remote source. Generate your hashes once, review them, and commit them.

The guide also warns against installing your own project with deprecated setuptools commands, which can download unchecked dependencies, and recommends installing with pip and the no-deps option once dependencies are installed from the hashed file.

What about output, errors and web code?

Use a template engine with autoescaping, parameterized queries for databases, and avoid returning stack traces to users. Log events without secrets or personal data, and keep log injection in mind by not writing raw user input with newlines into logs.

The checklist

  1. Validate all external input for type, length, range and format, on the server.
  2. Encode output for its context, with autoescaping on in templates.
  3. Use parameterized queries for every database call.
  4. Never unpickle untrusted data and use safe YAML loading.
  5. Call subprocesses with argument lists and no shell.
  6. Use the secrets module for tokens, keys and reset links.
  7. Install from a pinned, hashed requirements file in CI and production.
  8. Store credentials in a secret manager, not in the repository or environment dumps.
  9. Return generic errors to users and log details server-side without secrets.
  10. Apply least privilege to service accounts and file permissions.
  11. Run a linter and a dependency scan in the pull request pipeline.
  12. Review the checklist when the framework or Python version changes.

Safeguard can scan Python dependency files in pull requests and report vulnerable packages, which covers item 11 for dependencies.

Quick check

Is the random module fine for session tokens?

No. The Python documentation says secrets should be used in preference to random for security purposes, since random is designed for simulation.

Is subprocess safe by default?

Without shell=True, shell metacharacters are not interpreted, so passing an argument list is safe from shell injection. With shell=True you must quote input yourself.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.