Tools · Python and Bash for security automation · 01 / 20
Setting up Python for security scripting: virtual environments, pinned dependencies, and secrets
Create isolated environments, pin and hash dependencies, keep API keys out of code with environment variables, and structure a small script so it is easy to reuse.
One environment per project
Installing packages globally mixes versions across projects and can break system tools. Create a virtual environment per project with python3 -m venv, or use uv, which creates environments and installs packages very quickly. Record dependencies in requirements.txt or pyproject.toml so the script runs the same way next month and on a colleague’s machine.
python3 -m venv .venv && . .venv/bin/activate pip install requests pip freeze > requirements.txt # hashes make pip refuse tampered or unexpected packages pip install pip-tools echo requests > requirements.in pip-compile --generate-hashes requirements.in pip install --require-hashes -r requirements.txt
Secrets
Never paste API keys into scripts. Read them from environment variables, a .env file that is listed in .gitignore, or a secret manager. Fail clearly if the variable is missing.
import os, sys
api_key = os.environ.get('VT_API_KEY')
if not api_key:
sys.exit('Set VT_API_KEY in the environment')Lab: a reusable script skeleton
Create a project folder with a virtual environment, a requirements file, a .gitignore that excludes .venv and .env, and a script with argparse, logging, and a main function. Run it with --help to see the generated usage text. Use this skeleton for every script in this hub.
#!/usr/bin/env python3
"""Short description of what the script does."""
import argparse, logging, sys
def parse_args():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('input', help='file to read')
p.add_argument('-v', '--verbose', action='store_true')
return p.parse_args()
def main():
args = parse_args()
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, format='%(levelname)s %(message)s')
logging.info('reading %s', args.input)
return 0
if __name__ == '__main__':
sys.exit(main())Dependency hygiene
Check package names carefully before installing, because typosquatted packages with similar names exist on PyPI. Run pip-audit periodically to find known vulnerabilities in your dependencies, and prefer well-maintained libraries with many users.
pip install pip-audit && pip-audit -r requirements.txt
Diagram
Starting a script project
- Environment
python3 -m venv .venv or uv venv.
- Dependencies
Pin and hash in requirements.txt.
- Secrets
Environment variables; .env in .gitignore.
- Skeleton
argparse, logging, main(); pip-audit regularly.
Check yourself
1. Why use a virtual environment per project?
2. Where should an API key used by a script come from?
3. Which tool reports known vulnerabilities in installed Python dependencies?