Back to skill

Security audit

Baidu Milan Winter Olympics 2026

Security checks for vulnerabilities and agentic risk

Overview

This skill fetches public 2026 Milan Winter Olympics data from Baidu Sports and has some quality and transparency issues, but no evidence of hidden access, persistence, credential use, destructive behavior, or exfiltration.

Install only if you are comfortable with a Baidu Sports based, Chinese-localized Olympics scraper that sends live network requests. For safer operation, prefer adding response-size limits and clearer disclosure of User-Agent rotation and locale behavior before using it in a long-running or memory-constrained agent environment.

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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/milan-china-medals.js:64
Finding
Unbounded HTTP Response Buffering in China Medal Scraper## Vulnerability Details **File Location**: `scripts/milan-china-medals.js`, lines 64-71 **Vulnerability Type**: Uncontrolled memory allocation while buffering an HTTP response **Risk Level**: Medium **Vulnerable Code**: ```js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { const buffer = Buffer.concat(chunks); resolve(buffer.toString('utf-8')); }); }); ``` ### Technical Analysis The HTTP client stores every response chunk in the `chunks` array and then allocates another contiguous buffer using `Buffer.concat`. It does not enforce a maximum response size before or during buffering. The 15-second request timeout elsewhere in the function limits elapsed time, but it does not limit the number of bytes that may be delivered during that interval. A compromised upstream service, malicious intermediary capable of controlling the trusted response, or unexpectedly large legitimate response could therefore cause excessive memory consumption. The final `Buffer.concat` operation may temporarily increase memory pressure further because it creates a new allocation containing all collected chunks. ### Attack Path 1. The script requests the declared Baidu Sports medal endpoint over HTTPS. 2. The remote endpoint, or infrastructure controlling its response, returns an abnormally large body within the configured timeout. 3. Each response chunk is retained in the unbounded `chunks` array. 4. At response completion, `Buffer.concat(chunks)` attempts an additional allocation for the complete body. 5. The Node.js process experiences excessive memory consumption and may be terminated or crash with an out-of-memory error. Exploitation requires influence over the remote response or network infrastructure trusted by the process; the URL is fixed and is not directly supplied by a local user. ### Impact Assessment T ...[truncated 367 chars]
Remediation
## Remediation Suggestions - Define a conservative maximum response size appropriate for the expected HTML payload. - Read and validate the `Content-Length` header when present, while still enforcing a streaming byte counter because that header may be absent or inaccurate. - Increment the byte counter in the `data` handler and destroy the response immediately if the limit is exceeded. - Validate the HTTP status code and expected content type before buffering the body. - Prefer a streaming parser where practical. - Ensure that overflow and aborted-response conditions reject the promise exactly once. Example hardening pattern: ```js const MAX_RESPONSE_BYTES = 5 * 1024 * 1024; const req = https.request(options, (res) => { if (res.statusCode !== 200) { res.resume(); reject(new Error(`Unexpected HTTP status: ${res.statusCode}`)); return; } let received = 0; const chunks = []; res.on('data', (chunk) => { received += chunk.length; if (received > MAX_RESPONSE_BYTES) { res.destroy(new Error('Response exceeds size limit')); return; } chunks.push(chunk); }); res.on('end', () => { resolve(Buffer.concat(chunks, received).toString('utf-8')); }); res.on('error', reject); }); ```

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/milan-news.js:63
Finding
Unbounded HTTP Response Buffering in News Scraper## Vulnerability Details **File Location**: `scripts/milan-news.js`, lines 63-70 **Vulnerability Type**: Uncontrolled memory allocation while buffering an HTTP response **Risk Level**: Medium **Vulnerable Code**: ```js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { const buffer = Buffer.concat(chunks); resolve(buffer.toString('utf-8')); }); }); ``` ### Technical Analysis The news scraper retains the entire remote response in memory without imposing a byte limit. Once all chunks have been collected, `Buffer.concat` creates a contiguous copy of the response. Consequently, peak memory usage can exceed the response size itself. A request timeout does not mitigate this issue because a large response can be transferred before the timeout expires. The code also does not reject an oversized response based on `Content-Length` or a streaming byte count. ### Attack Path 1. The script connects to the fixed Baidu Sports news endpoint. 2. A compromised endpoint or trusted network path supplies an oversized response. 3. The `data` listener continuously appends chunks without checking cumulative size. 4. The `end` listener attempts to concatenate the complete response. 5. Memory exhaustion causes severe slowdown, an out-of-memory exception, or process termination. The endpoint is fixed, so exploitation depends on control or compromise of the response source rather than ordinary command-line input. ### Impact Assessment Successful exploitation can deny availability of the news retrieval operation and may destabilize the hosting Agent runtime. The affected process obtains no additional privileges for the attacker, and the audited code does not turn the downloaded body into executable code.
Remediation
## Remediation Suggestions - Enforce a maximum response-body size using a cumulative byte counter in the `data` handler. - Abort the response and reject the operation as soon as the maximum is exceeded. - Preflight the declared `Content-Length` when available, without treating it as authoritative. - Accept only expected successful HTTP statuses and content types. - Consider incremental HTML or JSON parsing instead of retaining the entire document. - Add automated tests covering oversized, truncated, non-200, and malformed responses. A suitable limit should be based on observed legitimate payload sizes and include modest operational headroom.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/milan-olympics.js:64
Finding
Unbounded HTTP Response Buffering in Medal Rankings Scraper## Vulnerability Details **File Location**: `scripts/milan-olympics.js`, lines 64-71 **Vulnerability Type**: Uncontrolled memory allocation while buffering an HTTP response **Risk Level**: Medium **Vulnerable Code**: ```js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { const buffer = Buffer.concat(chunks); resolve(buffer.toString('utf-8')); }); }); ``` ### Technical Analysis The response from the medal-ranking page is buffered completely in an array with no upper bound. The subsequent `Buffer.concat` operation performs another allocation proportional to the total response size. This permits a remote response to drive memory consumption up to the Node.js heap or process limit. The configured timeout only limits request duration and cannot prevent a high-bandwidth endpoint from sending an excessive number of bytes before expiry. Requesting identity encoding also does not solve the issue because an uncompressed body can itself be arbitrarily large. ### Attack Path 1. The Skill invokes the medal-ranking scraper. 2. The fixed remote endpoint or a compromised trusted component returns a very large response. 3. The script stores all incoming chunks without enforcing a maximum. 4. The response completion handler duplicates the buffered data through concatenation. 5. The process runs out of memory or becomes unavailable. Direct URL injection is not present; response-source influence is required. ### Impact Assessment The vulnerability affects availability of the Skill and potentially the surrounding Agent process. It does not, on the available evidence, expose confidential local data or permit command execution, persistence, or privilege escalation.
Remediation
## Remediation Suggestions - Establish a strict maximum body size for the medal-ranking HTML. - Track `chunk.length` cumulatively and terminate the response when the threshold is crossed. - Reject oversized values declared by `Content-Length`, but retain the runtime counter as the definitive control. - Reject redirects or non-success statuses unless they are explicitly required and safely handled. - Verify the expected content type before processing. - Use bounded streaming extraction if the page format permits it. - Record size-limit violations without logging full untrusted response bodies.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/milan-schedule.js:76
Finding
Unbounded HTTP Response Buffering in Schedule API Client## Vulnerability Details **File Location**: `scripts/milan-schedule.js`, lines 76-85 **Vulnerability Type**: Uncontrolled memory allocation while buffering an HTTP response **Risk Level**: Medium **Vulnerable Code**: ```js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { try { const buffer = Buffer.concat(chunks); const text = buffer.toString('utf-8'); const data = JSON.parse(text); resolve(data); ``` ### Technical Analysis The schedule client buffers every JSON response without checking its cumulative size and then creates both a concatenated buffer and a UTF-8 string before parsing JSON. This can cause several simultaneous memory allocations proportional to attacker-controlled response size: the original chunks, the concatenated buffer, the decoded string, and the parsed object graph. This implementation is particularly exposed because commands that retrieve all schedules issue requests for multiple dates in batches of five. Although each request is individually timed out, several oversized responses could be buffered concurrently, amplifying peak memory usage. ### Attack Path 1. A user invokes a schedule command, such as retrieval of all Olympic dates. 2. The script sends multiple concurrent requests to the fixed Baidu Sports schedule endpoint. 3. A compromised endpoint or trusted response path returns one or more oversized JSON bodies. 4. Each response is retained in its own unbounded `chunks` array. 5. Completion creates a combined buffer, a decoded string, and potentially a large parsed object. 6. Concurrent allocations exhaust process memory and terminate or severely degrade the Skill runtime. The date and sport parameters alter the query string but do not alter the fixed destination host. Exploitation therefore relies primarily on controlling or compromising endpo ...[truncated 331 chars]
Remediation
## Remediation Suggestions - Apply a strict per-response byte limit before decoding or parsing JSON. - Validate `Content-Length`, HTTP status, and an expected JSON content type. - Destroy oversized responses immediately and propagate a clear error. - Reduce or dynamically control request concurrency so several near-limit responses cannot exhaust the process simultaneously. - Consider a streaming JSON parser if expected payloads can legitimately become large. - Configure an aggregate memory or response budget for multi-date operations. - Add tests that serve oversized JSON responses across all concurrent requests and verify clean cancellation. Example byte-limit logic: ```js const MAX_RESPONSE_BYTES = 2 * 1024 * 1024; let received = 0; const chunks = []; res.on('data', (chunk) => { received += chunk.length; if (received > MAX_RESPONSE_BYTES) { res.destroy(new Error('Schedule response exceeds size limit')); return; } chunks.push(chunk); }); ```
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description presents a general Winter Olympics data skill covering medal standings, country medal counts, live news, and schedules. The code, however, is narrowly scoped to one endpoint: Baidu Sports' China delegation '获奖名单' page (delegation id=26). It parses China's medal winners and computes summary counts by medal type and sport. There is no code for fetching news, schedule data, date-based schedule filtering, sport-based schedule lookup, or a full cross-country medal table. While it does relate to Milan Winter Olympics data and medal information, the implemented primary purpose is materially narrower than declared, so this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The description presents a multi-function Winter Olympics data skill covering medal rankings, news, and schedules. However, this code chunk is narrowly focused on one function: scraping live news from a specific Baidu Sports '直击现场' page. It performs HTTPS GET requests to a single news URL, parses news entries, supports filtering by content subtype, and lists available content types. There is no logic for medal table extraction, country medal counts, schedule lookup, date parsing, or sport-based schedule filtering. The accessed resource is consistent with the news portion of the description, but the implemented behavior is materially narrower than the declared primary purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The implementation is narrowly scoped to medal table scraping. It sends an HTTPS GET request to a single Baidu Sports medal-ranking URL, parses ranking/country/medal counts/flag/detail link data, and exposes only getTopMedals/getAllMedals plus CLI commands for top/all medal standings. There is no code for fetching news pages, schedule pages, date handling, sport filtering, or any broader Olympics data retrieval beyond medal rankings. The accessed resource is also specifically the medal tab URL, not multiple endpoints for news and schedules. Therefore the declared description materially overstates the implemented functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description presents a broader Winter Olympics data skill with three major capabilities: medal table retrieval, news retrieval, and schedule retrieval. The code chunk implements only the schedule portion. All network access targets a single Baidu Sports schedule endpoint (`/al/major/schedule/list`), and all exported functions/CLI commands revolve around schedules, date lists, and sports lists. There is no code for scraping or querying medal standings, no parsing of country medal counts, and no code for news articles or live reports. The description is therefore materially inaccurate/overbroad relative to this code chunk. The date-based and sport-based schedule-query aspects do match, and the Baidu Sports source is consistent, but the missing medal/news capabilities make this a mismatch.

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-olympics.js top
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-olympics.js top
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-olympics.js top
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-china-medals.js list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-china-medals.js list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-china-medals.js list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-china-medals.js list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/milan-china-medals.js list
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

