Packages can be read/written outside the configured cache directory
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
.jsonand package archive.zipwere 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...
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)