Back to skill

Security audit

Cctv News Fetcher Conflict

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to fetch CCTV news as advertised, but its crawler follows unvalidated links from remote pages and sends a built-in cookie, so users should review its network behavior before installing.

Install only if you are comfortable running a local news crawler that makes outbound web requests. The main issue is not hidden behavior or persistence; it is that the crawler trusts links found in remote pages and may request destinations outside CCTV if those pages are manipulated. A safer version should allowlist CCTV HTTPS domains, validate redirects, remove the hard-coded cookie, cap fetched links and response sizes, add timeouts, and pin dependencies exactly.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/news_crawler.js:124
Finding
Unvalidated article URLs permit server-side request forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/news_crawler.js`, lines 9-29, 66-87, and 124-143 **Vulnerability Type**: Server-Side Request Forgery (SSRF) through unvalidated remote links **Risk Level**: Medium ### Vulnerable Code ```javascript const pageUrls = soup.querySelectorAll('li a').slice(1).map(a => a.getAttribute('href') || ''); const headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Cache-Control': 'no-cache', 'Cookie': 'cna=DLYSGBDthG4CAbRVCNxSxGT6', 'Host': 'tv.cctv.com', 'Pragma': 'no-cache', 'Proxy-Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' }; const data = await Promise.all(pageUrls.map(async pageUrl => { try { const pageResponse = await fetch(pageUrl, { headers }); ``` The same vulnerable pattern also occurs in the older and mid-period crawler paths: ```javascript const pageUrls = rawList.slice(1).map(item => item.match(/(http.*)/)?.[0].split('\'')[0] || ''); ``` ```javascript const pageUrls = soup.querySelectorAll('#contentELMT1368521805488378 li a') .slice(1) .map(a => a.getAttribute('href') || ''); ``` Each resulting value is subsequently passed to `fetch(pageUrl, { headers })`. ### Technical Analysis The crawler retrieves an index page from a fixed CCTV URL but then trusts article links extracted from that remotely supplied HTML. Before issuing secondary requests, it does not validate: - The URL scheme. - The destination hostname. - The destination port. - Whether the URL contains embedded credentials. - Whether DNS resolution points to loopback, private, link-local, or other restricted addresses. - Whether redirects remain on a ...[truncated 2211 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse every extracted link with `new URL()` and reject malformed URLs. 2. Permit only the `https:` scheme. 3. Apply an explicit hostname allowlist, limited to required CCTV domains such as `tv.cctv.com` and `cctv.cntv.cn`. 4. Reject URLs containing usernames or passwords and reject unexpected ports. 5. Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and cloud-metadata address ranges for both IPv4 and IPv6. 6. Disable automatic redirects or manually process them, applying the same validation to every redirect target. 7. Reject empty links and cap the number of links fetched from each index page. 8. Add request timeouts, response-size limits, status-code checks, and concurrency limits. 9. Enforce equivalent destination restrictions at the runtime or network-sandbox layer so the process cannot access internal networks even if application validation is bypassed. 10. Remove the manually assigned `Host` header and let the HTTP implementation derive it from the validated URL. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/news_crawler.js:133
Finding
Unnecessary hard-coded tracking cookie is disclosed with article requests<![CDATA[ ## Vulnerability Details **File Location**: `scripts/news_crawler.js`, lines 18, 76, and 133 **Vulnerability Type**: Hard-coded persistent identifier and unnecessary information disclosure **Risk Level**: Low ### Vulnerable Code The same header is defined in all three crawler implementations: ```javascript const headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Cache-Control': 'no-cache', 'Cookie': 'cna=DLYSGBDthG4CAbRVCNxSxGT6', 'Host': 'tv.cctv.com', 'Pragma': 'no-cache', 'Proxy-Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' }; ``` The headers are then attached to article requests: ```javascript const pageResponse = await fetch(pageUrl, { headers }); ``` ### Technical Analysis The crawler embeds a fixed `cna` cookie value and transmits it with article requests. No evidence in the project indicates that this cookie is necessary to retrieve public CCTV news pages. It is not identified as an authentication credential, but it acts as a persistent identifier and creates avoidable tracking and disclosure risk. The risk is amplified by the separate URL-validation flaw: because article destinations are derived from remote HTML without an origin allowlist, an attacker-controlled URL could receive the cookie. Even when requests remain on CCTV domains, embedding a shared static identifier causes different installations and users of the Skill to emit the same tracking value. ### Attack Path 1. The crawler extracts an article URL from a fetched index page. 2. It constructs a request containing the hard-coded `Cookie` header. 3. The request is sent to the extracted destination. 4. If the de ...[truncated 758 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hard-coded `Cookie` header because public news retrieval should not require a persistent identifier. 2. Do not replace it with a user-specific cookie unless authentication is explicitly required and documented. 3. If a cookie is genuinely required, obtain it through a controlled configuration mechanism, scope it to approved HTTPS origins, avoid logging it, and never send it to URLs obtained without strict validation. 4. Minimize request headers to those necessary for the operation. 5. Remove unnecessary browser-emulation headers, including `Host`, `Proxy-Connection`, and `Upgrade-Insecure-Requests`. 6. Combine this change with strict destination and redirect validation so sensitive headers cannot cross approved origin boundaries. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill instructs the agent to execute a local JavaScript crawler that fetches external content, but the manifest declares no explicit tool scope or permissions. This creates an authorization gap where a user-invocable skill can perform network-capable actions without clear restriction or review, increasing the risk of unintended data access or misuse of execution capabilities.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The only demonstrated user prompt is written in Chinese, which implies the skill is intended to operate in a fixed language. There is no accompanying note that users may choose another language or that the Chinese locale is a documented requirement, so this may violate language/locale policy expectations.

Vague Triggers

Low
Confidence
84% confidence
Finding
This manifest file uses the description "Fetch news from CCTV," which describes a general capability but does not define any specific trigger phrases, scope boundaries, or exclusion conditions. In manifest files, vague capability descriptions can contribute to ambiguous activation and unintended invocation.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"description": "Fetch news from CCTV",
    "main": "scripts/news_crawler.js",
    "dependencies": {
        "node-html-parser": "^7.0.2"
    }
}
Confidence
87% confidence
Finding
Using a caret range for dependencies allows automatically accepting future minor or patch releases, which can introduce malicious code, regressions, or breaking security behavior through the supply chain. In this skill's context, the risk is somewhat limited because there is only one dependency and package.json itself contains no active code, but it still weakens build reproducibility and increases exposure to compromised upstream releases.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The code hard-codes `Accept-Language: zh-CN,zh;q=0.9,en;q=0.8`, which imposes a locale preference in outbound requests. Under the policy, forcing a specific language or locale without user choice or a clearly documented region-specific justification is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This function also hard-codes `Accept-Language: zh-CN,zh;q=0.9,en;q=0.8`, creating the same locale restriction in outbound requests. The file does not provide a user-selectable language option or explain why this locale must be enforced.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The hard-coded `Accept-Language` value enforces a Chinese locale preference for requests in this code path as well. Because no opt-in or justification is present in the file, this matches the language/locale policy violation category.

Static analysis

No suspicious patterns detected.