Back to skill

Security audit

Skills of macro economy data released by ft.tech.

Security checks for vulnerabilities and agentic risk

Overview

This macroeconomic data skill largely matches its stated purpose, but its Python dispatcher can be steered toward unintended handler paths and should be reviewed before installation.

Install only if you are comfortable allowing the skill to run local Python scripts and contact market.ft.tech. Before broad use, harden run.py with an explicit allowlist of packaged subskill names and canonical path checks, and avoid passing arbitrary subskill names or path-like values.

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

T09 · Insecure Skill Coding Practices

Warning
Location
run.py:33
Finding

Path Traversal Allows Execution of an Unintended Python Handler

Content
View full analysis

Vulnerability Details

File Location: run.py, lines 33-43
Vulnerability Type: Path traversal in an executable file dispatcher
Risk Level: Medium

Vulnerable Code

python
subskill = sys.argv[1]
handler = os.path.join(SKILL_ROOT, "sub-skills", subskill, "scripts", "handler.py")

if not os.path.isfile(handler):
    print(f"Error: subskill '{subskill}' was not found: {handler}", file=sys.stderr)
    sys.exit(1)

result = subprocess.run(
    [sys.executable, handler] + sys.argv[2:],
    cwd=SKILL_ROOT,
)

Technical Analysis

The dispatcher incorporates the user-controlled subskill argument directly into the path of a Python file that it subsequently executes. It only verifies that the resulting path refers to a file; it does not:

  • Restrict the argument to the packaged sub-skill names.
  • Reject absolute paths or .. traversal components.
  • Canonicalize the resulting path before validation.
  • Verify that the resolved handler remains inside the intended sub-skills directory.
  • Protect against a symlink resolving outside that directory.

Consequently, a traversal value can cause the path to resolve outside the project’s sub-skills directory. If the resulting external directory contains scripts/handler.py, that file will be executed with the current Python interpreter.

The list-form subprocess.run() invocation does prevent shell metacharacter injection because shell=True is not used. However, that protection does not prevent selection and execution of an unintended Python script through path traversal.

