Scan dependencies for known vulnerabilities and licenses.
Overall
score
61%
Safety CLI uses a comprehensive set of data models and types to represent vulnerabilities, packages, requirements, and other security-related information. These models provide structured data access and serialization capabilities.
from safety.models import (
# Core models
Vulnerability, CVE, Severity, Fix, Package,
SafetyRequirement, RequirementFile,
# Utilities and encoders
SafetyEncoder, is_pinned_requirement, SafetyCLI, ToolResult
)
# Note: Announcement and Remediation must be imported directly from vulnerabilities module
from safety.models.vulnerabilities import Announcement, Remediation
from safety.errors import (
SafetyError, SafetyException, InvalidRequirementError,
InvalidCredentialError, NetworkConnectionError
)
from safety_schemas.models import (
ConfigModel, Ecosystem, FileType, Stage,
PolicyFileModel, DependencyResultModel
)Description: Represents a security vulnerability found in a package dependency.
# Note: Vulnerability is a named tuple with these fields (in order)
Vulnerability = namedtuple('Vulnerability', [
'vulnerability_id', # str: Unique vulnerability identifier
'package_name', # str: Affected package name
'pkg', # Package: Package object reference
'ignored', # bool: Whether vulnerability is ignored
'ignored_reason', # Optional[str]: Reason for ignoring
'ignored_expires', # Optional[datetime]: Ignore expiration date
'vulnerable_spec', # SpecifierSet: Vulnerable version specifiers
'all_vulnerable_specs', # List[str]: All vulnerable version patterns
'analyzed_version', # str: Currently installed version
'analyzed_requirement', # SafetyRequirement: Analyzed requirement object
'advisory', # str: Vulnerability description
'is_transitive', # bool: Is transitive dependency
'published_date', # datetime: Publication date
'fixed_versions', # List[str]: Versions with fixes
'closest_versions_without_known_vulnerabilities', # List[str]: Safe alternatives
'resources', # List[str]: Additional resources
'CVE', # CVE: CVE information
'severity', # Severity: Severity assessment
'affected_versions', # str: Affected version range
'more_info_url' # str: Additional information URL
])
class Vulnerability(vulnerability_nmt):
"""Core vulnerability information with comprehensive metadata."""Methods:
def to_dict(self) -> Dict[str, Any]:
"""
Convert vulnerability to dictionary format.
Returns:
Dict[str, Any]: Dictionary representation suitable for JSON serialization
"""
def get_advisory(self) -> str:
"""
Get cleaned advisory text.
Returns:
str: Advisory text with formatting cleaned
"""
def to_model_dict(self) -> Dict[str, Any]:
"""
Convert to model dictionary format for API communication.
Returns:
Dict[str, Any]: Structured model representation
"""Example Usage:
from safety.models import Vulnerability, CVE, Severity
from datetime import datetime
# Access vulnerability properties
vuln = Vulnerability(...) # From scan results
print(f"Vulnerability: {vuln.vulnerability_id}")
print(f"Package: {vuln.package_name} v{vuln.analyzed_version}")
print(f"Severity: {vuln.severity.cvssv3}")
print(f"Advisory: {vuln.get_advisory()}")
# Check if ignored
if vuln.ignored:
print(f"Ignored: {vuln.ignored_reason}")
if vuln.ignored_expires:
print(f"Expires: {vuln.ignored_expires}")
# Get remediation options
if vuln.fixed_versions:
print(f"Fixed in: {', '.join(vuln.fixed_versions)}")
# Convert to dictionary for serialization
vuln_dict = vuln.to_dict()Description: Common Vulnerabilities and Exposures (CVE) information.
class CVE(NamedTuple):
"""CVE identification and scoring information."""
name: str # CVE identifier (e.g., "CVE-2023-12345")
cvssv2: Optional[float] # CVSS v2.0 score
cvssv3: Optional[float] # CVSS v3.x score
def to_dict(self) -> Dict[str, Any]:
"""
Convert CVE to dictionary format.
Returns:
Dict[str, Any]: CVE information as dictionary
"""Example Usage:
from safety.models import CVE
# CVE with scoring information
cve = CVE(
name="CVE-2023-12345",
cvssv2=7.5,
cvssv3=8.1
)
# Access properties
print(f"CVE: {cve.name}")
print(f"CVSS v3 Score: {cve.cvssv3}")
# Severity classification based on CVSS score
if cve.cvssv3 >= 9.0:
severity_level = "Critical"
elif cve.cvssv3 >= 7.0:
severity_level = "High"
elif cve.cvssv3 >= 4.0:
severity_level = "Medium"
else:
severity_level = "Low"Description: Vulnerability severity assessment from multiple sources.
class Severity(NamedTuple):
"""Vulnerability severity with source attribution."""
source: str # Severity source (e.g., "safety", "nvd")
cvssv2: Optional[float] # CVSS v2.0 score
cvssv3: Optional[float] # CVSS v3.x score
def to_dict(self) -> Dict[str, Any]:
"""
Convert severity to dictionary format.
Returns:
Dict[str, Any]: Structured severity information
"""Description: Represents a Python package with version and dependency information.
@dataclass
class Package:
"""Python package with comprehensive metadata and version information."""
# Basic package information
name: str # Package name (normalized)
version: Optional[str] # Installed version
requirements: List[SafetyRequirement] # Package requirements
# Location information
found: Optional[str] = None # Where package was found
absolute_path: Optional[str] = None # Absolute path to package
# Version metadata
insecure_versions: List[str] = field(default_factory=list) # Known insecure versions
secure_versions: List[str] = field(default_factory=list) # Known secure versions
latest_version_without_known_vulnerabilities: Optional[str] = None # Latest safe version
latest_version: Optional[str] = None # Latest available version
more_info_url: Optional[str] = None # Package information URLMethods:
def has_unpinned_req(self) -> bool:
"""
Check if package has unpinned requirements.
Returns:
bool: True if any requirements are unpinned
"""
def get_unpinned_req(self) -> filter:
"""
Get unpinned requirements.
Returns:
filter: Filter object containing unpinned requirements
"""
def filter_by_supported_versions(self, versions: List[str]) -> List[str]:
"""
Filter versions by parsing support.
Args:
versions (List[str]): Version strings to filter
Returns:
List[str]: Valid, parseable version strings
"""
def get_versions(self, db_full: Dict) -> Set[str]:
"""
Get all versions from vulnerability database.
Args:
db_full (Dict): Complete vulnerability database
Returns:
Set[str]: All known versions for package
"""
def refresh_from(self, db_full: Dict) -> None:
"""
Refresh package metadata from database.
Args:
db_full (Dict): Complete vulnerability database
"""
def to_dict(self) -> Dict[str, Any]:
"""
Convert package to dictionary format.
Returns:
Dict[str, Any]: Package information as dictionary
"""Example Usage:
from safety.models import Package, SafetyRequirement
# Create package instance
package = Package(
name="requests",
version="2.28.1",
requirements=[
SafetyRequirement("urllib3>=1.21.1,<1.27"),
SafetyRequirement("certifi>=2017.4.17")
],
found="requirements.txt"
)
# Check for unpinned requirements
if package.has_unpinned_req():
unpinned = list(package.get_unpinned_req())
print(f"Unpinned requirements: {[req.name for req in unpinned]}")
# Package metadata access
print(f"Package: {package.name} v{package.version}")
print(f"Found in: {package.found}")
print(f"Latest safe version: {package.latest_version_without_known_vulnerabilities}")Description: Enhanced version of packaging.requirements.Requirement with Safety-specific features.
class SafetyRequirement(Requirement):
"""Enhanced requirement with Safety-specific metadata and methods."""
def __init__(self,
requirement: Union[str, Dependency],
found: Optional[str] = None) -> None:
"""
Initialize Safety requirement.
Args:
requirement: Requirement string or Dependency object
found: Location where requirement was found
Raises:
InvalidRequirementError: If requirement cannot be parsed
"""
# Additional properties
raw: str # Original requirement line
found: Optional[str] # Source locationMethods:
def to_dict(self, **kwargs: Any) -> Dict[str, Any]:
"""
Convert requirement to dictionary format.
Args:
**kwargs: Additional options (e.g., specifier_obj format)
Returns:
Dict[str, Any]: Requirement information as dictionary
"""
def __eq__(self, other: Any) -> bool:
"""
Compare requirements for equality.
Args:
other: Other requirement to compare
Returns:
bool: True if requirements are equal
"""Dictionary Format:
requirement_dict = {
'raw': 'requests>=2.20.0,<3.0.0', # Original requirement line
'name': 'requests', # Package name
'specifier': '>=2.20.0,<3.0.0', # Version specifiers
'extras': ['security'], # Optional extras
'marker': 'python_version >= "3.8"', # Environment markers
'url': None, # Direct URL (if any)
'found': 'requirements.txt' # Source location
}Description: Named tuple representing a requirements file location.
RequirementFile = namedtuple('RequirementFile', ['path'])
# Usage
req_file = RequirementFile(path="requirements.txt")
print(f"Requirements file: {req_file.path}")Description: Represents an applied or available security fix for a vulnerability.
@dataclass
class Fix:
"""Security fix information and metadata."""
# Dependency information
dependency: Any = None # Dependency object
package: str = "" # Package name
# Version changes
previous_version: Any = None # Version before fix
updated_version: Any = None # Version after fix
previous_spec: Optional[str] = None # Previous version specifier
other_options: List[str] = field(default_factory=list) # Alternative versions
# Fix metadata
update_type: str = "" # Type of update (major, minor, patch)
status: str = "" # Fix application status
applied_at: str = "" # When fix was applied
fix_type: str = "" # Fix type classification
more_info_url: str = "" # Additional information URLExample Usage:
from safety.models import Fix
# Applied security fix
fix = Fix(
package="requests",
previous_version="2.20.0",
updated_version="2.28.1",
update_type="minor",
status="applied",
applied_at="2024-01-15T10:30:00Z",
fix_type="security_update"
)
print(f"Fixed {fix.package}: {fix.previous_version} → {fix.updated_version}")
print(f"Update type: {fix.update_type}")
print(f"Applied: {fix.applied_at}")Description: Remediation suggestion for vulnerable packages.
class Remediation(NamedTuple):
"""Remediation suggestion with version recommendations."""
Package: Package # Affected package
closest_secure_version: str # Nearest secure version
secure_versions: List[str] # All secure versions
latest_package_version: str # Latest available version
def to_dict(self) -> Dict[str, Any]:
"""
Convert remediation to dictionary format.
Returns:
Dict[str, Any]: Remediation information
"""Description: Platform announcements and notices.
class Announcement(NamedTuple):
"""Platform announcement information."""
type: str # Announcement type
message: str # Announcement contentDescription: Abstract base class for objects that can be converted to dictionaries.
class DictConverter:
"""Base class for dictionary serialization."""
@abstractmethod
def to_dict(self, **kwargs: Any) -> Dict[str, Any]:
"""
Convert object to dictionary format.
Args:
**kwargs: Additional conversion options
Returns:
Dict[str, Any]: Dictionary representation
"""Description: Represents Safety CLI instance metadata.
from safety.models import SafetyCLI
class SafetyCLI:
"""Safety CLI instance information and metadata."""
# CLI version and environment information
version: str # Safety CLI version
python_version: str # Python version
platform: str # Operating system platform
# Usage and telemetry data
command: str # Executed command
options: Dict[str, Any] # Command options
execution_time: float # Execution durationDescription: Results from integrated security tools.
from safety.models import ToolResult
class ToolResult:
"""Results from integrated security analysis tools."""
tool_name: str # Tool identifier
exit_code: int # Tool exit code
output: str # Tool output
errors: List[str] # Error messages
metadata: Dict[str, Any] # Additional metadataDescription: Custom JSON encoder for Safety-specific data types.
class SafetyEncoder(json.JSONEncoder):
"""Custom JSON encoder for Safety objects."""
def default(self, value: Any) -> Any:
"""
Serialize Safety objects to JSON-compatible formats.
Handles:
- SafetyRequirement objects
- packaging.version.Version objects
- packaging.version.LegacyVersion objects
- Custom data classes
Args:
value: Object to serialize
Returns:
Any: JSON-serializable representation
Raises:
TypeError: If object type is not supported
"""Example Usage:
import json
from safety.models import SafetyEncoder
# Serialize complex Safety data structures
data = {
'vulnerabilities': vulnerability_list, # Contains Vulnerability objects
'packages': package_list, # Contains Package objects
'requirements': requirement_list # Contains SafetyRequirement objects
}
json_output = json.dumps(data, cls=SafetyEncoder, indent=2)These models are imported from safety_schemas.models:
from safety_schemas.models import (
ConfigModel, Ecosystem, FileType, Stage,
PolicyFileModel, DependencyResultModel
)
class ConfigModel:
"""Central configuration for Safety CLI operations."""
telemetry_enabled: bool # Enable telemetry collection
class Ecosystem(Enum):
"""Supported package ecosystems."""
PYTHON = "python"
class FileType(Enum):
"""Supported dependency file types."""
REQUIREMENTS_TXT = "requirements.txt"
PIPFILE = "Pipfile"
PYPROJECT_TOML = "pyproject.toml"
# ... additional file types
class Stage(Enum):
"""Development lifecycle stages."""
DEVELOPMENT = "development"
TESTING = "testing"
STAGING = "staging"
PRODUCTION = "production"from safety.errors import (
SafetyError, SafetyException, InvalidRequirementError,
InvalidCredentialError, NetworkConnectionError
)
class SafetyException(Exception):
"""Base exception for Safety CLI errors."""
def __init__(self, message: str = "Unhandled exception: {info}", info: str = ""):
"""Initialize with formatted message."""
def get_exit_code(self) -> int:
"""Get associated exit code."""
class SafetyError(Exception):
"""Generic Safety CLI error."""
def __init__(self, message: str = "Unhandled Safety error",
error_code: Optional[int] = None):
"""Initialize with message and optional error code."""
class InvalidRequirementError(SafetyError):
"""Error parsing requirement specifications."""
class InvalidCredentialError(SafetyError):
"""Authentication credential validation error."""
class NetworkConnectionError(SafetyError):
"""Network connectivity error."""from safety.models import Vulnerability, Package, SafetyRequirement
# Process scan results
for vulnerability in scan_results.vulnerabilities:
print(f"🚨 {vulnerability.vulnerability_id}")
print(f" Package: {vulnerability.package_name}")
print(f" Version: {vulnerability.analyzed_version}")
print(f" Severity: {vulnerability.severity.cvssv3}")
if vulnerability.fixed_versions:
print(f" Fixed in: {', '.join(vulnerability.fixed_versions[:3])}")
# Check if vulnerability is ignored
if vulnerability.ignored:
print(f" ⚠️ Ignored: {vulnerability.ignored_reason}")from safety.models import Package, is_pinned_requirement
# Analyze package requirements
for package in discovered_packages:
print(f"📦 {package.name} v{package.version}")
# Check for unpinned requirements
if package.has_unpinned_req():
unpinned = list(package.get_unpinned_req())
for req in unpinned:
print(f" ⚠️ Unpinned: {req.name} {req.specifier}")
# Show latest safe version
if package.latest_version_without_known_vulnerabilities:
print(f" ✅ Latest safe: {package.latest_version_without_known_vulnerabilities}")import json
from safety.models import SafetyEncoder
# Create custom report format
report = {
'scan_metadata': {
'timestamp': datetime.now(),
'target': '/path/to/project'
},
'findings': {
'vulnerabilities': vulnerability_list,
'packages': package_list
}
}
# Serialize with Safety encoder
json_report = json.dumps(report, cls=SafetyEncoder, indent=2)
# Save to file
with open('security_report.json', 'w') as f:
f.write(json_report)This comprehensive data models documentation covers all core types and structures used throughout Safety CLI, enabling developers to understand and work with vulnerability data, package information, and security analysis results programmatically.
Install with Tessl CLI
npx tessl i tessl/pypi-safetydocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10