T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/sandbox.py:132
- Finding
- Unrestricted Local File Upload and Overwrite Crosses the Sandbox Security Boundary<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sandbox.py:132-155` **Vulnerability Type**: Unrestricted local file access and third-party data transfer **Risk Level**: High ### Vulnerable Code ```python def cmd_upload(args): sbx = connect(args.sandbox_id) try: with open(args.local_path, "rb") as f: sbx.files.write(args.sandbox_path, f) json_out({"status": "ok", "from": args.local_path, "to": args.sandbox_path}) except FileNotFoundError: json_err(f"Local file not found: {args.local_path}") except Exception as e: json_err(f"Upload failed: {e}", sandbox_id=args.sandbox_id) def cmd_download(args): sbx = connect(args.sandbox_id) try: content = sbx.files.read(args.sandbox_path) if content is None: json_err(f"File not found in sandbox: {args.sandbox_path}", sandbox_id=args.sandbox_id) if isinstance(content, bytes): with open(args.local_path, "wb") as f: f.write(content) else: with open(args.local_path, "w") as f: f.write(content) json_out({"status": "ok", "from": args.sandbox_path, "to": args.local_path}) except Exception as e: json_err(f"Download failed: {e}", sandbox_id=args.sandbox_id) ``` The relevant documentation also exposes these operations in `SKILL.md:155-163`, while `SKILL.md:302` only provides a non-enforced instruction not to upload sensitive files. ### Technical Analysis The `upload` operation accepts an arbitrary local path and transmits the selected file to a Novita cloud sandbox. It does not enforce a workspace root, reject symbolic links, screen sensitive locations, impose a size limit, or require confirmation before crossing the local-to-cloud trust boundary. The `download` operation similarly accepts an arbitrary local destination and opens it using `wb` or `w`. These modes overwrite existing files without confirmation. There is no canonica ...[truncated 2497 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require an explicitly configured local workspace root and reject all paths outside it. 2. Resolve paths with `Path.resolve()` and verify that the canonical path remains beneath the approved root. 3. Reject symbolic links and revalidate opened files to mitigate symlink and time-of-check/time-of-use attacks. 4. Deny known sensitive file classes and directories, including SSH keys, cloud credentials, environment files, browser profiles, keychains, and Agent configuration. 5. Require explicit user confirmation before uploading any local file to a third-party service. 6. Apply file-size and file-type limits before upload. 7. For downloads, refuse to overwrite existing files by default. Use exclusive creation and require a separate `--overwrite` option with confirmation. 8. Write downloads to a controlled staging directory and use atomic replacement only after validation. 9. Clearly disclose the remote destination, selected local path, file size, and overwrite behavior before transfer. 10. Enforce these restrictions in code rather than relying solely on Skill instructions. ]]>
