Security audit
Source-level review of the vendored
fragglet/lhasa decoder.
Attack surface
Lhasa is a decoder. The attack surface is essentially the
LHA-format parser plus a tight set of output paths. Compared to
an encoder+decoder (the original lha binary), lhasa
is a much smaller target.
- No encoder — nothing the input archive can do
will cause lhasa to spawn child processes, write to a
predictable location, or take an action on the user's
behalf. The user controls extraction via the explicit
lha x ...path. - Static build — released binaries have no dynamic dependencies, no shared library hooks, no constructor / destructor ordering bugs.
- No filesystem side-effects on
lha l/lha t/lha p— those are read-only at the directory level. Side effects only happen on explicitlha x.
The decode kernels are short and well-isolated: each
lib/lh*_decoder.c is ~600 LoC of pure C with no
extern state outside the decoder object.
CVE history
No public CVEs filed against fraggle / lhasa or
vendored lhasa derivations as of 2026-07-15. Notable historical
issues fixed in upstream (per
NEWS):
- v0.6.0 (2026-06-17) — read overflow in
-pm2-decoder'scopy_decode[]access; not believed exploitable but fixed; reported by Yukimura (@damseleng). Also: empty-filename members now skip properly so subsequent files extract correctly. - v0.5.0 (2025-08-01) — list output tweaks (mostly cosmetic, but improves robustness of naively-written GUI parsing tools).
The 0.6.0 read-overflow fix is the most recent CVE-relevant
change. The vendored copy in upstream/lhasa/ is at
HEAD 75ed835, which includes the v0.6.0 fix.
Fuzz readiness
Lhasa ships a libFuzzer harness in
test/fuzzer.c
against the liblhasa entry points. The full corpus of upstream
tests + fuzz findings is what lhasa's regression suite runs
against via make check.
We do not yet run continuous fuzzing against the vendored copy in ljh-sh/lhasa's CI — that's a future addition (likely an OSS-Fuzz integration once the upstream is enrolled). For now, the 0.6.0 read-overflow fix is the most recent piece of evidence that upstream fuzzing is reaching production code.
Supply-chain hygiene
- Vendoring —
upstream/lhasa/is agit subtreesnapshot. The NOTICE.md documents the merge commit and re-vendor command. - Patches — none. The vendored tree is identical
to upstream
75ed835. Any local patch immediately shows as a subtree diverging from upstream, which the CI does not have a guard against. - Build determinism — see
build audit. Same source +
same CI runner + same toolchain = reproducible SHA256SUMS.
Currently observed variance is below
2 KBon output size — noise from header timestamps; binary content itself is identical.
Threat model & residual risk
Realistic threats ljh-sh/lhasa faces:
- Malicious .lzh archive — user downloads a
hand-crafted archive that tries to trigger a parse bug.
Surface area is small (decoder-only, no shell injection
paths). Mitigation:
lha t(CRC check) before extract; compare SHA256 against upstream source-of-truth when available. - Path traversal during
lha x— path stored in archive resolves outside cwd. Modern lhasa handles common cases (absolute paths,..); users runninglha xon untrusted archives should pre-check withlha l. - Zip-bomb-style decompression amplification — LZH
doesn't pad encoded data the way zip does, so amplification
ratios are bounded by the format itself
(
-lh5-roughly matches deflate levels). Disk-space sanity checks are still warranted for huge archives.
The decoder-only design is the central safety claim. lhasa
cannot emit harmful content; it only renders what the
archive contains. Compare with general-purpose decoders like
tar / unrar, which have larger
attack surfaces (more format families, more output paths,
more fork/exec history).
Vulnerability disclosure
Email: fragglet@gmail.com (upstream maintainer
— for issues in the vendored code). For ljh-sh/lhasa
distribution-specific issues (build pipeline, CI, release
artifacts), open an issue at
github.com/ljh-sh/lhasa/issues.