T09 · Insecure Skill Coding Practices
- Location
scripts/cloud_cli.py:25- Finding
Unrestricted Local File Encoding and Upload Through Source Image Parameter
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cloud_cli.py:25-44; data is subsequently transmitted byscripts/run.py:94-99andscripts/run.py:124
Vulnerability Type: Unrestricted local file read and network upload
Risk Level: MediumVulnerable Code
python def encode_image_source(source: str) -> str: """Local path → data URI; http(s)/data: returned unchanged.""" raw = (source or "").strip() if not raw: raise ValueError("source_image is empty") if raw.startswith(("http://", "https://", "data:")): return raw path = Path(raw) if not path.is_file(): raise ValueError(f"source_image file not found: {raw}") data = path.read_bytes() suffix = path.suffix.lower() if suffix == ".png": mime = "image/png" elif suffix == ".webp": mime = "image/webp" elif suffix in (".jpg", ".jpeg"): mime = "image/jpeg" else: mime = "image/jpeg" encoded = base64.b64encode(data).decode("ascii") return f"data:{mime};base64,{encoded}"The resulting value is added to the cloud request:
python if args.source_image: try: payload["source_image"] = encode_image_source(args.source_image) except ValueError as exc: print(f"Error: {exc}", file=sys.stderr) return 1python data = run_skill(SKILL_API_ID, payload, timeout=300.0)Technical Analysis
The source-image handler accepts any path that resolves to a regular file and reads its complete contents. It does not verify that the data is actually an image, inspect its file signature, enforce an approved input directory, reject symbolic links, or impose a file-size limit.
Files with unsupported extensions are labeled as
image/jpegrather than rejected. Base64 is legitimate transport encoding and is not, by itself, evidence of covert exfiltration. The security problem is that arbitrary file contents can be encoded and included in a network request while ...[truncated 1452 chars]- Remediation
View remediation
Remediation Suggestions
- Resolve the supplied path to its canonical form and require it to reside under an explicitly approved upload directory.
- Reject symbolic links unless there is a documented need to support them.
- Permit only explicitly supported image formats.
- Validate image content using file signatures and a maintained image-decoding library; do not trust the extension.
- Reject files whose detected type does not match the declared MIME type.
- Enforce conservative limits on file size, decoded dimensions, and total pixel count before encoding.
- Stream uploads where the API supports multipart transfer instead of holding the original and encoded copies in memory.
- Require explicit user confirmation showing the canonical path, destination host, detected type, and file size before transmitting a local file.
- Do not label unsupported files as JPEG; fail closed with a clear error.
