Safety CLI
Safety CLI (safety) is a Python dependency vulnerability scanner that identifies known security vulnerabilities and malicious packages in your project's dependencies. It integrates into local development, CI/CD pipelines, and production systems, providing actionable remediation recommendations. The current version is 3.7.0, and it maintains an active release cadence with regular updates.
Warnings
- breaking The policy file schema has changed significantly in Safety CLI 3.x compared to 2.x, particularly for the `scan` and `system-scan` commands. Older policy files will not work without migration.
- breaking Safety CLI 3.x has deprecated the `check` command in favor of the more comprehensive `scan` command. While `check` received maintenance until June 2024, it is no longer the recommended approach.
- breaking The JSON output format has been updated and improved in Safety CLI 3.x. If you have automated tools or integrations that parse Safety's JSON reports, they may break.
- deprecated The `license` command has been dropped from Safety CLI 3.x. Users relying on this command should continue using Safety 2.3.5 or 2.4.0b2, or await future 3.x releases that might reintroduce license scanning capabilities via the `scan` command.
- gotcha While `pip install safety` provides the CLI, comprehensive vulnerability scanning often requires authentication and an API key to access the full, up-to-date commercial vulnerability database (Safety DB).
- gotcha The current PyPI `safety` package (3.7.0) explicitly requires Python >=3.9. Although Safety CLI 3.0.0 changelog mentions supporting Python >=3.7, attempting to install or run the latest `safety` on Python 3.7 or 3.8 will fail due to environment requirements.
Install
-
pip install safety
Quickstart
import subprocess
import os
# Create a dummy requirements.txt for demonstration
with open('requirements.txt', 'w') as f:
f.write('requests==2.25.1 # known vulnerable version for demo (CVE-2023-32681, fixed in 2.31.0)
')
f.write('Flask==2.3.2 # non-vulnerable example
')
print('Scanning requirements.txt for vulnerabilities...')
# Run safety scan command. Note: For full, commercial vulnerability database access,
# an API key might be required. Basic scanning may work without explicit auth or prompt for it.
# Use os.environ.get('SAFETY_API_KEY', '') if using a commercial key programmatically.
try:
# Using check=False to capture output even if safety exits with a non-zero code (vulnerabilities found)
result = subprocess.run(
['safety', 'scan', '-r', 'requirements.txt', '--full-report'],
capture_output=True,
text=True,
check=False
)
print('--- Safety Scan Output ---')
print(result.stdout)
if result.stderr:
print('--- Safety Scan Errors ---')
print(result.stderr)
print(f'Safety exited with code: {result.returncode}')
except FileNotFoundError:
print("Error: 'safety' command not found. Ensure Safety CLI is installed and in your PATH.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# Clean up the dummy file
if os.path.exists('requirements.txt'):
os.remove('requirements.txt')