Repository navigation
Description
What happens
DiskCache opens its index, <cache_dir>/index, with diskcache's default Disk (cache.py L170-L173). That disk keeps each entry as a pickle and loads it with pickle.load, so the folder's contents decide what runs inside the IceFrame process. The index is read in three places once set_query_cache(DiskCache(...)) is in effect:
DiskCache.get(L191-L200), on everyQueryBuilder.cache(ttl).execute()(query.pyL282)DiskCache.put(L211), which loads the old entry for a query before it writes the new oneDiskCache.invalidate(L229-L232), which loads every entry and runs after each IceFrame write to any table, throughinvalidate_query_cache
Who can plant an entry
Planting an entry takes write access to cache_dir. The default is .iceframe_cache under the working directory, so the folder lands wherever the process happens to start:
- a project checkout;
- a notebook folder several people share;
- a volume mounted into a container;
- a cached CI workspace.
Write access there already lets someone swap the parquet files under data/ and change results. With a pickle in the index, it becomes code running in a process that holds the catalog's credentials.
What I checked
What I saw on 0.14.0 from PyPI, against a local SQLite catalog with a file:// warehouse and no credentials: I cached one query, then rewrote its index entry as a pickle.
- A pickle calling a function from my script ran on the next cached
execute(), and the result was the rows that function picked. - A pickle calling
os.systemran on the next cachedexecute()in a new process, which then raisedAttributeError: 'int' object has no attribute 'get'. It also ran onput()for that query and on an append to a different table, whereinvalidate_query_cachelogged the sameAttributeErroras a warning. - A pickled key in the index ran on the next write and on
clear().
The dependency
The cause sits in the dependency, and there is nothing to upgrade to: CVE-2025-69872 (GHSA-w8v5-vhqr-4h9v) is open against diskcache as a whole, whose last release, 5.6.3, came out in August 2023. pip-audit on a fresh install of iceframe[cache] 0.14.0 (plus pyiceberg[sql-sqlite] for the local catalog) lists exactly one finding, diskcache 5.6.3 (PYSEC-2026-2447), with no fix version. While the cache extra installs diskcache, every audit of such an environment keeps reporting it, and DiskCache keeps loading its index this way.
Versions
- IceFrame 0.14.0
- Python 3.12.13
- PyIceberg 0.12.0
- Polars 2.1.0
- diskcache 5.6.3
sqlcatalog on SQLite- local
file://storage - macOS arm64
Activity