CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-safety

Scan dependencies for known vulnerabilities and licenses.

Overall
score

61%

Overview
Eval results
Files

models.mddocs/

Data Models and Types

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.

Core Data Models

Import Statements { .api }

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
)

Vulnerability Models

Vulnerability Class { .api }

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()

CVE Class { .api }

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"

Severity Class { .api }

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
        """

Package and Requirement Models

Package Class { .api }

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 URL

Methods:

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}")

SafetyRequirement Class { .api }

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 location

Methods:

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
}

RequirementFile { .api }

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}")

Remediation and Fix Models

Fix Class { .api }

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 URL

Example 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}")

Remediation Class { .api }

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
        """

Utility Models and Types

Announcement Class { .api }

Description: Platform announcements and notices.

class Announcement(NamedTuple):
    """Platform announcement information."""
    
    type: str                                   # Announcement type
    message: str                                # Announcement content

DictConverter Base Class { .api }

Description: 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
        """

SafetyCLI Model { .api }

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 duration

ToolResult Model { .api }

Description: 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 metadata

Serialization and Encoding

SafetyEncoder { .api }

Description: 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)

Configuration Models

Schema Models { .api }

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"

Error and Exception Models

Core Exception Classes { .api }

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."""

Usage Examples

Working with Vulnerabilities

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}")

Package Analysis

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}")

Custom Serialization

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-safety

docs

authentication.md

cli-commands.md

configuration.md

errors.md

formatters.md

index.md

models.md

programmatic.md

scanning.md

tile.json