You are almost certainly running Python 3.10 somewhere in your stack right now. Python 3.10 reaches end of life on October 31, 2026, after which the CPython core team ships zero security patches. It hides in Lambda runtimes,
python:3.10-slimbase images pinned two years ago, GitHub Actions runners pulling the system Python, and Ansible control nodes nobody has touched since the original provisioning. Every CVE disclosed after October 31 accumulates unpaid, no fix, no backport, no upstream acknowledgement. Python 3.11 reaches EOL the same day, October 31, 2026 is the first time two major Python versions have gone end-of-life simultaneously, leaving a significant portion of the Python ecosystem unpatched at once.
Source: https://devguide.python.org/versions/
What Python 3.10 EOL Actually Means
Python 3.10 EOL means the CPython core team stops all maintenance activity on the 3.10 branch. No security patches, no bug fixes, no backports.
Python operates on a predictable five-year support model per PEP 619 and the general Python Developer’s Guide lifecycle documentation. Each release moves through three phases:
| Phase | Duration | What Changes |
| Feature | ~18 months from release | New features accepted |
| Security-fix only | ~3.5 years | Only security patches backported |
| End of Life | After October 31, 2026 | No patches of any kind |
Source: https://devguide.python.org/versions/
Python 3.10.0 shipped on October 4, 2021. It entered security-fix-only mode on October 3, 2023. From November 1, 2026 onwards, any vulnerability discovered in Python 3.10 — in ssl, urllib, xmlrpc, tarfile, or the interpreter itself, receives no upstream response.
“Still runs” and “permanently unpatched” are not the same operational posture. A process that accepts network input, parses untrusted files, or handles authentication tokens running on an unpatched interpreter is a liability with an open-ended CVE horizon.
No CVEs have been publicly disclosed against Python 3.10 for the post-EOL window as of June 2026. This does not mean no vulnerabilities exist, it means none have been documented against an EOL version yet. The pattern from Python 3.6 and 3.7 EOL cycles is that CVE reporters stop tagging older versions explicitly, which means your scanner stops flagging them, not that the exposure disappears.
Source: https://peps.python.org/pep-0619/
Python 3.10 Is Hiding in Your Stack — Where to Find It
Inventory before you migrate. Python 3.10 surfaces in more places than most teams track.
Docker and Container Images
Any image built FROM python:3.10 or FROM python:3.10-slim is the obvious case. The less obvious case: FROM ubuntu:22.04 ships Python 3.10 as the system Python, and any image built on top of it inherits that runtime whether the Dockerfile declares it or not.
# Scan all running containers for Python 3.10
docker ps -q | xargs -I{} docker exec {} python3 --version 2>/dev/null | grep "3\.10"
# Scan all local images for python:3.10 base
docker inspect $(docker images -q) \
--format '{{.RepoTags}} {{.Config.Image}}' 2>/dev/null | grep "3\.10"
# Use Trivy to report Python runtime version in all local images
trivy image --list-all-pkgs python:3.10-slim 2>/dev/null | grep "python"
# Grep Dockerfiles in your repo tree
grep -r "FROM python:3\.10" . --include="Dockerfile*"
grep -r "FROM ubuntu:22\.04" . --include="Dockerfile*" # system python is 3.10
CI/CD Pipelines
GitHub Actions, GitLab CI, and CircleCI all allow pinning a Python version either explicitly or by inheriting the runner’s system Python.
# GitHub Actions — find pinned 3.10 in workflow files
grep -r "python-version.*3\.10" .github/workflows/
grep -r "python-version.*3\.10" .github/
# GitLab CI
grep -r "PYTHON_VERSION.*3\.10" .gitlab-ci.yml
grep -r "image: python:3\.10" .gitlab-ci.yml
# CircleCI
grep -r "3\.10" .circleci/config.yml
# Tox configurations
grep -r "py310" tox.ini setup.cfg pyproject.toml
If any matrix entry reads python-version: "3.10", that pipeline will break the day your test suite or build toolchain drops 3.10 support and it will happen silently until a job fails.
AWS Lambda Runtimes
Lambda function runtime declarations are not always visible from the repo. You need to query the control plane directly.
# List all Lambda functions using python3.10 runtime across all regions
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "=== $region ==="
aws lambda list-functions \
--region "$region" \
--query 'Functions[?Runtime==`python3.10`].[FunctionName,Runtime,LastModified]' \
--output table 2>/dev/null
done
# Single region scan
aws lambda list-functions \
--region us-east-1 \
--query 'Functions[?Runtime==`python3.10`].[FunctionName,LastModified]' \
--output table
System Python on EC2, ECS Task Definitions, and Kubernetes Pods
# EC2 — run via SSM at scale
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--targets "Key=tag:Environment,Values=production" \
--parameters 'commands=["python3 --version"]' \
--query 'Command.CommandId' \
--output text
# Kubernetes — check all running pods
kubectl get pods -A -o json | jq -r '.items[].spec.containers[].image' | \
grep -E "python:3\.10|3\.10-slim|3\.10-alpine"
# Find Python version inside a running pod
kubectl exec -n <namespace> <pod-name> -- python3 --version
AWS Lambda Deprecation Timeline
AWS manages its own Lambda runtime deprecation schedule independently of upstream CPython EOL. AWS has consistently deprecated Lambda runtimes several months after upstream EOL and blocks new deployments before blocking existing function invocations.
| Provider | Runtime ID | Status | New Deployment Block | Invocation Block |
| AWS Lambda | python3.10 | Supported | [VERIFY: check AWS docs before publishing] | [VERIFY: check AWS docs before publishing] |
| AWS Lambda | python3.9 | Deprecated | Blocked | [VERIFY: invocation block date] |
| AWS Lambda | python3.8 | Deprecated | Blocked | Blocked |
Source: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
⚠️ AWS Lambda runtime deprecation for
python3.10has not been officially announced as of June 2026. Monitor the Lambda runtimes page | AWS typically provides 60–90 days notice before blocking new deployments.
The operational risk is not the AWS deprecation block date. The risk is the window between October 31, 2026 and whenever AWS eventually forces migration during which your Lambda functions are running a runtime with accumulating unpatched CVEs, and your scanner may not flag them because they are still technically “supported” by AWS.
Migration Path | Python 3.10 to Python 3.12
Python 3.12 is the recommended migration target. It is the current stable release with full security support through October 2028 per devguide.python.org/versions. Python 3.11 reaches EOL October 2027, migrating to it now means another migration in 16 months.
Source: https://devguide.python.org/versions/
Breaking Changes You Must Test
These are verified breaking changes between Python 3.10 and Python 3.12 sourced from official What’s New documentation:
| Change | 3.10 Behaviour | 3.12 Behaviour | Source |
distutils removed | Available (deprecated) | Removed entirely | What’s New 3.12 |
asynchat, asyncore, imp | Deprecated | Removed entirely | What’s New 3.12 |
pkgutil.find_loader() | Available | Removed (use importlib) | What’s New 3.12 |
unittest.TestCase.failUnlessEqual | Available | Removed | What’s New 3.12 |
| f-string parsing rewritten | Limited nesting, no \ inside expressions | Full nesting, \ allowed inside expressions | What’s New 3.12 |
sys.last_type/value/traceback | Set on uncaught exception | Deprecated in favour of sys.last_exc | What’s New 3.12 |
typing.get_type_hints() with include_extras=False | Returns extra metadata | Strips Annotated wrappers | What’s New 3.12 |
Source: https://docs.python.org/3/whatsnew/3.12.html
The distutils removal is the highest-impact change for DevOps toolchains. Any setup.py or build script importing distutils directly fails hard on 3.12. Audit with:
grep -r "from distutils" . --include="*.py"
grep -r "import distutils" . --include="*.py"
Dockerfile Migration
# BEFORE — Python 3.10
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
# AFTER — Python 3.12
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
For Ubuntu-based images where 3.10 is the system Python:
# BEFORE — implicit Python 3.10 via Ubuntu 22.04
FROM ubuntu:22.04
# AFTER — Ubuntu 24.04 ships Python 3.12 as system Python
FROM ubuntu:24.04
Lambda Runtime Migration
# Update a single function
aws lambda update-function-configuration \
--function-name my-function \
--runtime python3.12
# Bulk update all python3.10 functions in a region
aws lambda list-functions \
--region us-east-1 \
--query 'Functions[?Runtime==`python3.10`].FunctionName' \
--output text | tr '\t' '\n' | while read fn; do
echo "Updating $fn"
aws lambda update-function-configuration \
--function-name "$fn" \
--runtime python3.12
done
Local Validation Before Promoting
# Install Python 3.12 via pyenv
pyenv install 3.12
pyenv local 3.12
# Create fresh venv and reinstall dependencies
python3.12 -m venv .venv-312
source .venv-312/bin/activate
pip install -r requirements.txt
# Run your test suite against 3.12
pytest --tb=short -q
# Check for deprecated import patterns
python3.12 -W error -c "import your_module"
# Verify no distutils usage
python3.12 -c "from distutils.core import setup" 2>&1
# Expected on 3.12: ModuleNotFoundError — means you have a dependency to fix
Compliance Implications
Running Python 3.10 after October 31, 2026 is not automatically a compliance violation but it creates a documentation burden that auditors will pursue.
SOC 2 Type II: CC6.1 (Logical and Physical Access Controls) and CC7.1 (System Operations) both require that you demonstrate vulnerability management processes. An auditor finding production workloads on an unpatched runtime with no remediation timeline will raise a finding. The acceptable documentation paths are: (1) active migration with a tracked completion date, (2) a compensating controls statement with specific mitigations, or (3) a commercial extended support agreement.
PCI-DSS v4.0: Requirement 6.3.3 mandates all system components are protected from known vulnerabilities by installing applicable security patches. Post-EOL runtimes handling cardholder data or residing on networks that touch card data are non-compliant without an approved exception. PCI DSS does not accept “the vendor no longer provides patches” as a mitigation, it accepts compensating controls with equivalent security posture documented and approved by your QSA.
ISO 27001:2022: Annex A 8.8 (Management of Technical Vulnerabilities) requires you to identify, evaluate, and address technical vulnerabilities in a timely manner. An unpatched EOL runtime sits permanently in your vulnerability register with no remediation path. Internal auditors and certification bodies increasingly flag EOL runtimes as systemic control failures rather than individual findings.
The documentation requirement is consistent across all three frameworks: migration plan with target date, OR risk acceptance signed by asset owner, OR commercial extended support contract. “We haven’t got around to it” is none of those three.
FAQ
When does Python 3.10 reach end of life?
Python 3.10 reaches end of life on October 31, 2026. After that date, the CPython core team will not release any further patches, no security fixes, no bug fixes, no backports. This is documented in PEP 619 at https://peps.python.org/pep-0619/.
What happens to AWS Lambda functions using the python3.10 runtime after EOL?
AWS Lambda functions using python3.10 will continue to invoke after the upstream CPython EOL date, AWS manages its own deprecation schedule separately. However, the runtime will accumulate unpatched CVEs with no upstream remediation available. AWS will eventually block new deployments to python3.10 and later block invocations, on a timeline they have not yet published as of June 2026.
How do I find Python 3.10 in my Kubernetes cluster?
Run kubectl get pods -A -o json | jq -r '.items[].spec.containers[].image' | grep "3\.10" to find container images explicitly tagged with 3.10. For images based on ubuntu:22.04 where the version is implicit, exec into representative pods and run python3 --version. Trivy’s runtime scanning can also enumerate Python versions across a cluster.
Which Python version should I migrate to from Python 3.10?
Migrate to Python 3.12. It has full security support through October 2028, giving you two years before the next migration cycle. Python 3.11 is also supported but reaches EOL in October 2027, making it a short-runway target. Python 3.13 is available but carries more migration risk for established codebases — 3.12 is the stable choice.
Is Python 3.10 safe to run after October 31, 2026?
No unpatched CVEs exist against Python 3.10 specifically for the post-EOL period as of June 2026, because the EOL date has not yet passed. After October 31, 2026, any vulnerability discovered in CPython 3.10 will not receive a patch. Whether that represents acceptable risk depends on your threat model, network exposure, and compliance requirements — not on whether a CVE has been published yet.
Does distutils removal in Python 3.12 affect my deployment toolchain?
Yes, if anything in your dependency tree imports distutils directly. The module was deprecated in 3.10 and removed entirely in 3.12. Run grep -r "import distutils" . --include="*.py" and grep -r "from distutils" . --include="*.py" across your codebase and all vendored dependencies. Most modern packages have already migrated to setuptools, but older pinned dependencies may not have.
October 31, 2026 Is the Deadline That Actually Matters
AWS will give you a grace period. Your scanner will keep showing a green runtime status until AWS formally deprecates the Lambda runtime. None of that changes the upstream fact: zero patches after October 31, 2026.
The migration window is 139 days from publication. That is enough time to do this properly — inventory, test, stage, deploy — if you start the inventory this week rather than in September.
Migration Checklist
- [ ] Run Lambda function scan across all regions and document every
python3.10function - [ ] Grep all Dockerfile and docker-compose files for
python:3.10andubuntu:22.04base images - [ ] Scan CI/CD pipeline configs (
.github/workflows/,.gitlab-ci.yml,tox.ini,pyproject.toml) for Python 3.10 matrix entries - [ ] Audit all
setup.pyand build scripts fordistutilsimports - [ ] Run full test suite against Python 3.12 in a clean venv — document failures
- [ ] Update
python-versionconstraints inpyproject.tomlorsetup.cfg - [ ] Build and test updated Docker images locally before pushing
- [ ] Deploy to staging environment and validate with integration tests
- [ ] Update Lambda functions to
python3.12runtime — test with Lambda-specific test events - [ ] Update CI matrix to remove
3.10entries - [ ] Update any EC2 AMIs or ECS task definition base images
- [ ] Document migration completion date for SOC 2 / PCI-DSS / ISO 27001 audit trail
- [ ] Remove Python 3.10 from local pyenv installations to prevent accidental regression
Get notified before the next EOL deadline hits your stack. The Deprecation Digest covers upcoming EOL dates, CVE intersections, and migration guides, every Tuesday. Subscribe free →
Sources and Citations
Python 3.10 Release Schedule (PEP 619): https://peps.python.org/pep-0619/
Python Developer’s Guide — Version Lifecycle and Support Windows: https://devguide.python.org/versions/
What’s New in Python 3.12 — Official Changelog and Breaking Changes: https://docs.python.org/3/whatsnew/3.12.html
What’s New in Python 3.11 — Official Changelog: https://docs.python.org/3/whatsnew/3.11.html
AWS Lambda Supported Runtimes — Official Runtime Deprecation Schedule: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
endoflife.date — Python Version Matrix with Official EOL Dates: https://endoflife.date/python
Python 3.12 distutils Removal — Official Documentation: https://docs.python.org/3.12/whatsnew/3.12.html#removed
PEP 632 — Deprecate distutils module:https://peps.python.org/pep-0632/
