Skip to content

[security] T2.6 hardening: size caps on the remaining zip/tar sites (PSArchive, PSPackageBuilder, etc.) #89

Description

@natechadwick-intsof

Summary

T2.6 hardening sub-task of parent epic #73. This is a defense-in-depth follow-up to PR #83, which added per-entry / per-archive / per-archive-count size caps to PSArchiveFiles.extractFilesFromArchive(). This issue covers the other zip/tar sites in the project, which currently have ZipSlipGuard + canonical-path protection but lack the resource-exhaustion caps.

Scope

13 files use zip/tar APIs (excluding PSArchiveFiles.java already hardened in #83 and test files). All 13 already have ZipSlipGuard + canonical-path checks via the existing // codeql[java/zipslip] codeql suppressions. The change here is to add the same three caps that #83 added to PSArchiveFiles:

  • MAX_ENTRIES (10 000) — reject any archive with more entries
  • MAX_ENTRY_SIZE (100 MB) — reject any individual entry whose declared uncompressed size exceeds the cap
  • MAX_TOTAL_SIZE (500 MB) — sum the declared uncompressed sizes as entries are processed; abort if the running total exceeds the cap

These three limits cover the zip-bomb half of the 11 CVEs in commons-compress 1.28.0. The path-traversal half is already covered by the existing ZipSlipGuard.

Files affected

The 13 production files with zip/tar handling (no test files; tests are out of scope):

# File What it does
1 deployer/.../PSArchive.java Archive API for the deployer (ZipFile read path; uses PSArchiveFiles.getFile for extraction)
2 modules/perc-packages/.../PSPackageBuilder.java Package builder (ZipEntry write — defensive limits not strictly needed for writes, but symmetry helps)
3 projects/sitemanage/.../PSWidgetPackageBuilder.java Widget package builder (ZipInputStream read)
4 deliverytiersuite/.../MainDTSPreInstall.java DTS pre-install (ZipInputStream read)
5 modules/perc-distribution-tree/.../Main.java Distribution tree builder (ZipInputStream read)
6 system/.../PSInstallRxApp.java Install RxApp (ZipInputStream read)
7 system/.../Utils.java Install utilities (ZipInputStream read)
8 system/.../InstallRxApp.java Install RxApp alternate (ZipInputStream read)
9 modules/perc-ant/.../PSRxBuildInput.java Ant GUI (ZipInputStream read)
10 deployer/.../PSPackageLockManager.java Package lock manager (ZipFile read)
11 modules/Simple/.../PSDirectoryAnalyzer.java Directory analyzer (ZipFile read)
12 deployer/.../objectstore/PSArchive.java Archive wrapper (already covered by entry 1) — exclude
13 deployer/.../server/PSPackageLockManager.java Same as 10, exclude

After deduplication: 10 unique files to harden.

Approach

The cleanest pattern is a small helper class — PSZipBombGuard (or similar) — that wraps the size-check logic into a single utility. Then each call site does:

ZipInputStream zin = ...;
ZipBombGuard guard = new ZipBombGuard();
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) {
    guard.check(entry);  // throws SecurityException if cap exceeded
    ... process entry ...
}

The guard throws SecurityException with the offending entry name + cap that was hit (same fail-closed pattern as the ZipSlip check at lines 354-358, 374-379, 398-403 of PSArchiveFiles).

All three caps are overridable per JVM via the system properties PSARCHIVE_MAX_ENTRIES / PSARCHIVE_MAX_ENTRY_SIZE / PSARCHIVE_MAX_TOTAL_SIZE (matching the override keys used in #83).

Verification

  • ./mvn-env.sh clean install -DskipTests succeeds on Java 1.8
  • ./mvn-env.sh spotless:check passes
  • A small ad-hoc test with a zip containing > 10 000 entries (or > 100 MB entry, or > 500 MB total) throws SecurityException from each hardened call site
  • No UnsupportedClassVersionError in the build log

Out of scope

  • Test files (PSPackageLockManagerTest, PSPackageBuilderTest) are intentionally excluded. Test fixtures are controlled, not untrusted input.
  • The commons-compress 1.28.0 library upgrade itself (which would close the CVEs in the library code) — 1.28.0 is the last Java 1.8 line and 1.29+ requires Java 9+. The 11 CVEs cannot be closed by a version bump.
  • The PSPackageBuilder write path is technically not a zip-bomb attack surface (it's building archives, not reading them), but I'll add the same checks for symmetry / future-proofing.

References

Co-Authored by Mavis v1.0.0 using minimax-m3 with agent mavis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdependenciesPull requests that update a dependency file

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions