Packages can be read/written outside the configured cache directory
MediumPublished Jul 8, 2026
### Summary Pkl 0.31.1 accepts literal and percent-encoded `..` path segments in `package://` URI paths. When package caching is enabled, the disk package resolver derives cache filesystem paths from the decoded package URI path without rejecting parent-directory traversal. This allows an attacker-controlled package URI fetched from one authority to create cache entries under a different victim package authority. A later import of the clean victim package URI can then load attacker-controlled package content from the poisoned cache without contacting the victim authority. I also confirmed a constrained cache-root escape where package metadata `.json` and package archive `.zip` files are written outside the configured `--cache-dir`. ### Impact * Cross-authority package cache poisoning: a package fetched from one authority can create a cache entry for another package authority. * Trusted/victim package import from poisoned cache: a later clean victim import loaded attacker-controlled contents from cache * Constrained cache-root escape: attacker-controlled package metadata `.json` and package archive `.zip` were written outside the configured `--cache-dir`. Who is impacted: * Us...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| org.pkl-lang:pkl-core Maven | < 0.32.0 | 0.32.0 |
Details and references
### Summary Pkl 0.31.1 accepts literal and percent-encoded `..` path segments in `package://` URI paths. When package caching is enabled, the disk package resolver derives cache filesystem paths from the decoded package URI path without rejecting parent-directory traversal. This allows an attacker-controlled package URI fetched from one authority to create cache entries under a different victim package authority. A later import of the clean victim package URI can then load attacker-controlled package content from the poisoned cache without contacting the victim authority. I also confirmed a constrained cache-root escape where package metadata `.json` and package archive `.zip` files are written outside the configured `--cache-dir`. ### Impact * Cross-authority package cache poisoning: a package fetched from one authority can create a cache entry for another package authority. * Trusted/victim package import from poisoned cache: a later clean victim import loaded attacker-controlled contents from cache * Constrained cache-root escape: attacker-controlled package metadata `.json` and package archive `.zip` were written outside the configured `--cache-dir`. Who is impacted: * Users who evaluate or download Pkl package URIs from untrusted or attacker-influenced inputs while package caching is enabled. * CI/build systems that evaluate Pkl packages before generating configuration, code, manifests, or deployment artifacts. * Applications embedding Pkl evaluation where package URI inputs or dependency data can be influenced by untrusted parties and where disk package caching is enabled. ### Mitigation * Upgrade to 0.32.0, and clear existing package caches after upgrading, because poisoned cache entries can persist. * Reject package URIs containing literal `../` or `%2e%2e` before passing them to Pkl. * Prefer locked package dependencies and checksum verification, but do not rely on this alone for direct package imports without metadata checksums.
- Severity from
- GitHub (reviewed advisory)
More Apple advisories
All Apple| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Jul 17 | Unauthenticated out-of-bounds stack write via oversized ECDSA signature in swift-nio-ssh | Critical | 0.14.1 |
| Jul 16 | Double-free when parsing RSA public key fails | Critical | 4.5.1 |
| Jul 15 | Accessing bytes of non-string SAN can lead to out-of-bounds memory read | Critical | 2.37.2 |
| Jul 9 | Apple FileMaker Server: code execution | Medium4.9 | 26.0.1 |
| Jul 9 | DoS via WebSocket frame with oversize 64-bit payload length field (Int trap in WebSocketFrameDecoder) | High7.5 | 2.101.0 |
| Jul 8 | Remote packages can read files past a local package dependency root | Low | 0.32.0 |