Back to skill

Security audit

劳动法费用计算器

Security checks for vulnerabilities and agentic risk

Overview

This labor-law calculator is mostly purpose-aligned, but it needs review because it can write Excel files to caller-chosen paths and sends API credentials plus a persistent session ID to configurable policy endpoints.

Review before installing. The calculator purpose is legitimate and disclosed, but run it with a low-privilege account, avoid giving untrusted users control of output_path or @file payload paths, keep config.json API keys narrowly scoped, and do not allow untrusted environment variables to set policy API URLs.

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

T09 · Insecure Skill Coding Practices

Error
Location
compensation-damages-calculator/scripts/policy_data.py:83
Finding

Authenticated Policy Requests Can Be Redirected to an Arbitrary Destination

Content
View full analysis
str: return os.getenv( "COMPENSATION_DAMAGES_POLICY_API_URL", DEFAULT_POLICY_API_URL, ).strip() def build_api_request(payload: dict[str, Any], apikey: str) -> urllib.request.Request: request_payload = request_payload_from_input(payload) request_body = {"resource_type": RESOURCE_TYPE, "payload": request_payload} return urllib.request.Request( policy_api_url(), data=json.dumps(request_body, ensure_ascii=False).encode("utf-8"), headers={ "Content-Type": "application/json", "Authorization": authorization_header(apikey), **REQUEST_CONTEXT.headers, }, method="POST", ) def read_api_response(request: urllib.request.Request) -> dict[str, Any]: try: with urllib.request.urlopen(request, timeout=15) as response: data = json.loads(response.read().decode("utf-8")) ``` `overtime-pay-calculator/scripts/policy_data.py`: ```python def policy_api_url() -> str: return os.getenv("OVERTIME_POLICY_API_URL", DEFAULT_POLICY_API_URL).strip() ``` `work-injury-compensation-calculator/scripts/policy_data.py`: ```python def policy_api_url() -> str: return os.getenv("WORK_INJURY_POLICY_API_URL", DEFAULT_POLICY_API_URL).strip() ``` The latter two modules use the same request construction pattern, including the Bearer API key and `REQUEST_CONTEXT` headers. ### Technical Analysis Network access is relevant to the declared functionality because th ...[truncated 2341 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
compensation-damages-calculator/scripts/policy_data.py:51
Finding

Persistent Session Identifier Is Created and Transmitted Without Clear Disclosure

Content
View full analysis
str: session_id = path.read_text(encoding="utf-8").strip() if path.exists() else "" if session_id: return session_id session_id = str(uuid.uuid4()) path.write_text(session_id, encoding="utf-8") return session_id REQUEST_CONTEXT = SkillRequestContext() ``` The identifier is subsequently transmitted in the API request: ```python headers={ "Content-Type": "application/json", "Authorization": authorization_header(apikey), **REQUEST_CONTEXT.headers, }, ``` The overtime-pay and work-injury modules contain the same behavior. ### Technical Analysis Each policy module creates `REQUEST_CONTEXT` during module import. Its constructor reads `.session` from the current working directory or creates that file with a new UUID. The UUID is reused across later executions from the same working directory and is transmitted in the `Session-Id` ...[truncated 1718 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
compensation-damages-calculator/scripts/calc_engine.py:736
Finding

XLSX Export Accepts Unrestricted Paths and Can Overwrite Files

