Back to skill

Security audit

Tencent Doc Update Watcher

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Tencent Docs update-checking purpose, but its script can fetch arbitrary configured URLs and optionally retain raw pages, headers, and cookies, so it needs review before installation.

Install only if you trust the configs you will run. Keep --keep-raw off unless debugging, and avoid using sensitive authenticated Tencent Docs links unless you are comfortable with local snapshot metadata. The publisher should constrain URLs to https://docs.qq.com, restrict curl protocols and redirects, and document the exact filesystem/network permissions expected.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/check-qq-doc-updates.py:153
Finding
Unrestricted URL Fetching Enables SSRF and Local Resource Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check-qq-doc-updates.py`, lines 153–183 **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unrestricted local resource retrieval **Risk Level**: Medium ### Vulnerable Code ```python name = str(doc.get("name") or f"doc-{idx}") page_url = str(doc.get("url") or "").strip() doc_id = str(doc.get("id") or "").strip() or parse_doc_id(page_url) public_url = strip_query(page_url) if page_url else page_url doc_key = doc_id or public_url or name prefix = f"{idx:02d}_{sanitize_name(name)}" cookie_path = raw_dir / f"{prefix}.cookies.txt" html_path = raw_dir / f"{prefix}.html" opendoc_path = raw_dir / f"{prefix}.opendoc.js" header_path = raw_dir / f"{prefix}.opendoc.headers.txt" errors: list[str] = [] warnings: list[str] = [] if not page_url: return { "name": name, "url": public_url, "doc_key": doc_key, "id": doc_id, "fetch_ok": False, "errors": ["url is empty"], } code, err = run_cmd( [ "curl", "-sSL", "-c", str(cookie_path), "-b", str(cookie_path), "-A", user_agent, page_url, "-o", str(html_path), ], timeout=timeout, ) ``` ### Technical Analysis The configured `page_url` is passed directly to `curl` without validating its scheme, hostname, port, resolved IP address, or redirect destination. The `-L` option instructs curl to follow redirects automatically. Consequently, a configuration entry can direct the process to destinations outside the declared Tencent Docs scope. The Skill only needs to communicate with Tencent Docs, but the implementation can access: - Loopback services such as `127.0.0.1` or `::1` - Private network services - Link-local and cloud metadata endpoints - Unexpected external domains - Non-HTTP resources supported by the installed curl build, potentially including `file://` The response is written to the workspace as ...[truncated 2463 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Enforce the declared destination scope** - Accept only absolute HTTPS URLs. - Normalize the hostname and require an exact match for `docs.qq.com`. - Reject embedded credentials, unexpected ports, malformed URLs, and non-HTTPS schemes. 2. **Control redirects** - Prefer disabling redirects. - If redirects are necessary, inspect and validate every redirect destination before issuing the next request. - Apply the same scheme, hostname, port, and IP-address restrictions to every hop. 3. **Prevent access to internal addresses** - Resolve the hostname before connecting. - Reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses. - Protect against DNS rebinding by ensuring the validated address is the one used for the connection. 4. **Restrict curl protocols** - Add protocol restrictions such as `--proto =https` and `--proto-redir =https`. - Avoid relying only on string-based URL validation. 5. **Limit resource consumption** - Set a maximum response size. - Add connection, total-transfer, and low-speed timeouts. - Reject oversized responses and ensure partial files are removed after failures. 6. **Harden raw-data retention** - Keep raw response and cookie retention disabled by default. - Warn users explicitly that `--keep-raw` may retain sensitive content. - Create retained files with restrictive permissions. - Avoid retaining cookie files unless they are essential for an explicit debugging workflow. 7. **Add security tests** - Test rejection of `file://`, loopback, private-network, link-local, and metadata-service URLs. - Test redirects from an allowed-looking URL to a prohibited destination. - Test IPv6, alternative IP notation, hostname normalization, and DNS rebinding scenarios. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Ae1

High
Category
analysis-evasion
Content
python scripts/check-qq-doc-updates.py \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python scripts/check-qq-doc-updates.py \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python scripts/check-qq-doc-updates.py \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs use of shell execution, network access, and file read/write behavior, but it does not declare any explicit tool scope or permission boundaries. In an agent environment, this creates an authorization gap: the runtime may allow broader capabilities than reviewers or users expect, increasing the risk of unintended outbound requests, unsafe filesystem access, or misuse of temporary workspaces.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_cmd(cmd: list[str], timeout: int) -> tuple[int, str]:
    p = subprocess.run(
        cmd,
        capture_output=True,
        text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
When --keep-raw is enabled, the script preserves raw HTML, headers, and especially cookie jar files on disk under the snapshot directory. Because this skill processes Tencent Docs content that may rely on authenticated access, retained cookie files and fetched artifacts can expose session material or sensitive document metadata to other local users, backups, or later unintended reuse.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The file includes a section titled and written entirely in Chinese, but does not indicate that language selection is optional or provide equivalent opt-in guidance. This can conflict with language/locale policy requirements when a skill imposes or assumes a specific language without user choice.

Static analysis

No suspicious patterns detected.