Attack Path

  1. An attacker gains control of, or can influence, the first argument supplied to run.py.
  2. The attacker identifies or arranges an accessible directory outside the intended sub-skills directory containing a file at scripts/handler.py.
  3. The attacker supplies a traversal-based sub-skill value, such as a sequence containing ../, that causes the co ...[truncated 1466 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define an explicit allowlist containing the 16 packaged sub-skill names and reject every other value before constructing a path.
  2. Reject absolute paths, path separators, . components, and .. components in the supplied name.
  3. Resolve both the expected sub-skills directory and candidate handler with os.path.realpath().
  4. Use os.path.commonpath() to confirm that the canonical handler remains under the canonical sub-skills directory.
  5. Validate the canonical path after resolving symlinks so a symlink cannot redirect execution outside the package.
  6. Where possible, build a static mapping from each accepted sub-skill name to its exact handler path rather than treating the argument as a path component.
  7. Add negative tests covering traversal strings, absolute paths, nested path separators, and symlink escapes.

Example hardening approach:

python
ALLOWED_SUBSKILLS = {
    "economic-china-cpi-monthly",
    "economic-china-credit-loans-monthly",
    "economic-china-customs-trade-monthly",
    "economic-china-fiscal-revenue-monthly",
    "economic-china-fixed-asset-investment-monthly",
    "economic-china-forex-gold-monthly",
    "economic-china-gdp-quarterly",
    "economic-china-industrial-added-value-monthly",
    "economic-china-lpr-monthly",
    "economic-china-money-supply-monthly",
    "economic-china-pmi-monthly",
    "economic-china-ppi-monthly",
    "economic-china-reserve-ratio-monthly",
    "economic-china-retail-sales-monthly",
    "economic-china-tax-revenue-monthly",
    "economic-us-economic-by-type",
}

if subskill not in ALLOWED_SUBSKILLS:
    raise SystemExit("Invalid subskill")

subskills_root = os.path.realpath(os.path.join(SKILL_ROOT, "sub-skills"))
handler = os.path.realpath(
    os.path.join(subskills_root, subskill, "scripts", "handler.py")
)

if (
    os.path.commonpath([subskills_root, handler]) != subskills_root
    or not os.pa
...[truncated 76 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (25)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
`run.py` 与本文件(`SKILL.md`)位于同一目录。执行时:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
`run.py` 与本文件(`SKILL.md`)位于同一目录。执行时:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to read files, invoke a Python script, and access remote HTTP endpoints, but it declares no explicit tool scope or permission boundaries. This creates a least-privilege gap: an agent/runtime may grant broader-than-necessary file, shell, or network access, increasing the blast radius if the skill is misused, the routing logic is manipulated, or a sub-skill/run.py behaves unexpectedly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and usage examples are written entirely in Chinese, and the runtime error/help messages are also Chinese-only. Under the policy, forcing a specific language without opt-in or a documented region-specific justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · run.py (reported line 40)May include surrounding context.

python
print(f"错误:未找到 subskill '{subskill}',路径不存在:{handler}", file=sys.stderr)
        sys.exit(1)

    result = subprocess.run(
        [sys.executable, handler] + sys.argv[2:],
        cwd=SKILL_ROOT,
    )

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The description lists activation phrases such as “信贷数据”, “中国信贷”, and “社会融资” without clarifying scope, exclusion conditions, or negative examples. These terms are broad enough that the skill could be invoked for general discussion of Chinese credit or social financing rather than specifically for this monthly data endpoint.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill description says to use the skill when the user asks about terms including "中国财政收入", "财政收支", and "fiscal revenue", but it does not define exclusions or clarify when adjacent topics should not invoke this skill. Phrases like "财政收支" are broad enough to overlap with broader fiscal balance or expenditure discussions, which can cause unintended activation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger description includes broad terms like “固定资产投资”, “固投”, “中国投资”, and “China fixed asset investment”, which can cause the agent to invoke this narrow monthly China urban fixed-asset-investment skill for generic investment-related questions. This can lead to incorrect skill routing, irrelevant data retrieval, and misleading answers when the user intended a different investment concept, market, geography, or timeframe.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill content and usage instructions are entirely in Chinese and the trigger description centers on Chinese terms, with no indication that users may request output in another language. This can violate language/locale policy when a skill implicitly forces a specific language without explicit user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The module docstring is written only in Chinese, indicating a fixed language/locale expectation in the skill's natural-language description. Under the policy, locale-specific behavior should either offer user opt-in or clearly document a justified regional constraint; neither is present in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The module docstring is entirely in Chinese, which indicates a fixed language choice without offering any user language or locale option. Under the policy, forcing a specific language without opt-in can be a natural-language policy violation unless the locale restriction is clearly documented and justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description says to use the skill when a user asks about broad terms like "房贷利率" and "China LPR" without clarifying boundaries or exclusions. This can cause unintended invocation for general mortgage-rate discussions or broader China rate questions that are not specifically about the LPR monthly dataset.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The natural-language instructions and usage notes are presented only in Chinese, which effectively forces a specific language for users or maintainers without an explicit opt-in. The file does not state that the skill is intentionally region- or language-specific, nor does it offer an alternative language.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger description includes broad terms such as '工业品价格', which can match user requests that are not specifically about China's monthly PPI series. This can cause the agent to invoke the wrong skill and return misleading economic data, reducing reliability and potentially contaminating downstream analysis or decision-making.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest description says to use the skill when the user asks about terms like “中国消费” and “消费零售,” which are broad phrases that could match many general economic or consumer-topic conversations beyond this specific monthly retail-sales dataset. The trigger list also lacks explicit scope boundaries or negative examples to clarify when the skill should not activate.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description says to use the skill when the user asks about "税收收入" and "中国税收," which are broad topic phrases rather than narrowly scoped invocation triggers. Without clearer boundaries or exclusion examples, the skill could be invoked for many general tax-policy or tax-system questions rather than specifically monthly national tax revenue data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill content and usage instructions are entirely in Chinese, and the description mixes English trigger text with Chinese output expectations without stating that users may choose another language. This can violate a language/locale policy when a skill effectively constrains interaction to a specific language without opt-in or justification.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The description says to use the skill when the user asks about broad phrases like "CPI" and "China CPI" without giving exclusion conditions or negative examples. Because "CPI" can be used in multiple contexts, the trigger guidance may cause unintended invocation outside the intended monthly China consumer price index use case.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring is a user-visible natural-language label written only in Chinese, which can impose a specific language without user opt-in. The file does not indicate that the skill is region-specific or provide an alternative language/localization choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code makes an outbound HTTP request to retrieve data but does not include a user-facing notice, comment, or docstring explaining that network access occurs. For code files, network calls that transmit or retrieve data should have some visible disclosure unless the behavior is clearly documented as part of the skill's purpose within the file or accompanying markdown.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code performs an HTTP request to an external service using urllib.request.urlopen, which transmits system/request metadata to a remote endpoint. While the script's purpose appears to fetch GDP data, the code itself provides no user-facing notice beyond printing the response, and there is no inline warning or explanatory comment about the external network access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The only natural-language description in the file is entirely in Chinese, which may impose a language expectation without offering user opt-in or explaining that the skill is intentionally locale-specific. Under the policy, language constraints should be optional or clearly justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code makes an outbound HTTP request to an external domain using urllib.request.urlopen, which will at minimum disclose the runtime's IP/user-agent context to that service. The file contains no user-facing prompt, warning comment, or explanatory docstring beyond the title, so the network behavior is not disclosed within this code file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring is entirely in Chinese, which indicates the skill is oriented to a specific language/locale without any visible opt-in or alternative. The policy for this category asks to flag language or locale constraints when they are imposed without user choice or clear justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring presents the skill description only in Chinese, and the CLI help text is also Chinese-only. This can violate a language/locale policy when a skill forces a specific language without user opt-in or documented locale justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.