Back to skill

Security audit

WebMCP Adapter Creator

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent adapter-building purpose, but its scaffold script has a confirmed command-execution flaw when given crafted arguments.

Review before installing. Do not run the scaffold helper with untrusted or externally supplied host, URL, display name, or package name values until the Perl substitutions are fixed to treat replacements as data. If you proceed, pin Playwright in project dependencies, run scaffolding with minimal secrets in the environment, and remember that generated adapters are intended to act through your logged-in browser session.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scaffold-adapter.sh:87
Finding

Arbitrary Perl Code Execution Through Unsanitized Scaffold Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/scaffold-adapter.sh, lines 87-91
Vulnerability Type: Code injection through dynamically constructed Perl programs
Risk Level: High

Vulnerable Code

bash
LC_ALL=C perl -0pi -e "s#\Q@webmcp-bridge/example-adapter-template\E#${package_name}#g" "$out_dir/package.json"
LC_ALL=C perl -0pi -e "s#\Qadapter-template\E#adapter-${name}#g" "$out_dir/src/index.ts"
LC_ALL=C perl -0pi -e "s#\QAdapter Template\E#${display_name}#g" "$out_dir/src/index.ts"
LC_ALL=C perl -0pi -e "s#\Qexample.com\E#${host}#g" "$out_dir/src/index.ts"
LC_ALL=C perl -0pi -e "s#\Qhttps://example.com\E#${url}#g" "$out_dir/src/index.ts"

The affected values are accepted from command-line arguments without validation or safe encoding:

bash
--host)
  [[ $# -ge 2 ]] || fail 'missing value for --host'
  host="$2"
  shift 2
  ;;
--url)
  [[ $# -ge 2 ]] || fail 'missing value for --url'
  url="$2"
  shift 2
  ;;
--display-name)
  [[ $# -ge 2 ]] || fail 'missing value for --display-name'
  display_name="$2"
  shift 2
  ;;
--package-name)
  [[ $# -ge 2 ]] || fail 'missing value for --package-name'
  package_name="$2"
  shift 2
  ;;

Technical Analysis

The script embeds package_name, display_name, host, and url directly into Perl source passed through perl -e. Shell quoting does not make this safe: although the shell does not recursively evaluate syntax contained in expanded argument values, Perl subsequently parses the expanded value as part of its substitution program.

An attacker-controlled value can therefore introduce Perl replacement interpolation constructs or delimiter/modifier syntax. Perl replacements support executable interpolation forms such as ${\ ... }; when the template text is matched, the embedded Perl expression can be evaluated. Because the scaffold templates are expected to contain each searched placeholder, reaching the ...[truncated 2483 chars]

Remediation
View remediation

Remediation Suggestions

Do not construct Perl programs by interpolating untrusted values into perl -e.

  1. Pass replacement values through environment variables or positional arguments so they remain data:

    bash
    PACKAGE_NAME="$package_name" \
      perl -0pi -e 's/\Q@webmcp-bridge\/example-adapter-template\E/$ENV{PACKAGE_NAME}/g' \
      "$out_dir/package.json"
    

    Apply the same pattern to display_name, host, and url.

  2. Prefer a structured template-rendering implementation that reads replacements from arguments and performs literal string replacement. For JSON files, use a JSON-aware tool rather than textual substitution.

  3. Validate every argument according to its semantic type:

    • host: require a valid hostname and reject control characters, schemes, paths, and user-info.
    • url: parse as a URL and allow only expected schemes, normally https.
    • package_name: enforce the package manager's package-name grammar.
    • display_name: reject control characters and impose a reasonable length limit.
  4. Add regression tests containing Perl metacharacters, substitution delimiters, backslashes, dollar signs, braces, newlines, and ${\...}-style strings. Tests should verify that these values are either rejected or inserted literally and never executed.

  5. Consider constraining --dir to the intended repository package directory after canonicalization, particularly when the script may be invoked autonomously by an agent.

  6. Run scaffolding with the least-privileged account available and without unnecessary secrets in the environment. This limits impact if another injection defect is introduced later.

Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The skill instructs use of npx playwright install without pinning a specific package version, which can cause execution of whatever Playwright version resolves at runtime. In an agent or CI environment, this creates a supply-chain risk: a newer or compromised package version could be fetched and executed unexpectedly, reducing reproducibility and potentially running untrusted install scripts.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.