Back to skill

Security audit

多项目报价对比看板(Multi-Project Quote Board)

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed local report generator, but users should review the bundled Python scripts before running them on real quote data.

Install only if you are comfortable running the bundled Python scripts. Review any copied gen_board.py before running gen_excel.py, because the Excel generator executes the Python data-layer section. Also verify the configured deadline and output filenames before using the generated board for procurement decisions.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Dangerous chain: exec() wrapping compile

Critical
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

The script reads Python source from gen_board.py, slices part of it, then compiles and executes it with exec(). That means any code placed in the so-called data layer of gen_board.py will run when generating Excel, turning a report-generation helper into an arbitrary code execution path if the sibling file is modified, replaced, or supplied from an untrusted source.

Content

Scanner excerpt · scripts/gen_excel.py (reported line 25)May include surrounding context.

python
raise SystemExit("data-layer marker not found in gen_board.py")
_data_src = _src.split(MARK)[0]
ns = {}
exec(compile(_data_src, "gen_board_data", "exec"), ns)

PROJECTS = ns["PROJECTS"]; SUPPLIERS = ns["SUPPLIERS"]; QUOTES = ns["QUOTES"]
TERMS = ns["TERMS"]; CLAR = ns["CLAR"]; TRANS_NOTE = ns["TRANS_NOTE"]

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

For an Excel report generator, executing arbitrary Python from a sibling file exceeds the minimum capability needed and creates an unjustified attack surface. The skill context makes this more dangerous, not less, because users expect deterministic document generation, not hidden code execution inherited from a parsed source file.

Content

No source excerpt is available for this finding.

exec() call detected

High
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This exec() invocation executes code derived from file contents rather than a fixed in-memory literal. In the context of a quoting/report skill, there is no strong justification for runtime evaluation of source text, so this creates an unnecessary arbitrary code execution sink tied to local file contents.

Content

Scanner excerpt · scripts/gen_excel.py (reported line 25)May include surrounding context.

python
raise SystemExit("data-layer marker not found in gen_board.py")
_data_src = _src.split(MARK)[0]
ns = {}
exec(compile(_data_src, "gen_board_data", "exec"), ns)

PROJECTS = ns["PROJECTS"]; SUPPLIERS = ns["SUPPLIERS"]; QUOTES = ns["QUOTES"]
TERMS = ns["TERMS"]; CLAR = ns["CLAR"]; TRANS_NOTE = ns["TRANS_NOTE"]

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.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The table header says the feasibility check is "10/31 前?" / "By deadline?", but the actual deadline used everywhere in computation is LEAD_DEADLINE = 2026-02-28. This is an active documentation/UI contradiction that can mislead users about the basis for the recommendation even though the code logic uses the February deadline.

Content

No source excerpt is available for this finding.

compile() call detected

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

compile() is being used as part of a dynamic execution chain on text read from disk, which is dangerous because it prepares attacker-controlled source for execution. While compile() alone is not always a vulnerability, here it directly enables the exec-based code execution path.

Content

Scanner excerpt · scripts/gen_excel.py (reported line 25)May include surrounding context.

python
raise SystemExit("data-layer marker not found in gen_board.py")
_data_src = _src.split(MARK)[0]
ns = {}
exec(compile(_data_src, "gen_board_data", "exec"), ns)

PROJECTS = ns["PROJECTS"]; SUPPLIERS = ns["SUPPLIERS"]; QUOTES = ns["QUOTES"]
TERMS = ns["TERMS"]; CLAR = ns["CLAR"]; TRANS_NOTE = ns["TRANS_NOTE"]

Tainted flow: '_data_src' from open (line 23, file read) → exec (code execution)

Medium
Category
Data Flow
Confidence
97% confidence
Finding

There is a clear tainted flow from file input (_src/_data_src read from gen_board.py) into exec(), allowing file contents to control executed code. If an attacker can influence gen_board.py through supply-chain compromise, repository write access, or packaging manipulation, running gen_excel.py will execute their payload.

Content

Scanner excerpt · scripts/gen_excel.py (reported line 25)May include surrounding context.

python
raise SystemExit("data-layer marker not found in gen_board.py")
_data_src = _src.split(MARK)[0]
ns = {}
exec(compile(_data_src, "gen_board_data", "exec"), ns)

PROJECTS = ns["PROJECTS"]; SUPPLIERS = ns["SUPPLIERS"]; QUOTES = ns["QUOTES"]
TERMS = ns["TERMS"]; CLAR = ns["CLAR"]; TRANS_NOTE = ns["TRANS_NOTE"]

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The markdown states '默认中文' as the default language behavior. Under the policy, forcing a specific language without user opt-in can be a locale/language policy issue, and this line does not indicate consent or preference detection before choosing Chinese by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file contains user-facing natural-language guidance exclusively in Chinese, and there is no indication that the skill is intentionally limited to Chinese-speaking users or a China-specific workflow. Under the language/locale policy rule, forcing a single language without user opt-in can be a policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The generated HTML sets lang="zh" and later defaults the language toggle to Chinese, making a specific locale the initial experience. Although English is available as a toggle, the file imposes a default language choice rather than asking the user to choose first.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The lzh radio input is marked checked, which means the skill defaults to Chinese content until the user actively switches to English. This is a locale preference decision embedded in the skill rather than an explicit user opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code unconditionally writes board.html to disk, which is a file-modifying operation covered by the warning rule for code files. While the module docstring states the usage and implies generation of board.html, there is no nearby confirmation prompt or explicit caution that running the script will overwrite/create that file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code performs a file write by saving board.xlsx to the current working directory. Although it logs after completion, there is no warning before the write occurs, and the top-level docstring only states usage rather than disclosing that an existing file may be overwritten.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.