JanssenProject / JanssenProject/jans

feat(jans-cedarling): cap .cjar archive sizes to prevent zip-bomb resource exhaustion

Closed
#14,896 0 comments 0 reactions 1 assignee View on GitHub

Nobody has claimed this yet.

comp-jans-cedarling kind-feature
Dominant language
Java
Stars
648
Forks
174
Avg merge
1d 18h
Merged PRs (30d)
110

Description

## Problem

`.cjar` policy stores are ZIP archives. `ArchiveVfs` validates path traversal
and ZIP integrity, but reads every entry with an unbounded `read_to_end`
(`archive_handler.rs:324`). There is no limit on:

- decompressed size of a single entry (zip-bomb: a tiny archive can expand to a
huge in-memory file)
- total archive size
- number of entries (also makes `read_dir` / `is_directory_locked` O(n) per call)

This is the same class of issue already fixed for status lists in
`StatusList::parse` (10 MB decompressed cap), but not yet for policy stores. #14821

## Scope of limits

Two distinct sizes, two limits:

- **Downloaded (compressed) archive size** — already capped by
`CEDARLING_HTTP_MAX_RESPONSE_SIZE_BYTES` via `read_response_capped`.
- **Decompressed per-entry size** — currently uncapped, covered by the new
property below.

## Proposed change

Enforce limits during `ArchiveVfs::from_reader` validation and in `read_file`:

- per-entry decompressed size
- total archive size (also covers `CjarFile` / `ArchiveBytes`, which the HTTP
cap does not)
- maximum entry count

Exceeded limits return a typed `ArchiveError` variant (e.g.
`EntrySizeExceeded`, `ArchiveSizeExceeded`, `TooManyEntries`) instead of OOMing.

## Bootstrap property

- `CEDARLING_POLICY_STORE_MAX_FILE_SIZE` (default 10 MB) — cap on the
decompressed size of a single archive entry.

When `CEDARLING_HTTP_MAX_RESPONSE_SIZE_BYTES` is not set explicitly, it must
fall back to this value rather than using its own independent default, so a
download is never larger than the largest entry we are willing to decompress.

Update `default_config.yaml` and
`docs/cedarling/reference/cedarling-properties.md` in the same change.

## Acceptance criteria

- A `.cjar` with a zip-bomb entry fails with a typed error, not OOM.
- Unset `CEDARLING_HTTP_MAX_RESPONSE_SIZE_BYTES` falls back to
`CEDARLING_POLICY_STORE_MAX_FILE_SIZE`.
- The property is honored from env/JSON/YAML and documented.
- Tests cover: oversized entry, oversized archive, too many entries, and the
exact-at-limit boundary case.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.