Back to skill

Security audit

世界杯日历同步

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-aligned, but it can globally install an unpinned external CLI and perform real Feishu calendar writes or deletions, so users should review it before installing.

Install only if you are comfortable granting Feishu calendar access and running lark-cli locally. Prefer installing a verified, pinned lark-cli version yourself instead of using doctor --install-cli, preview sync and delete operations before adding --execute, and be especially careful with --all and --delete-calendar because they can remove calendar data.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T08 · Insecure Dependencies

Warning
Location
scripts/world_cup_calendar.py:118
Finding

Unpinned Global Installation of a Third-Party CLI Package

Content
View full analysis

Vulnerability Details

File Location: scripts/world_cup_calendar.py:17, 118-130
Vulnerability Type: Unpinned executable dependency installed globally
Risk Level: Medium

Vulnerable Code

python
LARK_CLI_PACKAGE = "@larksuite/cli"
python
def install_lark_cli() -> None:
    if not shutil.which("npm"):
        print("没有找到 npm,暂时不能自动安装 lark-cli。")
        print("请先安装 Node.js LTS:https://nodejs.org/")
        return

    print(f"开始安装飞书 CLI:npm install -g {LARK_CLI_PACKAGE}")
    completed = subprocess.run(["npm", "install", "-g", LARK_CLI_PACKAGE], text=True)
    if completed.returncode != 0:
        print("安装失败。可以手动执行:")
        print(f"npm install -g {LARK_CLI_PACKAGE}")
        raise SystemExit(completed.returncode)
    print("飞书 CLI 安装完成。")

The same unpinned installation is recommended in README.md:39-49 and SKILL.md:32-36, 105-109.

Technical Analysis

The doctor --install-cli operation installs @larksuite/cli without specifying an exact version or verifying package integrity. npm therefore resolves whichever package version is currently selected by the registry and may run its lifecycle scripts with the privileges of the user executing the Skill.

This makes the effective installed code mutable after the Skill has been audited. Although there is no evidence that the referenced package is currently malicious, compromise of the package, its maintainer account, the registry resolution path, or a future release could introduce arbitrary code without any change to this repository. The use of a global installation also expands the effect beyond this project and may replace an existing system-wide lark-cli executable.

Attack Path

  1. An attacker compromises the npm package, a maintainer account, or the package distribution process.
  2. A malicious release becomes the version resolved for @larksuite/cli.
  3. The user runs:
    bash
    python3 scripts/w
    

...[truncated 983 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the dependency to an exact, reviewed version:
    python
    LARK_CLI_PACKAGE = "@larksuite/cli@X.Y.Z"
    
  2. Verify the expected npm registry and package integrity before installation. Record and validate the package tarball integrity hash.
  3. Prefer a project-local or isolated installation rather than npm install -g, so the dependency cannot replace system-wide tooling.
  4. Separate environment diagnosis from dependency installation. Require an explicit confirmation that states the package version, source, destination, and security implications.
  5. Consider removing automatic installation entirely and provide version-pinned manual installation instructions.
  6. Document a reviewed version allowlist and reject versions outside it.
  7. Where operationally feasible, disable npm lifecycle scripts during installation and verify that the package functions without them:
    bash
    npm install --ignore-scripts --save-exact @larksuite/cli@X.Y.Z
    
  8. Re-audit and update the pinned dependency deliberately rather than resolving new releases automatically.

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/world_cup_calendar.py:96
Finding

Security-Sensitive CLI Execution Through a Mutable PATH

Content
View full analysis

Vulnerability Details

File Location: scripts/world_cup_calendar.py:96-105
Vulnerability Type: Executable search-path hijacking
Risk Level: Medium

Vulnerable Code

python
def run_lark(args: list[str]) -> dict:
    cmd = ["lark-cli", *args]
    completed = subprocess.run(cmd, text=True, capture_output=True)
    if completed.returncode != 0:
        message = completed.stderr.strip() or completed.stdout.strip()
        raise RuntimeError(message)
    try:
        return json.loads(completed.stdout)
    except json.JSONDecodeError:
        return {"raw": completed.stdout}

The script separately discovers and displays the executable path at scripts/world_cup_calendar.py:137-143, but does not retain or validate that path for subsequent calls:

python
lark_path = shutil.which("lark-cli")
lark_version = command_version("lark-cli")
print(f"- lark-cli:{lark_version or '未安装'}")
if lark_path:
    print(f"  路径:{lark_path}")

Technical Analysis

Every operational call invokes the bare executable name lark-cli. The operating system consequently resolves the executable using the current PATH at execution time. An attacker who can place a malicious executable in an earlier searched directory—or influence the environment used to launch the Skill—can cause the script to execute that program instead of the intended Feishu CLI.

Passing arguments as a list correctly prevents shell metacharacter injection, but it does not protect against executable substitution. The diagnostic path lookup does not mitigate the issue because the resolved path is only printed and is neither validated nor passed to subprocess.run.

This CLI is security-sensitive: it is used to list, create, and delete calendars and events under the user's identity. A spoofed executable receives the complete command arguments and runs with the same local privileges as the Skill.

Attack Path

  1. An attacker gai ...[truncated 1673 chars]
Remediation
View remediation

Remediation Suggestions

  1. Resolve lark-cli once to an absolute path before any operation:
    python
    LARK_CLI_PATH = shutil.which("lark-cli")
    if not LARK_CLI_PATH:
        raise RuntimeError("lark-cli was not found")
    
  2. Pass that absolute path to every subprocess invocation:
    python
    cmd = [LARK_CLI_PATH, *args]
    
  3. Validate that the path is an expected regular executable file and is not located in a world-writable or untrusted directory.
  4. Verify the executable's owner, permissions, version, and cryptographic checksum against an administrator-approved allowlist.
  5. Fail closed if the resolved executable changes between environment validation and execution.
  6. Use a controlled subprocess environment with a minimal trusted PATH, rather than inheriting an arbitrary caller-controlled search path.
  7. If the CLI is installed locally for this project, reference the known project-local absolute path instead of relying on global command resolution.
  8. Continue using argument-list subprocess execution and avoid introducing shell=True.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared purpose focuses on syncing World Cup matches to a Feishu calendar, but the documented behavior also includes installing software, deleting events, and deleting an entire calendar. This mismatch is dangerous because users may authorize or run the skill expecting additive calendar sync only, while it also contains destructive and environment-modifying capabilities.

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
使用 `scripts/world_cup_calendar.py` 读取内置赛程数据,并把比赛转换成飞书日程。

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README describes the sync flow and mentions '全部 104 场比赛' earlier, but around the execution step it does not prominently warn that the first real run can bulk-create up to 104 calendar events in the user's Feishu account. This can cause unintended data modification, notification noise, and calendar clutter if the user executes the command without fully understanding the scale of the write operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The deletion section includes commands for deleting selected matches, all 104 events, or the entire world-cup-calendar calendar, but lacks a strong, prominent warning about irreversible data loss. Users may copy-paste --all --execute or --delete-calendar --execute and permanently remove calendar data, especially because the README presents these commands in a routine instructional style.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes local scripts, reads bundled data, and directs use of shell commands and external CLIs, but it declares no explicit tool scope or permission boundaries. That makes the runtime capabilities opaque to users and reviewers, increasing the chance of unintended shell execution or file access beyond what the skill’s description suggests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The markdown states that the script will output Chinese prompts from lark-cli, and the overall skill content is written entirely in Chinese without indicating any user language choice or opt-in. This can violate language/locale policy when a skill implicitly enforces a specific language rather than offering localization choice.

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 · scripts/world_cup_calendar.py (reported line 99)May include surrounding context.

python
def run_lark(args: list[str]) -> dict:
    cmd = ["lark-cli", *args]
    completed = subprocess.run(cmd, text=True, capture_output=True)
    if completed.returncode != 0:
        message = completed.stderr.strip() or completed.stdout.strip()
        raise RuntimeError(message)

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 · scripts/world_cup_calendar.py (reported line 112)May include surrounding context.

python
def command_version(command: str, version_arg: str = "--version") -> str | None:
    if not shutil.which(command):
        return None
    completed = subprocess.run([command, version_arg], text=True, capture_output=True)
    if completed.returncode != 0:
        return "已安装,但读取版本失败"
    return (completed.stdout or completed.stderr).strip()

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
81% confidence
Finding

This line performs a global npm installation of an external package at runtime, which executes code from the package supply chain with the user's privileges. In the skill context, this is more dangerous because the script is framed as a helper utility and can prompt users to install tooling automatically, expanding trust to npm registry content and any dependency compromise or typosquatting event.

Content

Scanner excerpt · scripts/world_cup_calendar.py (reported line 125)May include surrounding context.

python
return

    print(f"开始安装飞书 CLI:npm install -g {LARK_CLI_PACKAGE}")
    completed = subprocess.run(["npm", "install", "-g", LARK_CLI_PACKAGE], text=True)
    if completed.returncode != 0:
        print("安装失败。可以手动执行:")
        print(f"npm install -g {LARK_CLI_PACKAGE}")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file presents all user-facing documentation in Chinese and does not indicate that other languages are available or that Chinese is optional. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The top-level source note states '抽取日期:2026-06-19', implying this JSON reflects an extraction performed on that date. However, all match records cite 'FIFA official match schedule PDF, 2026-04-10' as their source, which contradicts the extraction/date provenance described in the metadata rather than merely omitting detail.

Content

No source excerpt is available for this finding.