T09 · Insecure Skill Coding Practices
- Location
scripts/compile_and_run.py:56- Finding
Unrestricted local reference paths may expose files to an external image-generation workflow
- Content
View full analysis
str: p = pathlib.Path(os.path.expanduser(path)) if not p.is_absolute(): p = WORKSPACE / p return str(p.resolve()) def choose_reference_images(data: Dict[str, Any], args: argparse.Namespace) -> List[str]: refs = [] if args.reference_image: refs.extend(args.reference_image) else: refs.extend(as_list(data.get("reference_images"))) if args.style_image: refs.append(args.style_image) forbidden_terms = [x.lower() for x in as_list(data.get("forbidden")) + as_list(args.forbidden)] forbidden_image_terms = [x for x in forbidden_terms if x] out = [] seen = set() for ref in refs: full = resolve_path(ref) name_low = pathlib.Path(full).name.lower() stem_low = pathlib.Path(full).stem.lower() if any(term in name_low or term == stem_low for term in forbidden_image_terms): raise SystemExit(f"forbidden input image rejected: {ref}") if full not in seen: out.append(full) seen.add(full) if args.require_character_refs and not out: raise SystemExit("input_images must not be empty when --require-character-refs is set") if len(out) > args.max_input_images: raise SystemExit(f"too many input_images: {len(out)} > {args.max_input_images}") missing = [p for p in out if not pathlib.Path(p).exists()] if missing: raise SystemExit("missing input image(s): " + ", ".join(missing)) return out ``` The selected files are subsequently passed to the external image-generation workflow: ```python cmd = [sys.executable, str(DIRECT_RUN), "--prompt", prompt, "--task-name", task_name, "--provider", args.provider, "--model", ...[truncated 2955 chars]- Remediation
View remediation
pathlib.Path: candidate = pathlib.Path(value).expanduser() if not candidate.is_absolute(): candidate = WORKSPACE / candidate candidate = candidate.resolve(strict=True) try: candidate.relative_to(TRUSTED_REFERENCE_ROOT) except ValueError: raise SystemExit("reference image is outside the trusted asset directory") if not candidate.is_file(): raise SystemExit("reference image must be a regular file") return candidate ``` 2. Reject absolute paths and traversal syntax at the input boundary unless there is a documented need for them. 3. Resolve symlinks before applying the trusted-root check, as shown above. 4. Validate file type using content-based image decoding rather than filename extensions alone. 5. Add a separate explicit option or confirmation gate for transmitting local files to an external provider. 6. Record the provider destination and approved reference paths before execution without copying sensitive file contents into logs. 7. Treat specifications from chats, repositories, or remote task systems as untrusted input. 8. Add automated tests covering absolute paths, `..` traversal, home expansion, symlink escape, directories presented as files, and malformed image content. ]]>
