Back to skill

Security audit

China National Pension Calculation

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real pension calculator, but its local web server can expose sensitive financial data and readable files without adequate access controls.

Install only if you are comfortable with a local Node web server storing pension data in files and exposing it through unauthenticated local HTTP endpoints. Avoid entering real financial details until the server is restricted to loopback, authenticated, protected against path traversal, and given clear delete/retention controls.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
mcp-server.js:117
Finding

Arbitrary File Disclosure Through Static-File Path Traversal

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
mcp-server.js:49
Finding

Unauthenticated Network Access to Sensitive Financial Data APIs

Content
View full analysis
{ // Set CORS res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } // API: save data if (req.url === '/api/save-data' && req.method === 'POST') { let body = ''; req.on('data', chunk => body += chunk); req.on('end', () => { try { const data = JSON.parse(body); fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2)); fs.writeFileSync(STATUS_FILE, JSON.stringify({ status: 'completed', lastModified: new Date().toISOString() })); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true })); } catch (error) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } }); return; } // API: retrieve data if (req.url === '/api/get-data' && req.method === 'GET') { try { if (fs.existsSync(DATA_FILE)) { const data = fs.readFileSync(DATA_FILE, 'utf8'); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(data); } else { res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'No data found' })); } } catch (error) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } return; } }); webServer.listen(serverPort, ...[truncated 2897 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
mcp-server.js:65
Finding

Unbounded HTTP Request Accumulation Enables Memory and Disk Denial of Service

Content
View full analysis
body += chunk); req.on('end', () => { try { const data = JSON.parse(body); fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2)); fs.writeFileSync(STATUS_FILE, JSON.stringify({ status: 'completed', lastModified: new Date().toISOString() })); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true })); } catch (error) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } }); return; } ``` ### Technical Analysis The server appends every incoming chunk to an in-memory string without enforcing a maximum request size. The accumulated body is subsequently parsed and serialized again, causing multiple large in-memory representations of attacker-controlled data. The resulting formatted JSON is written synchronously using `writeFileSync`, blocking the Node.js event loop. A sufficiently large request can therefore: - Exhaust process memory during accumulation, parsing, or serialization - Block all MCP and web-server activity - Consume significant disk space - Repeatedly overwrite the shared data file - Crash the process due to an out-of-memory condition Because `/api/save-data` is unauthenticated, any reachable attacker can trigger the issue. Slow transmission can also keep connections and buffers active for extended periods. ### Attack Path 1. Start either HTTP server. 2. Connect to `/api/save-data`. 3. Send a very large valid JSON document or continuously stream data without promptly completing the request. 4. The server keep ...[truncated 931 chars]
Remediation
View remediation
{ size += chunk.length; if (size > MAX_BODY_SIZE) { res.writeHead(413, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Request body too large' })); req.destroy(); return; } chunks.push(chunk); }); ``` 3. Validate `Content-Length` when present, while still enforcing a streaming limit because that header is not trustworthy. 4. Configure request, header, and keep-alive timeouts. 5. Apply per-client rate limits and connection limits. 6. Validate the parsed object against a strict schema and reject unknown or excessively nested properties. 7. Replace synchronous filesystem operations in request handlers with asynchronous, atomic writes. 8. Set storage quotas and avoid retaining arbitrary attacker-supplied properties. 9. Apply equivalent limits to both server implementations. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
mcp-server.js:260
Finding

Prototype Pollution Through Unrestricted MCP Parameter Paths

