T09 · Insecure Skill Coding Practices
- Location
scripts/read_meeting_data.py:14- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears to be a meeting-note reader and lister, but it has unrestricted URL fetching and a Windows command-injection risk that need review before installation.
Review this skill before installing. Use it only with trusted local paths and trusted meeting-document URLs, avoid Windows use until the PowerShell directory listing is replaced with Python-only enumeration or properly parameterized, and run it with network egress controls if URL fetching is allowed.
scripts/read_meeting_data.py:14Unrestricted URL Fetching Enables Server-Side Request Forgery
scripts/list_meeting_files.py:71PowerShell Command Injection Through an Unescaped Directory Path
The declared description covers three capabilities: reading meeting-note content from a local file, reading from a URL/web document, and listing files in a local meeting-notes directory. The supplied code implements only the directory-listing portion. It validates that the input is an existing local directory, enumerates files via system commands or Python, filters to .md and .txt files, and returns file count plus file list. There is no logic for opening or parsing a single meeting-notes file, no network or URL handling, and no support for remote documents like Feishu links. Therefore the description materially overstates the implemented functionality, so this is a mismatch.
The implemented behavior partially matches the description: it can read from a local file or URL. However, a substantive declared capability is missing: directory inspection. The code checks whether a local path exists and is a file, and returns an error if the path is a directory. Therefore the description overstates what the skill can do. There are no obvious extra undeclared sensitive capabilities beyond file/URL reading, but the description does not accurately represent the full actual limitations, so this should be flagged as a mismatch.
The skill declares capabilities to read local files, fetch URLs, and invoke shell-backed directory listing behavior, but it does not declare any explicit tool scope or permissions boundary. That makes the effective access surface broader and less auditable, increasing the risk of unintended file access, outbound requests, or command execution behavior when the skill is invoked.
The skill explicitly supports fetching arbitrary user-supplied URLs on a best-effort basis, but it does not require a clear user-facing warning that data will be sent over the network. This can expose sensitive meeting-related queries or access patterns to external services and, depending on implementation, could enable SSRF-style access to internal or unexpected endpoints.
Artifact content does not match its filename extension
The skill uses OS-native command execution to perform a task that can be completed entirely with standard Python filesystem APIs. This expands the attack surface unnecessarily and, in this file, contributes directly to the Windows command-injection issue. Given the skill's purpose is only to inspect meeting-note directories, broad subprocess capability is more dangerous than needed.
This subprocess invocation executes a PowerShell command built from a user-influenced path string. Although subprocess.run is called with an argument list, the embedded PowerShell script interpolates the location into a command string, so crafted input containing quotes or PowerShell metacharacters can break out of the quoted literal and trigger command injection. In this skill, the path comes from user-supplied directory input, making the issue directly reachable.
system_name = platform.system().lower()
if system_name == "windows":
command = _build_windows_command(location, recursive)
output = subprocess.run(
command,
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
if system_name in {"linux", "darwin"}:
command = _build_unix_command(location, recursive)
output = subprocess.run(
command,
capture_output=True,
text=True,
The manifest says the skill can inspect a local meeting-notes directory and report the file count plus file list, but this script only supports reading a single local file or fetching a URL. For local paths, it explicitly rejects anything that is not a file, so the advertised directory-listing behavior is absent from the actual implementation.
The rule explicitly prioritizes requests containing a fixed set of Chinese and English phrases, which embeds a language-specific policy in the skill behavior. The file does not state that language handling is configurable or user-selected, so this may impose a locale expectation without opt-in.
No suspicious patterns detected.