Content
View full analysis
None: # XLSX document parts are constructed above. path.parent.mkdir(parents=True, exist_ok=True) with zipfile.ZipFile(path, "w", compression=zipfile.ZIP_DEFLATED) as archive: for archive_path, content in xlsx_parts.items(): archive.writestr(archive_path, content) def export_output_path(payload: dict[str, Any], default_name: str) -> Path: output_path = Path(str(payload.get("output_path") or default_name)) if not output_path.is_absolute(): output_path = BASE_DIR / output_path return output_path def export_to_excel(payload: dict[str, Any]) -> dict[str, Any]: normalized, amounts = export_rows_and_amounts( payload, "export_excel requires a rows or detail_rows array", ) output_path = export_output_path( payload, "compensation_damages_detail.xlsx", ) write_xlsx(output_path, normalized, amounts) ``` The overtime-pay and work-injury calculators use the same path-handling pattern. The unused-annual-leave calculator also directly constructs its export path from user input: ```python output_path = Path( str(payload.get("output_path") or "unused_annual_leave_detail.xlsx") ) ``` All four writers open the destination with ZIP write mode: ```python path.parent.mkdir(parents=True, exist_ok=True) with zipfile.ZipFile ...[truncated 2213 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (48)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个“路由技能”,重点在于依据用户劳动法费用问题自动分发到若干子技能,且列出的覆盖范围包括补偿金/赔偿金、加班费、年假折算、工伤赔偿。实际代码则是单体计算引擎:通过payload中的action调用具体处理函数,支持calc_s、calc_n、compensation_n、n_plus_1、illegal_2n、no_contract、non_compete,以及min_wage_lookup、social_avg_wage_lookup和export_excel。代码中完全没有加班工资、未休年休假补偿、工伤赔偿相关逻辑;相反却实现了竞业限制补偿、政策数据查询和Excel导出等未在声明中体现的能力。因此,声明与实际行为在核心功能范围和主要用途上均存在实质性不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的是一个上层“路由技能”,应根据用户问题在多个劳动法计算子技能之间分发。代码却是一个具体的数据访问脚本,专门为 compensation-damages-calculator 获取政策参数:读取 config.json 中的 API key,生成会话/技能头信息,向固定 API 发送 POST 请求,校验响应,缓存到本地文件,并输出政策字段(min_wage、social_avg_wage、law_basis 等)。这与“自动分发到补偿金/赔偿金、加班工资、年假、工伤赔偿子技能”的主功能明显不一致。虽然其内容与劳动法补偿相关,但范围明显更窄,且加入了外部资源访问和缓存这一未在描述中体现的核心行为,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的核心能力是“自动分发到多个劳动法费用计算子技能”,覆盖补偿金/赔偿金、加班工资、年假补偿、工伤赔偿等场景。但代码中 dispatch 仅按 payload.action 调用固定处理器,实际处理器只有 wage_conversion、各类加班费计算、最低工资查询/校验和 Excel 导出,没有任何离职补偿、年休假补偿或工伤赔偿相关逻辑。因此其主要用途与声明不符:它不是一个广义劳动法费用路由技能,而是一个加班费计算引擎,附带最低工资检查和报表导出。虽然“加班工资计算”这一子项与声明部分一致,但整体声明明显高估并误述了代码的功能范围,属于实质性描述-行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个面向多类劳动法费用问题的“路由技能”,核心行为应是识别用户问题并转发到不同计算子技能。但代码并未实现问题分类或路由逻辑,也没有补偿金、赔偿金、年假补偿、工伤赔偿等计算相关处理。相反,它专门处理加班工资政策数据:验证 region 参数、从本地配置读取 API key、调用固定远程资源类型 overtime-pay-calculator 的政策接口、校验政策字段并缓存结果。虽然这可能作为加班工资计算的支持组件,但它与“劳动法费用计算路由技能”的主用途存在实质性不符,因此应判定为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

从代码看,dispatch 只在固定 action 集合内分发到年休假相关处理函数(annual_leave_days、daily_wage、new_employee、resignation、in_service、eligibility_check、export_to_excel),没有任何基于用户问题文本的路由逻辑,也没有与离职补偿金、加班费、工伤赔偿相关的计算实现。因此,声明的核心能力“劳动法费用计算路由技能”与实际行为明显不符。虽然声明中提到“未休年休假补偿计算”,这一部分与代码一致,但代码覆盖面远窄于声明,同时还包含未声明的Excel导出功能,属于实质性描述-行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个覆盖多类劳动法费用问题的“路由技能”,核心能力应是识别用户问题并分发到补偿金/赔偿金、加班费、年假折算、工伤赔偿等子技能。实际代码并不是通用路由器,而是单一的工伤赔偿计算脚本:dispatch 仅按输入 action 调用内部函数,没有自然语言问题识别或跨子技能路由。功能范围也明显偏窄,集中在工伤保险待遇、工亡待遇、离职两项补助金、停工留薪期和相关政策数据查询;声明中提到的加班工资、未休年休假补偿、一般离职补偿/赔偿金均未实现。此外,代码还提供了未声明的 Excel 导出和政策数据 API 读取能力,以及退休年龄计算。这些都表明描述与实际行为存在实质性不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是一个上层“路由技能”,核心职责应是识别用户问题并分发到多个计算子技能。给出的代码却是 policy_data.py,其行为集中在工伤赔偿场景的政策数据管理:加载 session/skill 元数据、读取 config.json 中的 API key、调用远程 platform.delilegal.com API、处理响应、做字段校验、并将政策数据写入/读取本地缓存。它支持的 action 也仅为 api_snapshot/fetch_api_snapshot/policy_data,没有任何基于用户问题的路由逻辑,也没有加班费、离职补偿、年假补偿等计算实现。因此,代码的主要用途与声明的主要用途存在实质性不一致。

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