Content
View full analysis
Remediation
View remediation
{ data.profile.currentAge = value; }, 'profile.retirementAge': (data, value) => { data.profile.retirementAge = value; }, 'socialSecurity.currentBalance': (data, value) => { data.socialSecurity.currentBalance = value; } }; if (!Object.hasOwn(setters, param)) { throw new Error('Unsupported parameter'); } setters[param](data, value); ``` 2. Reject every path segment equal to `__proto__`, `prototype`, or `constructor`. 3. Require exactly two path segments if only top-level sections and numeric fields are supported. 4. Verify intermediate objects with `Object.hasOwn()` instead of following inherited properties. 5. Validate numeric values with `Number.isFinite()` and field-specific ranges. 6. Harden `deepMerge` with the same special-key rejection and own-property rules. 7. Consider constructing data containers with `Object.create(null)` where prototypes are unnecessary. 8. Freeze shared templates such as defaults after initialization. 9. Add regression tests verifying that prototype-oriented paths are rejected and that `Object.prototype` remains unchanged. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill asks users to provide sensitive financial and personal retirement data, while the supplied documentation indicates undeclared local file persistence and server/API functionality. When sensitive data handling is not clearly disclosed up front, users may expose personal information without informed consent, and downstream components may process or retain it more broadly than expected.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill asks users to provide sensitive financial and personal retirement data, while the supplied documentation indicates undeclared local file persistence and server/API functionality. When sensitive data handling is not clearly disclosed up front, users may expose personal information without informed consent, and downstream components may process or retain it more broadly than expected.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The skill asks users to provide sensitive financial and personal retirement data, while the supplied documentation indicates undeclared local file persistence and server/API functionality. When sensitive data handling is not clearly disclosed up front, users may expose personal information without informed consent, and downstream components may process or retain it more broadly than expected.

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 8)May include surrounding context.

md
entry: "mcp-server.js"

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The UI directly tells users to copy and paste their pension data into an AI chat for analysis, which normalizes exfiltration of sensitive retirement and financial profile information to an external system. In the context of a pension calculator, this is especially risky because the data is personal, longitudinal, and financially revealing, making accidental over-disclosure likely.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
84% confidence
Finding

fast-uri 3.1.0 is associated with multiple high-severity parsing issues including host confusion and possible SSRF primitives. Even though the lockfile does not prove the skill parses attacker-controlled URLs, URL parsing libraries are often security-sensitive, and misuse through validation or allowlist logic could enable outbound request bypasses or trust-boundary failures.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: hono==4.12.12 — 16 advisory(ies): CVE-2026-47676 (Hono: app.mount() strips mount prefix using undecoded path, causing incorrect ro); CVE-2026-47675 (Hono: Cookie helper does not sanitize sameSite and priority, allowing Set-Cookie); CVE-2026-56761 (hono Improperly Handles JSX Attribute Names Allows HTML Injection in hono/jsx SS) +13 more

High
Category
Supply Chain
Confidence
89% confidence
Finding

hono 4.12.12 has numerous advisories affecting routing, cookie handling, and possible HTML/JSX injection surfaces. Given this skill explicitly supports a web interface, a vulnerable web framework in the dependency tree is especially relevant because exposed HTTP routes, templating, or header generation may be reachable by untrusted users.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding

ip-address 10.1.0 is flagged for address parsing inconsistencies and XSS in HTML-emitting methods. The XSS portion may be irrelevant if HTML helpers are unused, but the parsing inconsistency can matter anywhere IP-based allowlists, rate limiting, or trust decisions are made, and this package is pulled in by express-rate-limit-related dependencies.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file states that data is automatically loaded from a server on page startup and supports multi-device synchronization, which implies network transfer and remote storage of user data. The description does not include any warning about privacy, server persistence, or when user data leaves local storage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file documents a web server that supports POST requests to save data and shares a data directory with another server component. Because this behavior affects user data persistence and system storage, the markdown should disclose that data will be written server-side and clarify where it is stored.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The markdown explicitly says the skill supports server file saving through an API endpoint, alongside localStorage and JSON export/import. Since server-side file persistence can affect privacy and system integrity, the description should warn users that their data may be stored remotely or outside the browser.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The 'important note' asserts universal applicability across all regions and no regional differentiation, which is a strong claim about behavior and scope. Later, the disclaimer acknowledges that actual pension calculations are determined by local authorities, creating a direct contradiction in the skill's stated intent and reliability.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrase is broad enough to match ordinary conversation and can cause the skill to activate automatically when users merely ask about pensions. In this skill's context, activation leads quickly to collection and local storage of sensitive financial and personal data, increasing privacy risk and the chance of unintended tool use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The workflow directs users to enter age, retirement age, account balances, contribution history, and savings information without a clear privacy warning first. Because the skill persists this data to local files and may expose it through a local server workflow, the absence of an upfront warning materially increases the risk of unintentional disclosure or retention of highly sensitive financial data.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The technical description says the Web interface is implemented as a pure frontend with no backend server, which implies browser-only operation. However, elsewhere the file explains that data saving depends on starting the Node MCP server because static hosting cannot handle POST requests and the skill persists data to local files, so the documentation actively contradicts the real architecture.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This UI is not limited to local pension calculation: it loads data from a server, posts full pension/financial profile data back to a server, exports JSON files, and explicitly prepares data for AI consumption. The data involved is highly sensitive financial profile information, so unnecessary transmission and secondary sharing materially increase privacy, leakage, and misuse risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code creates a summary of retirement age, balances, contribution history, and future deposits, then copies it to the clipboard and instructs the user to provide it to an AI. Packaging sensitive financial data for exfiltration to third-party AI services is dangerous because users may not understand retention, training, or downstream disclosure risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The application sends sensitive pension and financial profile data to '/api/save-data' without any prominent user-facing privacy disclosure explaining what is sent, why, where it is stored, or who can access it. Even if transmission is expected by the developer, the absence of transparent notice and consent creates a privacy vulnerability and increases the chance of unauthorized or surprising data exposure.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Comments and success messages explicitly position server save and file export as being 'for LLM' or '供LLM读取', indicating that sensitive user data is being prepared for non-essential downstream AI consumption. This makes the intent of secondary data use clearer and increases concern because the feature is framed around sharing financial profile data beyond the calculator's primary purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The clipboard flow copies a detailed pension summary and prompts the user to paste it into an AI chat, but it does not provide an explicit privacy warning about third-party processing, retention, or account-level exposure. Clipboard contents can also be inadvertently pasted elsewhere, broadening exposure of sensitive financial information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This JavaScript file contains user-facing natural-language descriptions and report strings exclusively in Chinese, including the module description and generated report/recommendation text. The stated policy forbids forcing a specific language without user opt-in, and the file provides no indication that users can choose another language or that the locale restriction is explicitly documented as intentional.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The report title and recommendation messages returned by generateReport/generateRecommendations are fixed Chinese strings, so any consumer of this skill receives Chinese output regardless of user preference. That is a natural-language locale policy issue because the skill does not offer language choice or disclose a justified region-specific limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The file’s natural-language comments and validation messages are exclusively in Chinese, indicating the skill is designed around a single language/locale without any visible user choice mechanism. Under the policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This file contains natural-language comments and user-visible strings centered on Chinese-language use, but there is no indication that the skill is region-specific or that users can opt into this locale. Under the policy, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Natural-language strings throughout the file, including tool descriptions and user instructions, are exclusively in Chinese and direct the user to respond with Chinese phrases such as "已完成". There is no indication that the user can choose another language or that the Chinese-only constraint is required for a region-specific compliance reason.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.