T09 · Insecure Skill Coding Practices
- Location
scripts/scan_skill.py:366- Finding
Unbounded Remote Package Download and ZIP Extraction Permit Resource Exhaustion
- Content
View full analysis
Vulnerability Details
File Location:
scripts/scan_skill.py:366-385
Vulnerability Type: Unbounded download and archive extraction
Risk Level: MediumVulnerable Code
python req = Request(download_url, headers={"User-Agent": "skill-security-audit/1.3.0"}) with urlopen(req, timeout=120) as resp: zip_path.write_bytes(resp.read())python extract_dir = tmp_dir / "extracted" try: with zipfile.ZipFile(zip_path, "r") as zf: safe_extract(zf, extract_dir)Technical Analysis
The response body is read completely into memory with
resp.read()before being written to disk. The scanner does not enforce a maximum download size or validate theContent-Lengthheader.Although
safe_extract()protects against ZIP path traversal, it does not impose limits on:- The number of archive entries.
- The compressed or expanded size of individual entries.
- The total expanded archive size.
- The compression ratio.
- Available disk space before extraction.
Consequently, an attacker-controlled ClawHub package can contain an oversized response or a highly compressed ZIP bomb. The network timeout limits how long an individual operation may take, but it does not limit the amount of data read or extracted.
Attack Path
- An attacker publishes or supplies the slug of a crafted ClawHub package.
- The victim invokes
scan_skill.py --slug <attacker-controlled-slug>. - The scanner downloads the package and loads the entire response body into process memory.
- If the package is a ZIP bomb,
safe_extract()validates path placement but proceeds to expand every entry. - The scanner exhausts memory, disk capacity, or CPU resources, causing process or host-level denial of service.
Impact Assessment
Exploitation does not grant the attacker additional operating-system privileges or arbitrary code execution. However, it can consume resources available to the ...[truncated 460 chars]
- Remediation
View remediation
Remediation Suggestions
- Stream the response in fixed-size chunks instead of calling unbounded
resp.read(). - Enforce a strict maximum package size while streaming, regardless of whether
Content-Lengthis present. - Reject responses whose declared
Content-Lengthexceeds the configured limit. - Before extraction, inspect every
ZipInfoentry and enforce:- A maximum number of entries.
- A maximum uncompressed size per entry.
- A maximum cumulative uncompressed size.
- A maximum compression ratio.
- Reject encrypted, malformed, overlapping, or otherwise unsupported archive entries.
- Check available disk space before extraction and stop extraction if cumulative output exceeds the approved limit.
- Run package processing inside a resource-constrained environment with memory, disk, CPU, and execution-time quotas.
- Preserve the existing path-traversal validation in addition to these resource controls.
- Stream the response in fixed-size chunks instead of calling unbounded
