Repository navigation
security: authenticate cache values with HMAC-SHA256 before unpickling - #147
Merged
Merged
Conversation
Mitigates DiskCache's unpatched GHSA-w8v5-vhqr-4h9v in toolkit cache readers by wrapping the raw diskcache.Cache in an AuthenticatedCache that signs every stored value with a private, machine-local key and verifies it before deserializing. Changes: - cache.py: import AuthenticatedCache and load_cache_key at module level; get_cache() now loads the signing key from platformdirs.user_data_dir/cache-signing and returns an AuthenticatedCache, or None if the key store is unsafe. - autocomplete.py: delegate cache creation to get_cache() instead of constructing diskcache.Cache directly; suppress now-unused diskcache import warning. - create.py: use shlex quoting when passing PEP 723 dependency metadata to the package installer so crafted dependency strings cannot inject shell commands. - tests/tasks/test_cache_security.py: new test suite covering unsigned pickles, tampered authenticated values, cross-key/cross-cache replay, insecure key storage, symlinked keys, poisoned payloads, forged Settings entries, file-backed entries, and concurrent key publication. - tests/extensions/test_create.py: add test asserting that dependency metadata is passed verbatim (not executed) to the installer. - pyproject.toml: add anyio>=4.14.2 runtime floor and uv constraint- dependencies for black, filelock, urllib3, uv and virtualenv. - README.md, CHANGELOG.md: document the cache authentication scheme and updated dependency floors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mitigates DiskCache's unpatched GHSA-w8v5-vhqr-4h9v in toolkit cache readers by wrapping raw
diskcache.Cachein anAuthenticatedCachethat signs every stored value with a private, machine-local HMAC-SHA256 key and verifies it before deserializing.Also fixes a shell-injection vector in
create.script_envwhere PEP 723 dependency metadata was interpolated into a shell command without quoting.Changes
src/invoke_toolkit/tasks/cache.pyAuthenticatedCacheandload_cache_keyfrom_cache_securityat module level.get_cache()loads the signing key fromplatformdirs.user_data_dir/cache-signing/cache.key(owner-only permissions required) and returns anAuthenticatedCache, orNoneif the key store is missing or has unsafe permissions — disabling caching rather than reading unsigned data.src/invoke_toolkit/tasks/autocomplete.pyget_cache()instead of callingdiskcache.Cachedirectly, so completion caches inherit the same authentication.src/invoke_toolkit/extensions/tasks/create.pyshlex.quotewhen interpolating PEP 723 dependency metadata into theuvinvocation, preventing crafted dependency strings from injecting shell commands.tests/tasks/test_cache_security.py(new)Comprehensive test suite covering:
Settingsentries cannot replace the signing keyfilenamecolumn entries cannot delete user filestests/extensions/test_create.pytest_script_env_quotes_dependency_metadata: verifies that a malicious;-suffixed dependency string is passed verbatim to the installer and not executed by the shell.pyproject.toml/uv.lockanyio>=4.14.2runtime floor (TLS fixes).uv constraint-dependenciesfor black, filelock, urllib3, uv, and virtualenv (patched releases).README.md/CHANGELOG.md