Skip to content

fix(security): cap bsdtar extraction size to prevent decompression bomb DoS [DEVA11Y-484]#25

Open
maunilm wants to merge 1 commit into
mainfrom
fix/DEVA11Y-484-bsdtar-size-limit
Open

fix(security): cap bsdtar extraction size to prevent decompression bomb DoS [DEVA11Y-484]#25
maunilm wants to merge 1 commit into
mainfrom
fix/DEVA11Y-484-bsdtar-size-limit

Conversation

@maunilm
Copy link
Copy Markdown
Collaborator

@maunilm maunilm commented May 29, 2026

Summary

  • CWE-400 (Uncontrolled Resource Consumption) — OWASP A05. bsdtar was invoked with no decompressed-size or entry-count limit, so an attacker who can influence the download URL (the HTTPS-only --download-url / BROWSERSTACK_A11Y_CLI_DOWNLOAD_URL override, or TLS interception of the default endpoint) could serve a decompression bomb that exhausts developer/CI disk space.
  • Fix covers all four affected surfaces: the Swift SPM plugin and the bash, zsh, and fish wrappers (the ticket only flagged scripts/bash/cli.sh; zsh/fish were byte-identical).

What changed

Plugins/BrowserStackAccessibilityLint.swift

  • curl now passes --max-filesize (100 MB) to cap the compressed download.
  • A background watchdog terminates bsdtar once the decompressed footprint on disk exceeds 200 MB. A cap on the curl→bsdtar pipe would only bound compressed bytes — useless against a bomb — so the guard measures bytes written to disk. Applied to both the remote and local extraction paths.
  • locateExecutable bounds enumeration at 10,000 entries (secondary CPU/IO drain from archives with millions of empty entries).

scripts/{bash,zsh,fish}/cli.sh

  • curl --max-filesize caps the compressed download.
  • bsdtar … -O output is piped through head -c (200 MB) with set -o pipefail; an oversized archive aborts (and deletes the partial binary) instead of filling the disk.

Why these limits don't break legitimate use

The real CLI artifact (macos arm64) is ~34 MB compressed / ~64 MB decompressed, so the 100 MB / 200 MB caps leave ~3× headroom for growth.

Note on scope vs. the ticket

The ticket's primary vector (MitM on a plaintext download) is already closed by DEVA11Y-479 (override restricted to HTTPS; default URL is HTTPS). This PR is defense-in-depth against the remaining vectors: an attacker-controlled HTTPS override endpoint, or TLS interception. Practical severity is arguably below the stated CVSS 5.3, but the guard is cheap and correct.

Verification

  • swiftc -typecheck -parse-as-library against the toolchain PackagePlugin module: clean.
  • bash -n on all three scripts: clean.
  • Functional test of the bsdtar -O | head -c pipeline: a 1 MB payload with a 4 KB cap aborts (pipefail → status 1); with a 200 MB cap it extracts normally.

Jira

DEVA11Y-484 · umbrella APPSEC-415

🤖 Generated with Claude Code

…mb DoS [DEVA11Y-484]

CWE-400 / OWASP A05. bsdtar was invoked with no decompressed-size or
entry-count limit in both the Swift SPM plugin and the bash/zsh/fish CLI
wrappers, so an attacker who can influence the download URL (the
HTTPS-only --download-url / BROWSERSTACK_A11Y_CLI_DOWNLOAD_URL override,
or TLS interception) could serve a decompression bomb that exhausts the
developer/CI disk.

Swift plugin (BrowserStackAccessibilityLint.swift):
- curl now passes --max-filesize (100 MB) to cap the compressed download.
- A background watchdog terminates bsdtar once the *decompressed* footprint
  on disk exceeds 200 MB (a pipe-level cap would only bound compressed
  bytes, which is useless against a bomb). Applied to both the remote and
  local extraction paths.
- locateExecutable now bounds enumeration at 10,000 entries.

Shell wrappers (bash/zsh/fish cli.sh):
- curl --max-filesize caps the compressed download.
- bsdtar output is piped through `head -c` (200 MB) with pipefail so an
  oversized archive aborts instead of filling the disk.

Real CLI artifact is ~34 MB compressed / ~64 MB decompressed, so the caps
leave ~3x headroom and do not affect legitimate downloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maunilm maunilm requested a review from a team as a code owner May 29, 2026 12:28
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.

1 participant