Back to skill

Security audit

PW Browser Setup

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs browser setup as described, but it uses privileged mutable installs and includes unsafe verification and screenshot-sharing patterns that need review before use.

Review this skill before installing on a sensitive workstation or CI host. Prefer running it in a disposable container or VM, avoid the Feishu upload example for sensitive screenshots, do not pass untrusted screenshot paths, and pin/remove the global Playwright install plus the --no-sandbox and Xvfb -ac defaults where possible.

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/verify-browser.sh:59
Finding

User-Controlled Screenshot Path Enables Arbitrary JavaScript Execution

Content
View full analysis
{ // ... await page.screenshot({ path: '$SCREENSHOT_PATH', fullPage: false }); console.log('截图保存: $SCREENSHOT_PATH'); await browser.close(); })().catch(e => { console.error('❌ 验证失败:', e.message); process.exit(1); }); " ``` ### Technical Analysis The second command-line argument is assigned to `SCREENSHOT_PATH` and interpolated directly into JavaScript source code passed to `node -e`. The value is placed inside a single-quoted JavaScript string without escaping quotes, backslashes, line breaks, or other JavaScript syntax. An attacker who can influence the screenshot path can terminate the string literal and insert additional JavaScript statements. Because the generated program runs in Node.js rather than an isolated browser context, injected code can import modules such as `child_process`, access files, read environment variables, and execute operating-system commands. Shell quoting does not make this safe: the variable is expanded before Node.js parses the resulting source, and the expanded value remains attacker-controlled JavaScript. ### Attack Path 1. An attacker convinces a user or automation system to run `verify-browser.sh` with a crafted second argument. 2. The crafted screenshot path closes the `path` string and object expression. 3. The argument inserts an additional Node.js statement, such as a call through `require('child_process')`. 4. The script builds the inline program through shell interpolation. 5. `node -e` parses and executes the injected statement. 6. The attacker’s command runs with the privileges and environment of the account invoking the Skill. ### Impact A ...[truncated 613 chars]
Remediation
View remediation
{ const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); await page.screenshot({ path: screenshotPath, fullPage: false }); await browser.close(); })(); NODE ``` Additional hardening should include: 1. Resolve the supplied path with `path.resolve`. 2. Restrict output to an approved directory if arbitrary destinations are unnecessary. 3. Reject null bytes and unsupported file extensions. 4. Avoid all user-controlled interpolation into `node -e` source. 5. Add regression tests using paths containing quotes, backslashes, newlines, and JavaScript syntax. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/install-browser.sh:66
Finding

Unpinned Playwright Installation Creates a Mutable Supply-Chain Execution Path

Content
View full analysis
&1 | tail -3 else echo "✅ Playwright 已安装 (node_modules)" fi # 全局 CLI(用于下载浏览器) if ! command -v playwright &>/dev/null; then npm install -g playwright 2>&1 | tail -3 fi echo "✅ Playwright $(playwright --version 2>/dev/null || echo '已安装')" # 3. 下载 Chromium 浏览器 echo "" echo "--- 下载 Chromium 浏览器 ---" CACHE_DIR="$HOME/.cache/ms-playwright" if [[ -d "$CACHE_DIR/chromium-"* ]] 2>/dev/null; then echo "✅ Chromium 已下载" else echo "正在下载 Chromium(约 300MB,可能需要几分钟)..." npx playwright install chromium 2>&1 | tail -5 echo "✅ Chromium 下载完成" fi # 4. 安装 Chrome Headless Shell(备用) echo "" echo "--- 下载 Chrome Headless Shell(备用)---" if [[ -d "$CACHE_DIR/chromium_headless_shell-"* ]] 2>/dev/null; then echo "✅ Chrome Headless Shell 已下载" else echo "正在下载 Chrome Headless Shell..." npx playwright install chromium-headless-shell 2>&1 | tail -5 echo "✅ Chrome Headless Shell 下载完成" fi ``` ### Technical Analysis The installer requests `playwright` without an exact version and does not require a reviewed lockfile. The effective package and transitive dependency graph can therefore change after the Skill has been audited. Package installation may execute npm lifecycle scripts under the invoking account. A compromised registry account, malicious future package release, or compromised transitive dependency could consequently introduce code execution during installation. The script also installs Playwright globally. This is unnecessary because the local package already exposes its CLI through `npx`, and it broadens the installation scope beyond the project workspace. Depending on npm configuration, the global installation may modif ...[truncated 1167 chars]
Remediation
View remediation
``` 2. Commit a reviewed `package.json` and `package-lock.json`, then install with: ```bash npm ci ``` 3. Remove the global installation: ```bash npm install -g playwright ``` 4. Invoke only the project-local pinned CLI: ```bash ./node_modules/.bin/playwright install chromium ``` 5. Consider `--ignore-scripts` where compatible, or explicitly review all required lifecycle scripts before allowing them. 6. Configure an approved npm registry and use integrity information from the lockfile. 7. Pin and verify browser artifact versions and checksums where the dependency tooling permits. 8. Do not suppress most installation output with `tail`; preserve complete logs for security review and incident investigation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify-browser.sh:36
Finding

Remote Web Content Is Loaded with the Chromium Sandbox Disabled

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify-browser.sh:14
Finding

Xvfb Is Started with Access Control Disabled

Content
View full analysis
/dev/null; then echo "启动 Xvfb 虚拟显示器..." Xvfb :99 -screen 0 1280x900x24 -ac & sleep 1 export DISPLAY=:99 echo "✅ Xvfb 已启动 (DISPLAY=:99)" else export DISPLAY=:99 echo "✅ Xvfb 已在运行 (DISPLAY=:99)" fi fi ``` The generated launcher contains the same configuration in `scripts/install-browser.sh`, lines 113–120: ```bash if pgrep -x Xvfb > /dev/null; then echo "Xvfb 已在运行 (DISPLAY=:99)" exit 0 fi Xvfb :99 -screen 0 1280x900x24 -ac & ``` ### Technical Analysis The `-ac` option disables X server access control. Processes able to reach display `:99` may connect without presenting an Xauthority credential. X11 clients can potentially inspect windows, capture displayed content, synthesize input events, or interfere with applications using the display. The script also uses a fixed display number and treats any running Xvfb process as if it were the intended `:99` instance. `pgrep -x Xvfb` does not establish which display that process owns, who started it, or whether it is trusted. The generated helper persists as a file in the Skill directory, but it is not registered as a startup service or scheduled task. Therefore, no system persistence mechanism was identified. ### Attack Path 1. The verification script or generated helper starts Xvfb on display `:99` with `-ac`. 2. A separate local process discovers or anticipates the fixed display number. 3. That process connects to the X server without authentication. 4. When headed Chromium uses the display, the local process can attempt to observe graphical content or inject X11 events. 5. Captured content or injected interaction may expose or alter the browser session. A second failure mode o ...[truncated 752 chars]
Remediation
View remediation
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

