Back to skill

Security audit

dabai/finance-news-brief

Security checks for vulnerabilities and agentic risk

Overview

This finance brief skill has a clear purpose, but it needs Review because it can automatically search the web, create files, install a Python package, and run Chrome with weakened isolation.

Install only if you are comfortable with a finance-report skill that performs web research, writes report files, runs a local Python script, may install a Python package automatically, and uses headless Chrome with reduced sandboxing. Prefer reviewing the script first, preinstalling pinned dependencies in an isolated environment, and confirming output paths before use.

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

T08 · Insecure Dependencies

Warning
Location
scripts/generate_pdf.py:20
Finding

Automatic Installation of an Unpinned Runtime Dependency

Content
View full analysis
str: install_if_missing("markdown") ``` ### Technical Analysis The PDF generator automatically invokes `pip` when the `markdown` module is unavailable. The package version is not pinned, no package hash is verified, and no lock file or isolated environment is used. Package resolution may also be affected by the invoking environment's pip configuration, configured indexes, or package mirrors. Python packages can execute code during installation. Consequently, the script treats mutable content retrieved from a package repository as trusted executable code. Automatic environment modification is not required for Markdown-to-PDF conversion and exceeds the minimum privileges necessary for the declared functionality. This is not direct evidence that the named `markdown` package is malicious. The vulnerability is the unsafe dependency acquisition mechanism and its exposure to repository compromise, malicious mirrors, configuration manipulation, and future upstream compromise. ### Attack Path 1. The Skill is invoked on a system where the `markdown` module is not installed or cannot be imported. 2. An attacker compromises or controls a package index, configured mirror, DNS/network path, or relevant pip configuration used by the environment. 3. The script executes `python -m pip install markdown -q` without enforcing a known version or artifact hash. 4. Pip downloads and installs ...[truncated 674 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_pdf.py:50
Finding

Untrusted HTML Rendered by Chrome with Browser Sandbox Disabled

Content
View full analysis
str: install_if_missing("markdown") import sys as _sys import site _sys.path.insert(0, site.getusersitepackages()) import markdown return markdown.markdown( md_text, extensions=["tables", "fenced_code", "nl2br"], ) ``` The directory containing the generated HTML is exposed through a temporary loopback HTTP server, and Chrome is launched with its sandbox disabled: ```python # 1. 起临时 HTTP server,从 html 所在目录服务文件 with socket.socket() as s: s.bind(("127.0.0.1", 0)) http_port = s.getsockname()[1] serve_dir = str(html_path.parent) handler_cls = functools.partial( http.server.SimpleHTTPRequestHandler, directory=serve_dir, ) handler_cls.log_message = lambda *a: None http_server = http.server.HTTPServer(("127.0.0.1", http_port), handler_cls) http_thread = threading.Thread(target=http_server.serve_forever) http_thread.daemon = True http_thread.start() page_url = f"http://127.0.0.1:{http_port}/{html_path.name}" # 2. 找一个空闲的远程调试端口 with socket.socket() as s: s.bind(("127.0.0.1", 0)) debug_port = s.getsockname()[1] # 3. 启动 Chrome,开启远程调试 chrome_proc = subprocess.Popen( [ chrome, "--headless=new", "--disable-gpu", "--no-sandbox", "--disable-extensions", f"--remote-debugging-port={debug_port}", "--no-first-run", "--no-default-browser-check", ], stdout=subprocess.DEVNULL, stderr=su ...[truncated 3304 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

代码的核心功能是一个 PDF 生成脚本:读取指定 Markdown 文件,转为 HTML,套用模板,并调用本地 Chrome 的 DevTools Protocol 输出 PDF。这可以视为声明中“输出正式 PDF 文件(含封面)”这一子能力的部分实现,但远不足以覆盖该 skill 的主要宣称用途。声明的主功能是财经新闻搜集与中文简报生成,而代码没有任何网络抓取/新闻源访问/内容聚合/摘要生成/市场板块分类等逻辑;也没有触发器实现。因此描述与实际行为存在明显的实质性不匹配。

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger rules are overly broad and force activation for common finance-related questions, which can cause the agent to perform network searches, file creation, and PDF generation when a simple conversational answer would suffice. Over-triggering expands the attack surface and may lead to unnecessary tool use without clear user intent for external actions.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill uses network access, file writes, and shell execution but does not declare any explicit tool scope or permission boundaries. This increases the chance of over-privileged execution and makes it harder for a host system or reviewer to constrain risky actions such as writing files or launching Python with dependency installation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description requires generating the brief in Chinese and later instructs that each news item be written as a concise Chinese summary. This is a natural-language locale constraint, but the file does not provide user opt-in, a language choice, or a documented reason that the skill must operate only in Chinese.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs the agent to save Markdown and PDF files into the working directory or another directory without first warning the user that local files will be created. Silent file creation can surprise users, overwrite expected outputs, or place sensitive research artifacts in locations the user did not intend.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill directs execution of a Python script via shell and states that it may install dependencies automatically. Running local commands and performing package installation without upfront warning materially increases risk because it changes the local environment, may fetch unpinned code or binaries, and can fail in unsafe or unexpected ways.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The expected output explicitly requires a "中文财经简报," and similar language appears elsewhere in the evals, but there is no indication that language selection is optional or that the skill is intentionally region-specific. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The eval prompt uses a very broad natural-language trigger ('今天市场有什么大事?帮我搜一下最新财经新闻...') to require mandatory activation of the skill. Broad trigger conditions can cause unintended invocation in loosely related conversations, increasing the chance of unnecessary web access, file generation, and tool execution beyond user intent. In this skill's context, forced activation is more dangerous because the skill performs external search and writes Markdown/PDF files to disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This expected output says the skill should generate a structured Chinese brief, but the prompt itself only asks for a report and does not establish that Chinese must always be used. Without an explicit language preference mechanism or a documented regional purpose, this can violate the language/locale policy.

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 is entirely in Chinese and presents the tool's purpose and usage only in that language. This is a natural-language locale constraint that does not offer the user any language choice or document a justified region-specific limitation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This finding correctly captures that the skill can modify its environment by installing packages on demand. In the context of a report-generation skill, that behavior is unnecessary and expands the attack surface to package-repository compromise, dependency confusion, and unexpected system changes.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/generate_pdf.py (reported line 23)May include surrounding context.

python
def install_if_missing(package: str, import_name=None):
    import_name = import_name or package
    try:
        __import__(import_name)
    except ImportError:
        print(f"正在安装依赖: {package} ...")
        subprocess.check_call([sys.executable, "-m", "pip", "install", package, "-q"])

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

The script automatically executes pip install at runtime. This introduces a supply-chain and arbitrary code execution risk because package installation runs code from external repositories during skill execution, which exceeds the minimum privileges expected for a PDF conversion helper.

Content

Scanner excerpt · scripts/generate_pdf.py (reported line 26)May include surrounding context.

python
__import__(import_name)
    except ImportError:
        print(f"正在安装依赖: {package} ...")
        subprocess.check_call([sys.executable, "-m", "pip", "install", package, "-q"])


def find_chrome():

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

The script launches Chrome with headless remote debugging enabled and explicitly passes --no-sandbox. Disabling Chromium's sandbox materially weakens process isolation, so if the rendered HTML or browser engine is compromised, arbitrary code execution or local file access on the host becomes more feasible.

Content

Scanner excerpt · scripts/generate_pdf.py (reported line 103)May include surrounding context.

python
debug_port = s.getsockname()[1]

    # 3. 启动 Chrome,开启远程调试
    chrome_proc = subprocess.Popen(
        [
            chrome,
            "--headless=new",

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

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

python
for _ in range(20):
            time.sleep(0.3)
            try:
                resp = urllib.request.urlopen(
                    f"http://127.0.0.1:{debug_port}/json/version", timeout=2
                )
                info = json.loads(resp.read())

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The HTML document explicitly sets lang="zh-CN", which imposes a specific language/locale. Under the policy rules, forcing a locale without user opt-in or a clearly documented region-specific justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.