Medium
Confidence
92% confidence
Finding
An overly broad activation description can cause the agent to invoke this skill for loosely related sports/news requests, leading to incorrect tool use and untrusted web scraping when unnecessary. In an agent environment, ambiguous routing increases attack surface because users or prompt content can more easily steer execution into external-data-fetching behavior not actually needed for the task.

Natural-Language Policy Violations

Medium
Confidence
81% confidence
Finding
The skill prominently describes retrieving data from Baidu Sports and several output fields are defined as Chinese-language values, such as country names in Chinese and Chinese content categories, but the document does not state that this is a China/Chinese-only skill or offer a language preference. This can violate language/locale policy when users have not opted into Chinese-localized behavior.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The request headers hard-code `Accept-Language: zh-CN,zh;q=0.9,en;q=0.8`, which imposes a specific locale preference. The file does not offer any user opt-in or configuration for language/locale, and no region-specific compliance justification is documented.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The HTTP headers force `Accept-Language` to `zh-CN,zh;q=0.9,en;q=0.8`, which imposes a specific locale preference in the tool's behavior. Under the policy, locale constraints should be optional or clearly justified; this file does not provide an opt-in or explanation that the skill is intentionally China-specific.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The docstring and function intent at L223-L225 imply the function retrieves available content subtypes from the page. However, `extractNewsFromHtml` returns only an array of news items (L104-L116), so `data.subTabs` at L232 can never exist, meaning the function does not actually do what its documentation suggests except by returning a static fallback list.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes a broader Winter Olympics data skill covering medal rankings, live news, and schedules by date or sport. In this file, all implemented logic is dedicated to fetching and parsing a single Baidu medal-table page and exposing only `getTopMedals`/`getAllMedals`, with no code for news or schedule retrieval.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code file performs outbound HTTPS requests to a third-party service and intentionally rotates User-Agent strings to avoid using a fixed identifier. While the file has internal comments describing the behavior, there is no user-facing disclosure at runtime that the tool contacts Baidu and disguises requests as different clients, which is relevant to privacy and operational transparency.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The Accept-Language header forces a zh-CN-first locale preference for all requests. Under the policy, a language or locale constraint should not be imposed without user opt-in unless it is clearly documented and justified as region-specific behavior.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The docstrings at L589-L600 say these helpers return today's and tomorrow's Winter Olympics schedules. In code, getTodayDate/getTomorrowDate derive the host machine's current date (L568-L586), and getTodaySchedule/getTomorrowSchedule pass that directly into Baidu requests (L593-L604), even though the skill is specifically about the 2026-02-06 to 2026-02-22 Olympics range. This creates a direct mismatch between the documented intent and what the code actually queries outside that event window.

Intent-Code Divergence

Low
Confidence
77% confidence
Finding
The top-level doc comment describes the tool as fetching China's medal-winner list from Baidu Sports. However, the module also exposes getMedalStats and CLI commands for statistical aggregation, which goes beyond the stated documented intent rather than merely implementing the described fetch.

Description-Behavior Mismatch

Low
Confidence
91% confidence
Finding
The manifest describes a skill for retrieving 2026 Milan Winter Olympics medal standings, live news, and schedules, including queries by date or sport. This file hardcodes a single Baidu page for the China delegation's award list and implements only medal list/statistics retrieval, with no news, schedule, or general standings support in this module.

Intent-Code Divergence

Low
Confidence
76% confidence
Finding
The header comment presents the file as a '2026 Milan Winter Olympics medal standings retrieval tool,' which is consistent at a high level, but in the skill context this file serves as the implementation for a broader skill promising schedules and news. The code and exported API expose only medal-ranking operations, creating a documentation-to-implementation gap for the represented skill capability.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The `Accept-Language` header is fixed to `zh-CN,zh;q=0.9,en;q=0.8`, which enforces a specific locale behavior in the tool's outbound requests. The file does not offer users a language/locale option or explain why this locale constraint is required, which fits the policy-violation criterion for forced language or locale.

Static analysis

No suspicious patterns detected.