md
按以下关键词优先级匹配,**命中即停止**,直接读取对应子技能的 `SKILL.md` 并执行:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
按以下关键词优先级匹配,**命中即停止**,直接读取对应子技能的 `SKILL.md` 并执行:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code accepts a user-controlled output_path, converts it to a Path, and writes an XLSX there with no allowlist, sandboxing, or traversal prevention. In an agent/runtime context, this creates an arbitrary local file write primitive that can overwrite application files, place files in sensitive directories, or be chained with other behaviors for persistence or data tampering.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The export path is caller-controlled via output_path and is converted directly into a Path, with relative paths resolved under BASE_DIR but absolute paths left untouched. This allows an untrusted caller to write a ZIP/XLSX file to arbitrary filesystem locations accessible to the process, which can overwrite application files, plant artifacts in sensitive directories, or abuse disk write privileges beyond the calculator's business purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The export_to_excel path is user-controlled via output_path and is only checked for absoluteness before being written, allowing arbitrary relative paths under BASE_DIR and any absolute path outright. This enables path traversal or arbitrary local file write in the agent's execution context, which can overwrite application files, drop deceptive artifacts, or write into sensitive locations if privileges permit.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

export_output_path builds the destination from caller-controlled output_path and resolves relative paths against BASE_DIR, but does not restrict absolute paths or traversal to a safe directory. This permits arbitrary file creation or overwrite anywhere the process can write, which is dangerous in an agent runtime and unrelated to the stated calculation purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

load_payload accepts an argument beginning with '@' and reads that path directly from the local filesystem, allowing a caller to cause arbitrary file reads within the permissions of the process. For a labor-fee calculator, this capability is unjustified and can expose sensitive host data such as configuration files, secrets, or user documents.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description and main instructions are entirely in Chinese and define the skill's behavior for Chinese labor-law fee calculations without any opt-in or alternative language handling. Under the policy, forcing a specific language or locale without user choice is a natural-language policy violation unless the restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill metadata description is entirely written as a Chinese-only operating description and presents the skill as activating and responding in that locale without mentioning any user language preference or opt-in. Under the policy, locale or language constraints should either be optional, user-selected, or clearly justified as region-specific; here the region is labor law, but the file does not explicitly state that outputs are limited to Chinese by user choice.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest focuses on dispatching labor-law fee calculation requests to subskills. This file additionally performs policy data retrieval through get_policy_data/policy_api_url and returns 'needs_web_search' guidance when data is missing, introducing external data lookup behavior that is not described in the manifest.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The export function writes to a caller-provided filesystem path without any visible confirmation or warning in this code path. In a skill context, silent file creation amplifies the danger of the arbitrary-write capability because routine calculation requests could be repurposed to drop files locally without meaningful user awareness.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes this skill as a labor-law fee calculation router that dispatches questions to calculation subskills for compensation, overtime, annual leave, and work-injury compensation. In this file, the skill also exports calculation rows to an XLSX file on disk, which is a materially broader behavior than routing or calculating fees.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This Python file sends request payload data, an authorization header, and session/skill metadata to an external API via HTTP POST. While the behavior is implemented clearly in code, there is no confirmation prompt, user-facing log/print, or inline warning in this file disclosing that user inputs and local session identifiers will be transmitted to a remote service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description is entirely framed in Chinese and describes the skill as a Chinese labor-law overtime calculator, but it does not state that output language follows the user's preference or offer any language choice. Under the policy rule, forcing a specific language without opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file title and usage note indicate the reference is written entirely in Chinese and intended to be loaded by the AI during calculations. There is no natural-language indication that users can opt into another language or that the skill is intentionally restricted to Chinese-speaking or China-specific users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file consistently emits Chinese-only labels and messages, beginning with hard-coded spreadsheet headers such as 序号, 加班类型, and 金额(元). This enforces a specific language/locale in user-visible outputs without any visible opt-in or language selection mechanism, which matches the language/locale policy violation category.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill performs a filesystem write based on caller input without any built-in confirmation, warning, or policy gate. In agent contexts, silent side effects are dangerous because a prompt or tool-chain step can cause persistent file creation unexpectedly, increasing the risk of misuse, data sprawl, or writing into operational locations when combined with the unrestricted output_path behavior.

Content

No source excerpt is available for this finding.