总体上,代码与“安装和配置浏览器自动化环境”的核心目的基本一致,确实会安装 Xvfb、系统依赖、Playwright 和 Chromium,并支持非头模式相关配置。但声明中明确提到“检查和验证工具”以及“系统兼容性检查(内存、CPU、磁盘)”,这些在该代码片段中并未实现;脚本也没有实际执行浏览器验证,只是提示用户运行另一个 verify-browser.sh。虽然额外安装全局 Playwright CLI 和 chromium-headless-shell 可视为配套实现细节,不算严重问题,但缺失了声明中的关键检查/验证能力,因此存在描述与实际行为的不一致。

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

bash
# 1. 上传图片获取 image_key
IMAGE_KEY=$(curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/images" \
  -H "Authorization: Bearer $TENANT_TOKEN" \
  -F "image_type=message" \
  -F "image=@/tmp/browser-verify.png" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['image_key'])")

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 20)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/install-browser.sh (reported line 26)May include surrounding context.

sh
elif command -v dnf &>/dev/null; then
      sudo -n dnf install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v pacman &>/dev/null; then
      sudo -n pacman -S --noconfirm xorg-server-xvfb 2>/dev/null || SUDO_OK=false
    else
      echo "❌ 无法自动安装 Xvfb,请手动安装: apt-get install xvfb / yum install xorg-x11-server-Xvfb"
      exit 1

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs users to execute multiple shell scripts but does not declare any tool scope or permissions boundary. This is dangerous because it hides the skill's need for shell execution from reviewers and agents, increasing the chance that privileged commands are run without explicit authorization or policy checks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill includes instructions to upload a browser screenshot to Feishu and send it in a message, but it does not warn the user that local data will be transmitted to a third-party service. Screenshots may contain sensitive page content, session state, internal URLs, or user data, so silent exfiltration risk is significant in an automation/setup context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This command sends an image message to Feishu using an access token and a previously uploaded screenshot, which is a clear external data transmission path. In the context of browser verification, the screenshot may expose sensitive visual content, and the skill does not gate or warn about that transfer.

