Skip to content

Commit 3d9b52c

Browse files
authored
Merge pull request #1 from mapped/fix-cve-2025-69872
Fix CVE-2025-69872: restrict pickle deserialization to safe types
2 parents ebfa37c + 1ff09f5 commit 3d9b52c

9 files changed

Lines changed: 651 additions & 127 deletions

File tree

.github/workflows/ci.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
6+
env:
7+
BASE_VERSION: '6.0.0'
8+
9+
jobs:
10+
checks:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
max-parallel: 8
14+
matrix:
15+
check: [bluecheck, doc8, docs, flake8, isortcheck, mypy, pylint, rstcheck]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.11'
23+
- name: Install tox
24+
run: pip install tox
25+
- name: Run checks
26+
run: tox -e ${{ matrix.check }}
27+
28+
tests:
29+
needs: checks
30+
runs-on: ubuntu-latest
31+
strategy:
32+
max-parallel: 4
33+
matrix:
34+
python-version: ['3.9', '3.10', '3.11', '3.12']
35+
36+
steps:
37+
- uses: actions/checkout@v4
38+
- name: Set up Python ${{ matrix.python-version }}
39+
uses: actions/setup-python@v5
40+
with:
41+
python-version: ${{ matrix.python-version }}
42+
- name: Install tox
43+
run: pip install tox
44+
- name: Run tests
45+
run: tox -e py
46+
47+
publish:
48+
needs: tests
49+
if: github.ref == 'refs/heads/main'
50+
runs-on: ubuntu-latest
51+
permissions:
52+
contents: read
53+
id-token: write
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Establish Versioning, Tags, and Labels
59+
id: vtl
60+
uses: mapped/action-vtl@latest
61+
with:
62+
baseVersion: ${{ env.BASE_VERSION }}
63+
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
64+
65+
- name: Set up Python
66+
uses: actions/setup-python@v5
67+
with:
68+
python-version: '3.11'
69+
70+
- name: Update package version
71+
run: |
72+
sed -i "s/__version__ = '.*'/__version__ = '${{ steps.vtl.outputs.ver_semVerNoMeta }}'/" diskcache/__init__.py
73+
74+
- name: Build package
75+
run: |
76+
pip install build
77+
python -m build
78+
79+
- name: Publish to PyPI
80+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/integration.yml

Lines changed: 0 additions & 52 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 0 additions & 30 deletions
This file was deleted.

.pylintrc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ source-roots=
101101

102102
# When enabled, pylint would attempt to guess common misconfiguration and emit
103103
# user-friendly hints instead of false-positive error messages.
104-
suggestion-mode=yes
104+
# suggestion-mode removed (pylint 4.x dropped this option)
105105

106106
# Allow loading of arbitrary C extensions. Extensions are imported into the
107107
# active Python interpreter and may run arbitrary code.
@@ -433,7 +433,9 @@ disable=raw-checker-failed,
433433
no-member,
434434
no-else-return,
435435
no-else-raise,
436-
inconsistent-return-statements
436+
inconsistent-return-statements,
437+
too-many-lines,
438+
too-many-positional-arguments
437439

438440
# Enable the message, report, category or checker with the given id(s). You can
439441
# either give multiple identifier separated by comma (,) or put this option

CHANGES.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Changes
2+
=======
3+
4+
6.0.0 (NEXT)
5+
-------------
6+
7+
**Breaking Changes**
8+
9+
* Pickle deserialization is now restricted to safe built-in types only.
10+
This mitigates CVE-2025-69872, which allowed arbitrary code execution
11+
when an attacker with write access to the cache directory injected a
12+
crafted pickle payload.
13+
14+
The following types are permitted during deserialization:
15+
16+
- Python builtins: ``int``, ``float``, ``str``, ``bytes``, ``bytearray``,
17+
``list``, ``dict``, ``tuple``, ``set``, ``frozenset``, ``complex``,
18+
``range``, ``slice``, ``object``, ``bool``, ``None``
19+
- ``collections``: ``OrderedDict``, ``defaultdict``, ``deque``
20+
- ``datetime``: ``date``, ``datetime``, ``time``, ``timedelta``,
21+
``timezone``
22+
- ``decimal.Decimal``
23+
- ``fractions.Fraction``
24+
- ``uuid.UUID``
25+
26+
All other types will raise ``UnpicklingError`` on read.
27+
28+
* There is no opt-out mechanism. Users who need to cache custom types have
29+
two migration paths:
30+
31+
1. Use ``JSONDisk`` for JSON-serializable data::
32+
33+
cache = Cache('/tmp/my-cache', disk=JSONDisk)
34+
35+
2. Subclass ``Disk`` and override ``get()`` and ``fetch()`` with a custom
36+
serialization strategy appropriate for your data.
37+
38+
**New Features**
39+
40+
* Added ``SafeUnpickler`` class for restricted pickle deserialization.
41+
* Added ``UnpicklingError`` exception raised when a disallowed type is
42+
encountered during deserialization.
43+
44+
**Internal**
45+
46+
* ``SAFE_PICKLE_CLASSES`` uses ``frozenset`` values to prevent runtime
47+
modification.
48+
49+
5.6.3 (2023-08-31)
50+
-------------------
51+
52+
* Previous release (see git history for details).

diskcache/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
Disk,
1515
EmptyDirWarning,
1616
JSONDisk,
17+
SafeUnpickler,
1718
Timeout,
1819
UnknownFileWarning,
20+
UnpicklingError,
1921
)
2022
from .fanout import FanoutCache
2123
from .persistent import Deque, Index
@@ -44,9 +46,11 @@
4446
'JSONDisk',
4547
'Lock',
4648
'RLock',
49+
'SafeUnpickler',
4750
'Timeout',
4851
'UNKNOWN',
4952
'UnknownFileWarning',
53+
'UnpicklingError',
5054
'barrier',
5155
'memoize_stampede',
5256
'throttle',
@@ -60,9 +64,9 @@
6064
# Django not installed or not setup so ignore.
6165
pass
6266

63-
__title__ = 'diskcache'
64-
__version__ = '5.6.3'
65-
__build__ = 0x050603
67+
__title__ = 'mapped-diskcache'
68+
__version__ = '6.0.0'
69+
__build__ = 0x060000
6670
__author__ = 'Grant Jenks'
6771
__license__ = 'Apache 2.0'
6872
__copyright__ = 'Copyright 2016-2023 Grant Jenks'

0 commit comments

Comments
 (0)