T09 · Insecure Skill Coding Practices
- Location
scripts/search.py:32- Finding
Arbitrary Local Files Can Be Uploaded to External Search Providers
- Content
View full analysis
Vulnerability Details
File Location:
scripts/search.py:32-35,scripts/search.py:150-156, andscripts/search.py:223-224
Vulnerability Type: Unrestricted local-file handling and external data disclosure
Risk Level: HighVulnerable Code
python def is_local_file(path: str) -> bool: if path.startswith(("http://", "https://", "ftp://")): return False return Path(path).exists()python if local: resp = await engine._send_request( method="post", params=params, data={"prg": 1}, files={"upfile": read_file(input_path)}, )python if is_local_file(input_path): resp = await engine.search(file=input_path) else: resp = await engine.search(url=input_path)Technical Analysis
The application considers any existing filesystem path to be a valid local image. It does not verify that the path:
- Refers to a regular file rather than another filesystem object.
- Resides within an explicitly approved upload directory.
- Has a permitted image format or MIME type.
- Can be decoded as an image.
- Satisfies a safe file-size limit.
- Does not contain sensitive or polyglot content.
Consequently, any file readable by the process can be passed to
engine.search(file=...)and uploaded to Yandex, Google Lens, or Bing. The Yandex diagnostic fallback can perform an additional direct upload usingread_file(input_path).This is particularly dangerous if an untrusted party can influence the command-line argument, such as through an agent-generated invocation, automation wrapper, API parameter, or crafted instruction.
Attack Path
- An attacker influences the value supplied as
image_url_or_path. - The attacker supplies the path of a sensitive readable file, such as an environment file, application configuration, source file, access token file, or SSH private key.
Path(path).exists()returns ...[truncated 926 chars]
- Remediation
View remediation
Remediation Suggestions
- Resolve the path with
Path.resolve(strict=True)and require it to remain inside one or more explicitly approved upload directories. - Require
Path.is_file()and reject symbolic links, devices, directories, sockets, and other special filesystem objects. - Enforce a conservative maximum file size before reading or uploading content.
- Decode the file with a trusted image-processing library and only accept an allowlist of raster formats such as JPEG, PNG, and WebP.
- Do not rely solely on extensions or client-provided MIME types.
- Reject active or complex formats such as SVG unless they are safely rasterized in isolation.
- Require explicit user confirmation identifying the destination provider before uploading local content.
- Avoid repeating an upload during diagnostics unless the user has separately authorized it.
- Prefer accepting an already validated attachment object rather than an unrestricted filesystem path.
- Resolve the path with
