HSEC-2026-0014 json
Arbitrary file write via path traversal in unpackToDir
published yesterday modified yesterday
- cvss
- 9.8
- version 3.1, OSV
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
# Arbitrary file write via path traversal in unpackToDir
`Codec.Archive.unpackToDir` extracts a tar (or other archive supported by the libarchive C library) from a `ByteString` into a directory. `unpackToDirLazy` is the streaming variant; both funnel through the same internal `unpackEntriesFp` routine.
`unpackEntriesFp` joined each entry's name onto the destination directory with `System.FilePath.(</>)` without validating the name. Entry names starting with `..` sequences therefore escape the destination: `fp </> "../../../../etc/x"` resolves outside the extraction root. The joined path is written back into the archive entry (`archiveEntrySetPathname`) and handed to libarchive's `archive_read_extract` with no `ARCHIVE_EXTRACT_SECURE_*` flags, so neither the Haskell layer nor the C library rejects the traversal. The `..` check is not limited to tar archives: any format whose entry names libarchive reports verbatim is affected. Extraction result codes were also discarded, so write failures could pass unnoticed.
An attacker who can supply an archive to a service that extracts it with these APIs gains an arbitrary file write with the privileges of the extracting process. A demonstrated escalation (verified in a container): an archive with member `../../../../etc/profile.d/zz-poc-zipslip.sh` plants a shell script sourced by every subsequent login shell, converting the file write into code execution when any user logs in.
The reported traversal is fixed in libarchive-3.0.6.0, which fails with `ArchiveFatal` when an entry path begins with `..` (commit `325a2296379905557de1fa21b28d86f34bab2441`).
Users should upgrade to libarchive-3.0.6.0 or later. If pinned to an older version, validate entry names before extraction (reject absolute paths and any path containing a `..` component) or extract inside a sandboxed directory.
External vulnerability reported by Akash Sebastian (justabughunter).
Patch / fix
Is HSEC-2026-0014 in your dependencies? Fencer shows which of your repositories are affected as soon as an advisory lands, and opens the fix as a pull request.
Check with FencerCVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| OSV | 3.1 | 9.8 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| hackage | libarchive | >=0.1.0.0, <3.0.6.0 |
3.0.6.0 |
References
Sources
- OSV HSEC-2026-0014
Fencer Intel keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.