Content

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

md
-F "image=@/tmp/browser-verify.png" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['image_key'])")

# 2. 发送图片消息
curl -s -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
  -H "Authorization: Bearer $TENANT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"receive_id":"<open_id>","msg_type":"image","content":"{\"image_key\":\"'"$IMAGE_KEY"'\"}"}'

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This shell script's comments and all user-facing status messages are written in Chinese, which imposes a specific language on users. Under the policy, language constraints should either be optional/opt-in or clearly justified as region-specific; neither is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file's natural-language interface is entirely in Chinese, including the header comment and all user-facing echo messages. Under the stated policy, forcing a specific language without offering user choice or documenting a justified locale restriction is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 20)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 22)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 24)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 26)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 34)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 45)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 52)May include surrounding context.

sh
echo "正在安装 xvfb..."
    SUDO_OK=true
    if command -v apt-get &>/dev/null; then
      sudo -n apt-get update -qq 2>/dev/null && sudo -n apt-get install -y -qq xvfb 2>/dev/null || SUDO_OK=false
    elif command -v yum &>/dev/null; then
      sudo -n yum install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v dnf &>/dev/null; then

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
65% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/install-browser.sh (reported line 26)May include surrounding context.

sh
elif command -v dnf &>/dev/null; then
      sudo -n dnf install -y xorg-x11-server-Xvfb 2>/dev/null || SUDO_OK=false
    elif command -v pacman &>/dev/null; then
      sudo -n pacman -S --noconfirm xorg-server-xvfb 2>/dev/null || SUDO_OK=false
    else
      echo "❌ 无法自动安装 Xvfb,请手动安装: apt-get install xvfb / yum install xorg-x11-server-Xvfb"
      exit 1

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

The script invokes npx playwright install chromium without pinning the Playwright version to a known-safe release. That makes the install behavior dependent on whatever package version is currently resolved in the workspace or registry, increasing supply-chain risk and making builds non-reproducible.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

The script downloads chromium-headless-shell via npx playwright without ensuring an exact Playwright version is used. In an installation script that pulls binaries from the network, unpinned versions create avoidable supply-chain exposure and inconsistent results across runs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script's comments and runtime messages are consistently in Chinese, including user-visible status output, with no indication that the skill is region-specific or that users can opt into another language. This can violate a language/locale policy when a skill imposes a specific language by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest description and operational instructions are written in Chinese, but the file does not indicate that language choice is optional or user-selected. If organizational policy requires not forcing a specific language or locale without opt-in, this is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code navigates to https://www.baidu.com, which causes outbound network traffic and transmits system/browser metadata to a third-party service. Although the script logs that it is opening Baidu, it does not clearly warn the user ahead of time that running the skill contacts an external website.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.