T09 · Insecure Skill Coding Practices
- Location
scripts/doc_search.py:296- Finding
Shell Command Injection Through Search-Result Filename
- Content
View full analysis
Vulnerability Details
File Location:
scripts/doc_search.py:296
Vulnerability Type: OS command injection
Risk Level: MediumVulnerable code:
python if args.open and results: top = results[0] try: os.startfile(top["file"]) if sys.platform == "win32" else os.system(f'xdg-open "{top["file"]}"') print(f"📂 已打开:{top['file']}") except Exception as e: print(f"⚠️ 打开失败:{e}")Technical Analysis
The non-Windows path interpolates
top["file"]into a command string passed toos.system(). This API invokes a system shell, so the selected document path is parsed as shell syntax rather than passed solely as an argument toxdg-open.top["file"]originates from filenames discovered beneath the directory selected for indexing. The filename and document content can therefore be controlled by an independent contributor when the searched directory is shared, synchronized, downloaded, or otherwise accepts third-party documents.Wrapping the path in double quotes is insufficient. Unix filenames may contain double quotes and other shell-significant characters. A filename can terminate the quoted argument and append another command. Command substitution expressions may also be evaluated inside double quotes.
The vulnerable operation is reached when:
- The Skill runs on a non-Windows platform.
- A search directory contains an attacker-supplied document with a malicious filename.
- The document is made the highest-ranked result by including content relevant to the query.
- The user invokes the search operation with
--open.
The user authorizes opening the highest-ranked document, but does not authorize executing shell commands encoded in its filename. This crosses the trust boundary between untrusted filesystem metadata and shell execution.
Attack Path
- An attacker places a supported document in a directory later searched by the victim. Supported i ...[truncated 1316 chars]
- Remediation
View remediation
Remediation Suggestions
Remove shell invocation and pass the selected path as a separate subprocess argument:
python if sys.platform == "win32": os.startfile(top["file"]) elif sys.platform == "darwin": subprocess.run(["open", top["file"]], check=False) else: subprocess.run(["xdg-open", top["file"]], check=False)Also apply the following hardening measures:
- Resolve the selected result path with
Path.resolve(). - Resolve the user-selected search root and verify that the result remains beneath that root using
Path.relative_to()or an equivalent containment check. - Confirm that the target is a regular file before opening it.
- Do not attempt to fix this by manually escaping shell characters; eliminating the shell is the reliable remediation.
- Add regression tests using filenames containing quotes, semicolons, dollar signs, command substitutions, backticks, spaces, and newlines.
- Resolve the selected result path with
