Package Integrity Verification#
The CPEX framework includes built-in SHA256 hash verification for packages, providing an additional security layer beyond pip’s built-in checks.
Overview#
The framework provides integrity verification for different installation sources:
PyPI Packages#
When installing plugins from PyPI, the framework automatically:
- Fetches expected SHA256 hashes from PyPI’s JSON API
- Downloads the package file
- Computes the SHA256 hash of the downloaded file
- Compares the computed hash against the expected hash
- Aborts installation if hashes don’t match
Git and Monorepo Packages#
When installing from Git repositories or monorepos, the framework:
- Downloads the package archive
- Computes the SHA256 hash of the downloaded file
- Logs the hash for future reference and verification
- Allows manual verification against known-good hashes
This protects against:
- Tampered packages: Detects if a package has been modified in transit
- Corrupted downloads: Identifies incomplete or corrupted downloads
- Supply chain attacks: Verifies package authenticity
Configuration#
Environment Variables#
Control integrity verification behavior using environment variables:
# Enable/disable integrity verification (default: true)
export PLUGINS_VERIFY_PACKAGE_INTEGRITY=true
# Strict mode: fail if hashes unavailable (default: false)
export PLUGINS_STRICT_INTEGRITY_MODE=falseConfiguration File#
Add to your .env file:
# Package Integrity Verification
PLUGINS_VERIFY_PACKAGE_INTEGRITY=true
PLUGINS_STRICT_INTEGRITY_MODE=falseVerification Modes#
Standard Mode (Default)#
PLUGINS_VERIFY_PACKAGE_INTEGRITY=true
PLUGINS_STRICT_INTEGRITY_MODE=falseBehavior:
- Verifies packages when hashes are available
- Warns but continues if hashes are unavailable
- Fails immediately on hash mismatch
Use case: Recommended for most deployments. Provides security without breaking installations for packages that don’t publish hashes.
Strict Mode#
PLUGINS_VERIFY_PACKAGE_INTEGRITY=true
PLUGINS_STRICT_INTEGRITY_MODE=trueBehavior:
- Requires hashes for all packages
- Fails installation if hashes are unavailable
- Fails immediately on hash mismatch
Use case: High-security environments where all packages must be verifiable.
Disabled Mode#
PLUGINS_VERIFY_PACKAGE_INTEGRITY=falseBehavior:
- Skips hash verification entirely
- Relies only on pip’s built-in checks
Use case: Development environments or when troubleshooting installation issues.
Usage Examples#
Installing with Verification (Default)#
PyPI Installation:
# Verification is enabled by default
cpex plugin install --type pypi my-plugin
# Output shows verification status:
# Package integrity verification: enabled
# Fetching package hashes from PyPI for my-plugin
# Retrieved hashes for 2 distribution files
# Verifying integrity of my-plugin-1.0.0.tar.gz
# ✓ Integrity verification passed for my-pluginGit Installation:
# Hash is computed and logged for future verification
cpex plugin install --type git "MyPlugin @ git+https://github.com/user/repo.git"
# Output shows:
# Package integrity verification: enabled (hash will be computed and logged)
# Package integrity hash for MyPlugin (MyPlugin-1.0.0.tar.gz): SHA256=abc123def456...
# Store this hash for future verification or to detect tamperingMonorepo Installation:
# Hash is computed and logged
cpex plugin install --type monorepo my-plugin
# Output shows:
# Package integrity hash for my-plugin (my-plugin-1.0.0.tar.gz): SHA256=abc123def456...
# Store this hash for future verification or to detect tamperingInstalling with Verification Disabled#
# Temporarily disable verification
export PLUGINS_VERIFY_PACKAGE_INTEGRITY=false
cpex plugin install --type pypi my-plugin
# Output shows:
# Package integrity verification: disabledInstalling from Test PyPI#
# Verification works with test.pypi.org too
cpex plugin install --type test-pypi my-test-pluginError Handling#
Hash Mismatch#
If a downloaded package’s hash doesn’t match the expected hash:
ERROR: Integrity verification failed for my-plugin
Expected: abc123def456...
Actual: 789ghi012jkl...
File: /tmp/cpex_plugin_my-plugin_xyz/my-plugin-1.0.0.tar.gz
IntegrityVerificationError: Integrity verification failed for my-pluginResolution:
- Retry the installation (may be a transient network issue)
- Check if PyPI is experiencing issues
- Report to package maintainer if problem persists
Hash Unavailable#
If PyPI doesn’t provide hashes for a package:
Standard Mode:
WARNING: No hashes available from PyPI for my-plugin
WARNING: No matching hash found for my-plugin-1.0.0.tar.gz. Proceeding without verification.Installation continues.
Strict Mode:
ERROR: No hashes available from PyPI for my-plugin
RuntimeError: Package hashes required in strict mode but not availableInstallation fails.
Network Error Fetching Hashes#
If the PyPI API is unreachable:
WARNING: Failed to fetch hashes from PyPI: Connection timeout. Proceeding without verification.Installation continues to avoid breaking deployments due to temporary network issues.
Security Best Practices#
Production Deployments#
- Enable verification (default setting)
- Monitor logs for verification warnings
- Consider strict mode for critical environments
- Use private PyPI mirrors with known-good packages
Development Environments#
- Keep verification enabled to catch issues early
- Use standard mode for flexibility
- Disable only when troubleshooting specific issues
CI/CD Pipelines#
- Enable verification in all pipelines
- Use strict mode for production deployments
- Cache verified packages to reduce API calls
- Fail builds on verification errors
Technical Details#
Hash Algorithm#
- Algorithm: SHA256 (256-bit)
- Source: PyPI JSON API (
/pypi/{package}/json) - Format: Hexadecimal string (64 characters)
Verification Process#
# 1. Fetch expected hashes from PyPI
hashes = fetch_pypi_package_hashes("my-plugin", "1.0.0")
# Returns: {"my-plugin-1.0.0.tar.gz": {"sha256": "abc123...", "url": "..."}}
# 2. Download package
package_file = download_package("my-plugin==1.0.0")
# 3. Compute actual hash
actual_hash = compute_file_hash(package_file)
# 4. Verify
if actual_hash != expected_hash:
raise IntegrityVerificationError(...)Performance Impact#
- API Call: ~100-500ms to fetch hashes from PyPI
- Hash Computation: ~10-50ms per MB of package size
- Total Overhead: Typically <1 second per package
The overhead is minimal compared to download time and provides significant security benefits.
Troubleshooting#
Verification Always Fails#
Symptoms: Every package fails verification with hash mismatch.
Possible Causes:
- Corporate proxy modifying downloads
- Antivirus scanning altering files
- Disk corruption
Solutions:
- Check proxy configuration
- Temporarily disable antivirus
- Run disk check utility
Verification Warnings for All Packages#
Symptoms: “No hashes available” warning for every package.
Possible Causes:
- Network blocking PyPI API
- Firewall rules
- PyPI API outage
Solutions:
- Check network connectivity to
pypi.org - Review firewall rules
- Check PyPI status page
Slow Installations#
Symptoms: Package installations take much longer than expected.
Possible Causes:
- Slow network to PyPI API
- Large packages taking time to hash
Solutions:
- Use a PyPI mirror closer to your location
- Consider caching verified packages
- This is normal for very large packages (>100MB)
API Reference#
See cpex.tools.integrity for detailed API documentation.
Related Documentation#
- CLI Reference - Command-line usage
- Configuration - General configuration options
- Security Best Practices - Comprehensive security guide
Changelog#
Version 0.1.0rc1#
- Initial implementation of SHA256 hash verification
- Support for PyPI and Test PyPI
- Configurable verification modes (standard/strict/disabled)
- Comprehensive error handling and logging