Files
Rodin 8a94a08511 Add supply-chain, deserialization, cryptography, error-handling patterns
Now covers all OWASP Top 10:2025 categories:
- A03: supply-chain.md (SolarWinds, Bybit, npm worm examples)
- A04: cryptography.md (algorithm recommendations, key management)
- A08: deserialization.md (pickle, yaml, language-specific risks)
- A10: error-handling.md (fail closed, error messages)
2026-05-10 22:48:39 -07:00

3.5 KiB

Supply Chain Security

Rule

Verify integrity of all dependencies. Generate SBOMs. Monitor for vulnerabilities.

Source: OWASP Top 10 2025 - A03 Software Supply Chain Failures

Attack Examples

  • SolarWinds (2019): Compromised build system, 18,000 orgs affected
  • Bybit (2025): Supply chain attack in wallet software, $1.5B theft
  • Shai-Hulud (2025): Self-propagating npm worm, 500+ packages

Correct Pattern

# Generate and maintain SBOM
import subprocess
import json
import hashlib

def generate_sbom(project_path: str) -> dict:
    """Generate Software Bill of Materials."""
    # Use CycloneDX or SPDX format
    result = subprocess.run(
        ["cyclonedx-py", "poetry", "-o", "sbom.json"],
        cwd=project_path,
        capture_output=True
    )
    with open(f"{project_path}/sbom.json") as f:
        return json.load(f)

# Verify package integrity
def verify_package(package_path: str, expected_hash: str) -> bool:
    """Verify package hash before installation."""
    with open(package_path, "rb") as f:
        actual_hash = hashlib.sha256(f.read()).hexdigest()
    return actual_hash == expected_hash

# Pin dependencies with hashes
# requirements.txt with hashes:
# requests==2.28.0 --hash=sha256:abc123...

# Lock file example (poetry.lock, package-lock.json)
def verify_lockfile_integrity(lockfile_path: str) -> bool:
    """Ensure lockfile hasn't been tampered with."""
    # Compare against known-good version in version control
    ...

Incorrect Pattern

# Wrong: no version pinning
# requirements.txt
# requests
# flask

# Wrong: pulling from arbitrary sources
pip install https://sketchy-site.com/package.tar.gz

# Wrong: no integrity verification
def install_dependency(name):
    os.system(f"pip install {name}")  # No hash check

# Wrong: auto-updating without verification
def auto_update():
    os.system("pip install --upgrade -r requirements.txt")

Dependency Scanning

# Integrate vulnerability scanning in CI
def scan_dependencies() -> list[dict]:
    """Scan for known vulnerabilities."""
    # Use tools like:
    # - OWASP Dependency-Check
    # - Snyk
    # - GitHub Dependabot
    # - OSV (Open Source Vulnerabilities)
    
    result = subprocess.run(
        ["pip-audit", "--format=json"],
        capture_output=True
    )
    return json.loads(result.stdout)

def block_on_critical(vulnerabilities: list[dict]) -> bool:
    """Fail CI on critical vulnerabilities."""
    critical = [v for v in vulnerabilities if v["severity"] == "CRITICAL"]
    if critical:
        raise SecurityError(f"Critical vulnerabilities found: {critical}")
    return True

CI/CD Hardening

# Verify CI/CD pipeline integrity
PIPELINE_REQUIREMENTS = {
    "mfa_required": True,
    "branch_protection": True,
    "signed_commits": True,
    "code_review_required": True,
    "secrets_scanning": True,
}

def audit_pipeline(config: dict) -> list[str]:
    """Audit CI/CD configuration."""
    issues = []
    for requirement, expected in PIPELINE_REQUIREMENTS.items():
        if config.get(requirement) != expected:
            issues.append(f"Missing: {requirement}")
    return issues

Edge Cases

  • Transitive dependencies (deps of deps) can be vulnerable
  • Typosquatting attacks (similar package names)
  • Dependency confusion (internal vs public package names)
  • Compromised maintainer accounts
  • Post-install scripts can execute arbitrary code
  • IDE extensions and dev tools are part of supply chain