Currently viewing the AI version
Switch to human version

PyPI Publishing Security Guide: AI-Optimized Reference

Critical Context & Threat Landscape

Current State: Malicious package attacks increased 200% in 2025. PyPI faces thousands of malicious packages uploaded monthly. Supply chain attacks are now standard threat vectors.

Major Incidents: December 2024 Ultralytics breach - Bitcoin mining malware injected into popular computer vision package through compromised GitHub Actions workflow.

Authentication & Access Control

API Token Issues

Problem: Legacy passwords disabled in 2024. Common failure: "HTTP 403: Invalid or non-existent authentication information"

Solution:

twine upload dist/* --username __token__ --password pypi-your-actual-token-here

Storage Configuration (~/.pypirc):

[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmcyLongTokenStringHere

Trusted Publishing (Recommended)

Security Level: Eliminates token storage completely
Implementation Time: 5 minutes setup
Authentication Method: GitHub Actions OIDC with PyPI

Setup Process:

  1. PyPI: Account Settings → Publishing → Add pending publisher

    • Repository: username/package
    • Workflow: publish.yml
    • Environment: pypi
  2. GitHub: Create protected environment pypi

    • Settings → Environments → New environment
    • Required reviewers (access control)
    • Prevents unauthorized publishing
  3. Workflow Configuration:

name: Publish to PyPI
on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    environment: pypi
    permissions:
      id-token: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Build package
        run: |
          pip install build
          python -m build
      - uses: pypa/gh-action-pypi-publish@release/v1

Package Structure & Configuration

Modern Package Layout (src/ layout)

Critical Advantage: Prevents testing local code instead of installed package
Failure Prevention: Catches import errors before users encounter them

Structure:

myproject/
├── src/
│   └── mypackage/
│       ├── __init__.py
│       └── core.py
├── tests/
├── pyproject.toml
└── README.md

pyproject.toml Configuration

Status: setup.py is deprecated. pyproject.toml is the only modern standard.

Working Configuration:

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.1.0"
description = "Does stuff without breaking"
authors = [{name = "Your Name", email = "you@domain.com"}]
license = {text = "MIT"}
dependencies = [
    "requests>=2.31.0,<3.0.0",  # Pin major versions
    "click>=8.0.0"
]
requires-python = ">=3.8"

[tool.setuptools.packages.find]
where = ["src"]  # Critical for src layout

Common Failure: Missing build-backend and where configuration causes module import failures.

Security Scanning & Vulnerability Management

Dependency Vulnerabilities

Primary Attack Vector: Most common compromise method
Scanning Tools:

pip install pip-audit
pip-audit  # Scans against PyPA Advisory Database
pip-audit --desc  # Shows vulnerability descriptions
pip-audit --fix   # Attempts to upgrade to safe versions

Workflow Security

Tool: zizmor - detects template injection attacks

pip install zizmor
zizmor .github/workflows/

CI Integration:

- name: Audit dependencies
  run: pip-audit --desc --format=json
- name: Audit workflows
  run: zizmor --format=json .github/workflows/

Version Management & Compatibility

Semantic Versioning Requirements:

  • 1.0.01.0.1: Bug fixes (safe auto-update)
  • 1.0.01.1.0: New features (probably safe)
  • 1.0.02.0.0: Breaking changes (requires human review)

Automation:

pip install bump2version
bump2version patch  # 1.0.0 → 1.0.1
bump2version minor  # 1.0.1 → 1.1.0
bump2version major  # 1.1.0 → 2.0.0

Testing & Quality Assurance

Installation Testing

Critical Step: Test installed package, not local code

# Build and install in isolated environment
python -m build
pip install dist/*.whl --force-reinstall

# Verify installation
python -c "import mypackage; print(mypackage.__version__)"
python -m pytest tests/

Common Hidden Failures:

  • Missing __init__.py files
  • Incorrect package paths in pyproject.toml
  • Missing data files not included in MANIFEST.in
  • Import errors from incorrect module structure

Multi-Version Testing

Tool: tox for comprehensive Python version testing

# tox.ini
[tox]
envlist = py38,py39,py310,py311

[testenv]
deps = pytest
commands = pytest tests/

GitHub Actions Matrix:

strategy:
  matrix:
    python-version: ["3.8", "3.9", "3.10", "3.11"]

Dependency Management

Conflict Resolution

Diagnostic Tool:

pip install pipdeptree
pipdeptree --warn conflict

Best Practices:

  • Loose pinning: requests>=2.28.0,<3.0.0
  • Avoid exact pinning (==) unless specific reason
  • Use dependency groups: [project.optional-dependencies]

Cross-Platform Compatibility

Tool: cibuildwheel for universal wheels
Critical for: C extensions, Apple Silicon compatibility

# .github/workflows/wheels.yml
- name: Build wheels
  uses: pypa/cibuildwheel@v2.16.2
  env:
    CIBW_ARCHS_MACOS: x86_64 arm64  # Both Intel and M1
    CIBW_ARCHS_LINUX: x86_64 aarch64  # Both x64 and ARM

Release Process & Human Controls

Staging Workflow

Required Step: Test on TestPyPI before production

# Upload to TestPyPI
twine upload --repository testpypi dist/*

# Test installation
pip install --index-url https://test.pypi.org/simple/ mypackage

# Production upload only after verification
twine upload dist/*

Human Firewall Requirements

  1. Code review: All changes require PR approval
  2. Protected environments: Only trusted maintainers can publish
  3. Release checklist: Documented manual verification steps
  4. Fresh environment testing: Test wheel installation on clean Python environment

Threat Response & Incident Management

Credential Compromise

Timeline: Leaked credentials get scraped within minutes
Response Protocol:

  1. Immediately revoke leaked credentials
  2. Delete PyPI release (30-minute window before permanent caching)
  3. Generate new credentials
  4. Add leaked keys to .gitignore, use environment variables
  5. Consider compromised systems breached until proven otherwise

Typosquatting Protection

Monitoring:

  • Register common typos early
  • Use PyPI-Scout for similar name monitoring
  • Set up Google Alerts for package name

Response: File PyPI support request immediately with evidence

Package Abandonment

Requirements: Either transfer ownership or mark deprecated
Reason: Abandoned packages become attack targets

Production Package Considerations

High-Impact Package Responsibilities

Indicators:

  • Major company dependencies (check Libraries.io)
  • High download statistics (pypistats)
  • GitHub "Used by" tab shows critical projects

Additional Requirements:

  • More rigorous testing procedures
  • Security-focused development practices
  • Communication channels for security issues
  • Succession planning (bus factor > 1)

Corporate Security Compliance

Common Flags:

  • Network requests
  • File system access
  • Dependencies with CVEs
  • Unknown publisher

Documentation Template:

## Security Information
This package:
- ✅ Makes HTTPS requests to api.example.com only
- ✅ Reads/writes files only in user-specified directories
- ✅ Dependencies scanned with pip-audit (see CI results)
- ✅ Published via GitHub Actions with signed commits
- ❌ Does NOT access sensitive system resources
- ❌ Does NOT make unexpected network connections

Deprecation Management

Breaking Change Timeline

  1. Version 1.5.0: Add deprecation warnings
  2. Version 1.6.0: Increase warnings, update documentation
  3. Version 2.0.0: Remove deprecated features

Implementation:

import warnings

def old_function():
    warnings.warn(
        "old_function() is deprecated, use new_function() instead. "
        "This will be removed in version 2.0.0",
        DeprecationWarning,
        stacklevel=2
    )
    return new_function()

Minimum Timeline: 3 months and 2 minor versions for migration

Publishing Method Comparison

Method Security Risk Maintenance Burden Best Use Case Critical Weakness
Manual twine Token storage vulnerability High - constant token rotation Learning/one-offs Human error prone
GitHub Actions (token) Secret leakage risk Medium - token management Legacy workflows Token compromise
Trusted Publishing Minimal - no stored secrets Low - automatic auth Production packages Requires GitHub/PyPI setup
Local build High - dev machine compromise Very high - bus factor of 1 Emergency fixes only Single point of failure

Essential Toolchain

Security Tools

  • pip-audit: PyPA Advisory Database scanning
  • zizmor: GitHub Actions security analysis
  • safety: Commercial vulnerability database
  • bandit: Python code security analysis

Build Tools

  • build: Modern package builder (replaces setup.py)
  • cibuildwheel: Multi-platform wheel building
  • twine: Package uploading

Testing Tools

  • tox: Multi-version Python testing
  • pytest: Test framework
  • pipdeptree: Dependency conflict analysis

Monitoring Tools

  • pypistats: Download analytics
  • Libraries.io: Reverse dependency tracking
  • PyPI-Scout: Typosquatting monitoring

Resource References

Critical Resources

Security Resources

Development Resources

Useful Links for Further Investigation

Essential Resources for Package Publishing

LinkDescription
PyPI Help & FAQOfficial troubleshooting when shit breaks
Python Packaging User GuideThe canonical reference, not always up to date
Trusted Publishing GuideHow to publish without storing tokens
PyPI Terms of UseLegal requirements for package publishing
pip-auditScan dependencies for known vulnerabilities
zizmorFind GitHub Actions security issues
safetyAlternative vulnerability scanner with commercial DB
BanditFind security issues in your Python code
buildModern package builder, replaces `setup.py`
cibuildwheelBuild wheels for all platforms automatically
PyPI SupportReport malicious packages, security issues, account problems
Stack Overflow pypi tagWhere you'll be debugging at 3am
Python Infrastructure StatusCheck if PyPI is down before panicking
GitHub Actions PyPI PublishOfficial action for Trusted Publishing
Pre-commit hooksCatch issues before they hit CI
toxTest your package across Python versions
noxMore flexible alternative to tox
PyPA GitHub OrganizationWhere Python packaging tools are developed
pyOpenSci Packaging GuideComprehensive guide with modern best practices
PyPI BlogSecurity announcements and policy changes
Sonatype Security ResearchReports on malicious package campaigns
Checkmarx Supply Chain SecurityAnalysis of package repository attacks
TestPyPIStaging environment for testing uploads
pypistatsDownload statistics and usage analytics
Libraries.ioSee what depends on your package
Snyk AdvisorPackage health and security scores
PyPA Sample ProjectReference implementation of modern packaging
Python Package TemplateCookiecutter with CI/CD setup
Hypermodern PythonBest practices guide with working examples
MITRE CVE DatabaseCheck if vulnerabilities have CVE numbers assigned
Python Vulnerability DatabaseBrowse known security vulnerabilities in Python packages
PyPI Security ReportingGuidelines for reporting security issues

Related Tools & Recommendations

compare
Similar content

Uv vs Pip vs Poetry vs Pipenv - Which One Won't Make You Hate Your Life

I spent 6 months dealing with all four of these tools. Here's which ones actually work.

Uv
/compare/uv-pip-poetry-pipenv/performance-comparison
100%
tool
Similar content

Python Dependency Hell - Now With Extra Steps

pip installs random shit, virtualenv breaks randomly, requirements.txt lies to you. Pipenv combines all three tools into one slower tool.

Pipenv
/tool/pipenv/overview
90%
tool
Similar content

Stop Conda From Ruining Your Life

I wasted 6 months debugging conda's bullshit so you don't have to

Conda
/tool/conda/performance-optimization
85%
integration
Recommended

GitHub Actions + Jenkins Security Integration

When Security Wants Scans But Your Pipeline Lives in Jenkins Hell

GitHub Actions
/integration/github-actions-jenkins-security-scanning/devsecops-pipeline-integration
71%
tool
Similar content

uv - Python Package Manager That Actually Works

Discover uv, the high-performance Python package manager. This overview details its core functionality, compares it to pip and Poetry, and shares real-world usa

uv
/tool/uv/overview
65%
tool
Similar content

PyPI - Where Python Packages Live

The place your pip install goes to grab stuff, hosting 665k+ packages that mostly work

PyPI (Python Package Index)
/tool/pypi/overview
62%
review
Similar content

I've Been Testing uv vs pip vs Poetry - Here's What Actually Happens

TL;DR: uv is fast as fuck, Poetry's great for packages, pip still sucks

uv
/review/uv-vs-pip-vs-poetry/performance-analysis
61%
tool
Similar content

uv Performance Optimization and Troubleshooting

uv is fast as hell until it eats all your RAM and crashes your Docker builds. Here's how to tame it.

uv
/tool/uv/performance-optimization
61%
tool
Similar content

Crates.io - Where Rust Packages Live

The official Rust package registry that works with cargo add and doesn't randomly break your builds like npm

Crates.io
/tool/crates-io/overview
54%
integration
Recommended

How We Stopped Breaking Production Every Week

Multi-Account DevOps with Terraform and GitOps - What Actually Works

Terraform
/integration/terraform-aws-multiaccount-gitops/devops-pipeline-automation
43%
howto
Recommended

Stop MLflow from Murdering Your Database Every Time Someone Logs an Experiment

Deploy MLflow tracking that survives more than one data scientist

MLflow
/howto/setup-mlops-pipeline-mlflow-kubernetes/complete-setup-guide
43%
tool
Recommended

Conda - когда pip снова все сломал

Пакетный менеджер, который реально работает в production

Conda
/ru:tool/conda/overview
40%
tool
Recommended

Conda - The Package Manager That Actually Solves Dependency Hell

Stop compiling shit from source and wrestling with Python versions - conda handles the messy bits so you don't have to

Conda
/tool/conda/overview
40%
tool
Recommended

Poetry — dependency manager для Python, который не врёт

Забудь про requirements.txt, который никогда не работает как надо, и virtualenv, который ты постоянно забываешь активировать

Poetry
/ru:tool/poetry/overview
40%
tool
Recommended

uv Docker Production Deployment - Troubleshooting & Best Practices

integrates with uv

uv
/tool/uv/docker-production-guide
40%
alternatives
Recommended

GitHub Actions is Fine for Open Source Projects, But Try Explaining to an Auditor Why Your CI/CD Platform Was Built for Hobby Projects

integrates with GitHub Actions

GitHub Actions
/alternatives/github-actions/enterprise-governance-alternatives
36%
integration
Recommended

GitHub Actions + Docker + ECS: Stop SSH-ing Into Servers Like It's 2015

Deploy your app without losing your mind or your weekend

GitHub Actions
/integration/github-actions-docker-aws-ecs/ci-cd-pipeline-automation
36%
tool
Similar content

Pip - Python's Package Installer That Usually Works

Install Python packages from PyPI. Works great until dependencies conflict, then you'll question your career choices.

pip
/tool/pip/overview
36%
tool
Recommended

Anaconda AI Platform - Enterprise Python Environment That Actually Works

When conda conflicts drive you insane and your company has 200+ employees, this is what you pay for

Anaconda AI Platform
/tool/anaconda-ai-platform/overview
36%
tool
Similar content

uv Advanced Configuration for Enterprise Environments

Corporate networks fucking hate uv. Here's how to make it work anyway.

uv
/tool/uv/advanced-configuration
32%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization