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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

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.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 51)May include surrounding context.

md
node scripts/milan-olympics.js top

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 59)May include surrounding context.

md
node scripts/milan-olympics.js top

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 65)May include surrounding context.

md
node scripts/milan-olympics.js top

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 148)May include surrounding context.

md
node scripts/milan-china-medals.js list

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 156)May include surrounding context.

md
node scripts/milan-china-medals.js list

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 162)May include surrounding context.

md
node scripts/milan-china-medals.js list

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 168)May include surrounding context.

md
node scripts/milan-china-medals.js list

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 176)May include surrounding context.

md
node scripts/milan-china-medals.js list

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.