Skip to content

Mitigate CWE-409 (zip bombs) - #587

Open
Derek Keeler (d3r3kk) wants to merge 3 commits into
mainfrom
update-cwe-409
Open

Mitigate CWE-409 (zip bombs)#587
Derek Keeler (d3r3kk) wants to merge 3 commits into
mainfrom
update-cwe-409

Conversation

@d3r3kk

Copy link
Copy Markdown
Contributor

Mitigations for CodeQL-detected vulnerability that this library would (might) expose a consumer to.

See CWE-409 for a longer description and more context.

Alternatives to consider:

  • Remove IO handling from gctoolkit (shifts IO responsibility)
    • Enforce wrapping application handling for IO
    • gctoolkit accepts stream data only
  • Reduce handling to just .zip - Apache compression lib mitigates (reduced functionality)
  • Do not mitigate at all, provide guidance for consuming services/applications (likely not a great plan)

Bound compressed and expanded input, line length, archive structure, and rotating log processing. Preserve limit and archive integrity failures for callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Delegate ZIP64 metadata and entry decoding to Commons Compress while
retaining bounded preflight, resource accounting, and integrity checks.
Keep the guarded GZIP reader for bounded optional-header parsing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

There is at least one correctness/security-affecting accounting bug in compressed-byte tracking plus a notable performance regression in plaintext tail reading that should be addressed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 High severity · 2 Medium severity

New issues introduced by this change (3)
Severity Finding
High severity api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LimitedInputStream.java — LimitedInputStream registers the initial compressed-byte count but does not update…
Medium severity api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​GCLogFileSegment.java — tail(...) now collects the last N lines by streaming the entire file. This is O(file size) I/O (and…
Medium severity api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LogFileStreams.java — openValidatedZipChannel() returns a SeekableByteChannel after ZipArchivePreflight.validate() has…
What changed in this PR

This PR mitigates CWE-409 (zip bombs) exposure in GCToolKit’s log I/O layer by introducing explicit, finite resource limits for plaintext/GZIP/ZIP inputs and enforcing them during streaming and metadata inspection.

Changes:

  • Add LogFileReadLimits + enforcement plumbing (expanded/compressed bytes, line length, compression ratio, archive entry/metadata limits, gzip header limits) and propagate limits through GCLogFile, SingleGCLogFile, RotatingGCLogFile, and segment/metadata readers.
  • Switch ZIP handling to Apache Commons Compress with a ZIP preflight validator + per-entry validation/CRC/size checks.
  • Add comprehensive unit tests that exercise limit triggers and boundary behaviors across plaintext, gzip (including multi-member), and zip (including forged metadata cases).
File Description
pom.xml Adds commons-compress version + dependency for ZIP mitigations.
api/​pom.xml Adds module dependency on commons-compress.
api/​src/​main/​java/​module-info.java Declares JPMS requirement on org.apache.commons.compress.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LogFileReadLimits.java Defines configurable secure defaults and validated limit configuration.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LogFileReadLimitExceededException.java Introduces a dedicated unchecked exception for limit failures during lazy stream operations.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LogFileReadBudget.java Tracks expanded/compressed budgets and enforces compression ratio across reads.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LimitedInputStream.java Enforces budgets while reading and tracks compressed/expanded ratios.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LimitedGZIPInputStream.java Implements a bounded/validated GZIP reader with header/member limits and ratio checks.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​BoundedLineSpliterator.java Enforces maximum decoded characters per line with proper close-on-failure semantics.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​ZipArchivePreflight.java Validates ZIP central directory structure/size bounds before indexing/streaming.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​LogFileStreams.java Centralizes safe stream creation for plaintext/gzip/zip entries with validation and limits.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​GCLogFile.java Adds per-log immutable read-limits and ensures stream closures in diary() discovery.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​SingleGCLogFile.java Routes streaming through LogFileStreams with per-operation budgets and limit enforcement.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​RotatingGCLogFile.java Streams rotating segments through LogFileStreams.segment(...) with a shared budget.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​SingleLogFileMetadata.java Propagates read limits into segment inspection.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​RotatingLogFileMetadata.java Applies limits when enumerating ZIP entries and directory segments; improves ordering logic.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​GCLogFileSegment.java Propagates read limits into segment streaming and timestamp inspection.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​GCLogFileZipSegment.java Uses validated ZIP entry streaming with limits and avoids leaking ZIP file handles.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​jvm/​AbstractJavaVirtualMachine.java Ensures data source streams are closed and surfaces I/O as unchecked for lazy failures.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​GCToolKit.java Preserves checked-IOException behavior by unwrapping UncheckedIOException; passes through limit exceptions.
api/​src/​main/​java/​com/​microsoft/​gctoolkit/​io/​DataSource.java Documents limit-exceeded failures during terminal stream operations.
api/​src/​test/​java/​com/​microsoft/​gctoolkit/​io/​SingleGCLogFileReadLimitsTest.java Adds extensive tests covering ZIP/GZIP edge cases and limit enforcement.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +34 to +36
if (compressedBytes != null) {
budget.registerCompressedBytes(compressedBytes.getAsLong());
}
Comment on lines +193 to 196
private List<String> tail(int numberOfLines, LogFileReadBudget readBudget) {
try (Stream<String> lines = stream(readBudget)) {
return lines.collect(tailCollector(numberOfLines));
}
Comment on lines +250 to +252
try {
ZipArchivePreflight.validate(channel, path, limits);
return channel;
Raise the finite expanded-byte and line-length defaults above the largest existing regression fixtures while retaining independent compression and archive safeguards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 2, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants