Back to skill

Security audit

飞书发票报销机器人管理

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-built for managing a Feishu invoice reimbursement bot, but it has review-worthy risks around command execution, secrets exposure, and host modification.

Review this skill before installing. Use it only in a trusted local environment, avoid pasting real Feishu secrets into chat or logs, pin and review dependencies, restrict BOT_DIR to a known safe directory, and do not run the start/config commands with elevated privileges until command construction and secret masking are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
scripts/manage.py:22
Finding
Shell Command Injection Through the BOT_DIR Environment Variable<![CDATA[ ## Vulnerability Details **File Location**: `scripts/manage.py`, lines 22 and 56-64 **Vulnerability Type**: OS command injection **Risk Level**: High ### Evidence ```python BOT_DIR = Path(os.environ.get("BOT_DIR", str(_DEFAULT_BOT_DIR))) ``` ```python cmd = ( f"cd {BOT_DIR} && " f"python3 {ORCHESTRATOR} >> {LOG_FILE} 2>&1" ) result = subprocess.run( ["tmux", "new-session", "-d", "-s", TMUX_SESSION, cmd], capture_output=True, text=True, ) ``` ### Technical Analysis `BOT_DIR` is obtained from an environment variable and interpolated directly into a command string without validation or shell quoting. The string is supplied to `tmux new-session` as the session command. Tmux executes such command strings through a shell, so shell metacharacters in `BOT_DIR` are interpreted as command syntax rather than as part of a directory name. Although `subprocess.run` itself receives an argument list, this does not prevent injection because the final argument is subsequently interpreted as a shell command by tmux. ### Attack Path 1. An attacker gains control over the environment used to invoke the management script, or persuades an operator or Agent to configure a malicious `BOT_DIR`. 2. The attacker assigns a value containing shell syntax, for example: ```bash export BOT_DIR='/tmp/nonexistent; touch /tmp/invoice-bot-compromised #' ``` 3. The operator or Agent invokes: ```bash python3 scripts/manage.py start ``` 4. The generated command becomes equivalent to: ```bash cd /tmp/nonexistent; touch /tmp/invoice-bot-compromised # && python3 invoice_orchestrator.py ... ``` 5. Tmux passes the command to a shell, which executes the injected command. ### Impact Assessment Successful exploitation provides arbitrary command execution with the privileges of the user running `manage.py`. An attacker could read or modify files available to that user, access Feishu credentials in `.env`, alter the external invoice bot, submit ...[truncated 225 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not construct a shell command containing `BOT_DIR`. - Launch the orchestrator directly with an argument array and set its working directory through `cwd`. - If tmux is required, invoke a fixed wrapper script whose path and arguments are not interpreted as shell syntax. - If a shell command cannot be avoided, apply `shlex.quote` separately to every dynamic path. Quoting should be defense in depth rather than the primary design. - Resolve the path with `Path.resolve()`, require it to be an existing directory, and verify that `invoice_orchestrator.py` is a regular file in that directory. - Where deployment permits, restrict `BOT_DIR` to an approved base directory or exact configured path. - Add tests using values containing spaces, semicolons, command substitutions, redirections, and newline characters. A safer direct-process design would resemble: ```python subprocess.Popen( ["python3", str(BOT_DIR / ORCHESTRATOR)], cwd=BOT_DIR, stdout=log_handle, stderr=subprocess.STDOUT, ) ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/manage.py:155
Finding
Plaintext Disclosure of Sensitive Configuration Values<![CDATA[ ## Vulnerability Details **File Location**: `scripts/manage.py`, lines 155-180 **Vulnerability Type**: Sensitive information exposure **Risk Level**: Medium ### Evidence The single-key lookup path prints the entire matching environment entry: ```python elif key: content = ENV_FILE.read_text() for line in content.splitlines(): if line.startswith(f"{key}="): print(line) return print(f"⚠️ 未找到配置项: {key}") ``` The update path also prints the newly supplied key and plaintext value after writing it: ```python ENV_FILE.write_text("\n".join(new_lines) + "\n") print(f"✅ 已更新: {key}={value}") ``` ### Technical Analysis The no-argument configuration listing attempts to mask entries containing `SECRET`, but the protection is inconsistent: - Requesting one specific key prints the complete `KEY=value` entry. - Updating a key echoes the complete new value. - The sensitive-key check in the general listing is case-sensitive and only recognizes names containing `SECRET`. Consequently, credentials such as `FEISHU_APP_SECRET` can be exposed in terminal output, Agent transcripts, CI logs, shell-session recordings, or any system collecting process output. ### Attack Path 1. The bot has a populated `.env` containing `FEISHU_APP_SECRET` or another credential. 2. A user, automation process, or Agent invokes: ```bash python3 scripts/manage.py config FEISHU_APP_SECRET ``` 3. The script reads the `.env` file and prints the complete secret. 4. Alternatively, setting a secret through the command echoes its plaintext value: ```bash python3 scripts/manage.py config FEISHU_APP_SECRET supplied-secret-value ``` 5. Anyone with access to the resulting terminal output, transcript, or logs can recover the credential. ### Impact Assessment Exposure of `FEISHU_APP_SECRET` may permit unauthorized use of the associated Feishu application, subject to the application's configured permissions and any additional platform c ...[truncated 383 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never print secret values when retrieving or updating configuration. - Apply one centralized, case-insensitive sensitive-key policy to every output path. - Treat names containing terms such as `SECRET`, `TOKEN`, `PASSWORD`, `PRIVATE_KEY`, `API_KEY`, and `CREDENTIAL` as sensitive. - For sensitive keys, print only confirmation that the value exists or was updated. - Consider displaying a short fingerprint, such as a cryptographic hash prefix, when operators need to distinguish configured values. - Accept sensitive updates through protected standard input or a secure secret manager rather than command-line arguments, because command-line arguments may be captured in shell history or process listings. - Ensure `.env` is created with restrictive permissions such as mode `0600`. - Review historical logs and transcripts for previously disclosed credentials and rotate any exposed values. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:66
Finding
Unpinned Third-Party Dependencies and Dynamically Resolved Package Execution<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 66-71 and 167-168 **Vulnerability Type**: Software supply-chain weakness **Risk Level**: Medium ### Evidence ```bash pip install paddlepaddle paddleocr easyocr lark-oapi pdf2image pyzbar Pillow python-dotenv ``` ```bash npm install -g @larksuite/cli npx skills add larksuite/cli -y -g lark-cli config init ``` ### Technical Analysis The documented installation commands do not pin package versions or verify artifact integrity. Each installation therefore resolves whichever package version is current at execution time. The `npx` command is particularly sensitive because it can dynamically resolve and execute package tooling. Global npm installation also increases the scope of any compromised package by placing executable components in the user's global environment. No evidence shows that the named packages are currently malicious. The vulnerability is the absence of reproducible, integrity-controlled dependency resolution, which leaves installation behavior dependent on mutable external registries. ### Attack Path 1. An operator follows the installation instructions. 2. Pip, npm, or npx queries an external package registry for the latest matching releases. 3. A package account, release, transitive dependency, or registry response has been compromised, or a future incompatible release introduces unsafe behavior. 4. The package manager downloads and installs the resolved artifact without comparison to a repository-controlled hash or lockfile. 5. Installation hooks or subsequently executed package code run with the operator's privileges. ### Impact Assessment A compromised dependency could execute code with the privileges of the installing or running user. Potential consequences include theft of Feishu credentials, modification of the invoice bot, tampering with OCR or approval data, and compromise of files accessible to that account. Global installation can affect commands outside this ...[truncated 155 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every direct dependency to a reviewed exact version. - Store Python dependencies in a requirements or lock file and include cryptographic hashes where supported. - Use a committed npm lockfile and execute package tooling from a reviewed project dependency rather than dynamically resolving it with an unpinned `npx` command. - Avoid global package installation where possible; install dependencies in an isolated virtual environment or project-local Node.js environment. - Pin and review transitive dependencies. - Use trusted registries, dependency-scanning automation, and update review procedures. - Document a controlled upgrade process so version changes are tested before deployment. - Where package signatures or provenance attestations are available, verify them during installation. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/manage.py:29
Finding
Bot Start Operation Performs Undeclared Automatic System Package Installation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/manage.py`, lines 29-43 **Vulnerability Type**: Unexpected host modification **Risk Level**: Low ### Evidence ```python if subprocess.run(["which", "tmux"], capture_output=True).returncode == 0: return True ``` ```python result = subprocess.run( ["brew", "install", "tmux"], capture_output=True, text=True, ) ``` ### Technical Analysis The `start` action calls `_ensure_tmux()`. If tmux is absent, the function automatically invokes Homebrew to install it. Starting an application is normally expected to validate prerequisites rather than modify the host's package inventory. Although `SKILL.md` declares tmux as a required binary, it does not clearly disclose that invoking `start` performs package installation. There is no explicit confirmation, dry-run mode, version pin, or separation between package installation and bot lifecycle management. The command uses a fixed argument array and is not itself vulnerable to shell injection. The security issue is the unexpected execution of an external package-management operation. ### Attack Path 1. The host has Homebrew but does not have tmux. 2. An operator or Agent invokes: ```bash python3 scripts/manage.py start ``` 3. `_ensure_tmux()` detects that tmux is missing. 4. Without obtaining explicit confirmation, the script runs: ```bash brew install tmux ``` 5. Homebrew resolves and installs packages and may execute installation logic under the invoking user's account. ### Impact Assessment The operation modifies the host and executes externally obtained package installation logic. Its privileges are limited to those available to the invoking user and Homebrew configuration. It may change the user's package environment, install transitive components, consume network and disk resources, or introduce behavior not anticipated from a bot start command. There is no evidence that this mechanism provides persistence or privileg ...[truncated 29 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove automatic package installation from the `start` path. - If tmux is unavailable, terminate with a clear prerequisite error and provide a separate installation instruction. - If automated installation is required, implement it as an explicit `install-dependencies` action. - Require interactive confirmation before modifying the host, with a noninteractive opt-in flag for controlled automation. - Document the network access and host changes that installation performs. - Pin or otherwise control the installed version where the package manager permits it. - Prefer a design that does not require tmux, such as direct process supervision by an existing service manager selected by the operator. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents this skill as a management interface for a Feishu/Lark invoice reimbursement bot, including operational controls and administrative tasks. The supplied code instead is a standalone script `test_ocr.py` whose purpose is to test OCR on a single invoice file, optionally output JSON, and perform QR verification. While the description does mention OCR debugging/testing, that is only one subset of the declared scope. The main code shown does not start or stop an agent, monitor a running bot, modify configuration, or inspect approval templates, nor does it interact with Feishu APIs or CLI management functions. Therefore the code materially underdelivers and has a different primary purpose from the declared skill description.

Credential Access

High
Category
Privilege Escalation
Content
LOG_FILE = BOT_DIR / "invoice_bot.log"
TMUX_SESSION = "invoice-bot"
ORCHESTRATOR = "invoice_orchestrator.py"
ENV_FILE = BOT_DIR / ".env"


def _ensure_tmux():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def cmd_config(key: str = None, value: str = None):
    """查看或修改 .env 配置"""
    if not ENV_FILE.exists():
        print(f"⚠️ .env 文件不存在: {ENV_FILE}")
        return
Confidence
88% confidence
Finding
The command is explicitly designed to view or modify the .env file, which contains operational secrets. In a local admin script this may be intentional, but when packaged as an agent skill, exposing credential-bearing configuration through a management interface meaningfully increases the risk of unauthorized secret access or tampering.

Credential Access

High
Category
Privilege Escalation
Content
def cmd_config(key: str = None, value: str = None):
    """查看或修改 .env 配置"""
    if not ENV_FILE.exists():
        print(f"⚠️ .env 文件不存在: {ENV_FILE}")
        return

    if key and value:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill describes shell execution, environment-variable access, file reads, and file writes, but it does not declare an explicit permission or allowed-tools scope. That creates an under-specified trust boundary: a caller may invoke a skill that can manipulate bot processes, credentials, and configuration files without any machine-readable restriction or review gate.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill processes invoice images/PDFs and submits approval data through Feishu services, but it does not clearly disclose that potentially sensitive financial documents and metadata are transmitted to third-party services. This omission undermines informed consent and can create privacy, compliance, or data-handling risks for invoices that contain personal or corporate financial information.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill instructs users to configure and handle sensitive values such as `FEISHU_APP_SECRET` and to edit `$BOT_DIR/.env`, but it does not warn about credential exposure, secret storage hygiene, or the risks of modifying configuration files. In practice, this can lead users to paste secrets into chat, logs, shell history, or world-readable files, increasing the chance of credential compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding
Using `npx skills add larksuite/cli -y -g` without a pinned version makes installation non-reproducible and exposes users to supply-chain risk if the upstream package changes or is compromised. Because this skill manages a bot with access to invoices and Feishu credentials, a malicious or broken update could execute code during setup with meaningful access.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding
The dependency section again references `npx skills add larksuite/cli -y -g` without pinning a version, repeating the same supply-chain exposure. Repetition in installation docs increases the chance users will follow the unsafe pattern in production setups.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The file explicitly instructs that invoice images be uploaded to Feishu approval attachments and file codes written into a field, which affects user data and privacy. The markdown contains no warning or disclosure that sensitive invoice information and attachments will be transmitted to an external approval system.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The guide shows how to retrieve and use a Feishu App Secret but does not warn that it is a sensitive credential, should never be committed to files/screenshots, and must be protected from logs or chat transcripts. In a skill focused on managing an invoice/OCR reimbursement bot, these credentials can enable unauthorized API access to messages, files, and approval workflows if mishandled.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
Automatically installing tmux exceeds the declared scope of start/stop/monitor behavior and silently mutates the host system. This widens the attack surface and can violate least surprise and least privilege, especially for an agent skill expected to perform bounded operational tasks.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _ensure_tmux():
    """检查 tmux 是否可用,不可用时尝试安装"""
    if subprocess.run(["which", "tmux"], capture_output=True).returncode == 0:
        return True
    print("⏳ tmux 未安装,正在尝试安装...")
    result = subprocess.run(
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if subprocess.run(["which", "tmux"], capture_output=True).returncode == 0:
        return True
    print("⏳ tmux 未安装,正在尝试安装...")
    result = subprocess.run(
        ["brew", "install", "tmux"],
        capture_output=True, text=True,
    )
Confidence
93% confidence
Finding
The script automatically installs tmux via Homebrew when it is missing. For a management utility, invoking a package manager changes system state and executes externally provided software, which expands the tool's privilege and trust boundary beyond simple bot lifecycle management. In this skill context, that is riskier because the agent is supposed to manage an invoice bot, not modify the host environment.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
f"cd {BOT_DIR} && "
        f"python3 {ORCHESTRATOR} >> {LOG_FILE} 2>&1"
    )
    result = subprocess.run(
        ["tmux", "new-session", "-d", "-s", TMUX_SESSION, cmd],
        capture_output=True, text=True,
    )
Confidence
97% confidence
Finding
The tmux session is started with a single shell command string built from BOT_DIR and log path values derived from environment/configurable paths. Because tmux executes the command through a shell, a malicious BOT_DIR value containing shell metacharacters could trigger command injection and arbitrary code execution. The skill context makes this more dangerous because it is an admin-style bot management script that may be run with elevated local privileges.

Tainted flow: 'cmd' from os.environ.get (line 61, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
f"cd {BOT_DIR} && "
        f"python3 {ORCHESTRATOR} >> {LOG_FILE} 2>&1"
    )
    result = subprocess.run(
        ["tmux", "new-session", "-d", "-s", TMUX_SESSION, cmd],
        capture_output=True, text=True,
    )
Confidence
98% confidence
Finding
This is a true tainted-data issue: BOT_DIR is sourced from the BOT_DIR environment variable and interpolated into a shell-like command passed to tmux. If an attacker can influence the environment, they can inject additional shell syntax and execute arbitrary commands, potentially gaining code execution under the privileges of the operator running the script.

Tainted flow: 'PID_FILE' from os.environ.get (line 25, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
pid = get_pid()
    if pid:
        with open(PID_FILE, "w") as f:
            f.write(str(pid))
        print(f"✅ 机器人已启动 (tmux session: {TMUX_SESSION}, PID: {pid})")
    else:
Confidence
90% confidence
Finding
PID_FILE is derived from BOT_DIR, which comes from an environment variable, so the script can be tricked into writing a PID file to an attacker-chosen location. If run with elevated privileges, this becomes an arbitrary file write primitive that can overwrite or create files outside the intended bot directory. In this admin skill context, operator-run scripts are more likely to have access to sensitive filesystem locations.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
pass

    # 强制关闭 tmux session
    subprocess.run(
        ["tmux", "kill-session", "-t", TMUX_SESSION],
        capture_output=True,
    )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
print("❌ 机器人未运行")

    # 2. 飞书 CLI 连接
    result = subprocess.run(
        ["lark-cli", "auth", "status"],
        capture_output=True, text=True, timeout=10,
    )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The config command exposes environment configuration with insufficient safeguards and no strong warning, making accidental secret leakage likely. Because this script manages an invoice reimbursement bot, the .env may contain bot tokens, tenant credentials, webhook endpoints, or OCR service secrets, so disclosure could enable takeover or unauthorized API access.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The code claims to hide secrets but only masks lines containing the literal string 'SECRET'. Many sensitive .env values such as tokens, API keys, app IDs, webhook URLs, database passwords, or credentials under other names will be printed in full, leading to credential disclosure. This is especially dangerous in a bot-management skill where operators are likely to inspect configuration during debugging and may paste output into chats or tickets.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def check_running() -> bool:
    """检查机器人是否在运行"""
    # 检查 tmux session
    result = subprocess.run(
        ["tmux", "has-session", "-t", TMUX_SESSION],
        capture_output=True,
    )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This is a natural-language policy concern because the skill presents its usage instructions exclusively in a single language, which can force a locale on users without opt-in. The file does not indicate that the tool is restricted to a Chinese-speaking environment or provide an alternative language option.

Natural-Language Policy Violations

Low
Confidence
74% confidence
Finding
The skill description and trigger phrases are entirely Chinese-focused, centered on Chinese invoice reimbursement workflows, with no indication that users may opt into another language or locale. For SQP-3, a language or locale constraint should either offer user choice or be explicitly documented and justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
All headings, field names, and instructions are presented only in Chinese, with no note that the skill is region-specific or that users can choose another language. Under the stated policy, forcing a single language without opt-in can be a natural-language policy violation.

Static analysis

No suspicious patterns detected.