Back to skill

Security audit

PageAgent Browser Enhancement

Security checks for vulnerabilities and agentic risk

Overview

This browser-automation skill is purpose-aligned overall, but it needs review because it injects powerful JavaScript into any selected webpage and exposes unrestricted page-script execution.

Install only if you are comfortable giving the skill script-level control over pages you target. Avoid using it on banking, admin, production, email, or other sensitive authenticated sites unless you have isolated the browser profile and explicitly trust the page and task. Prefer the documented inject-cdp.mjs path, avoid the alternate shell wrapper with untrusted arguments, and pin or preinstall any local server dependency instead of relying on unpinned npx resolution.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/inject-via-cdp.sh:7
Finding

Shell Arguments Are Interpolated into Executable Node.js Source

Content
View full analysis

Vulnerability Details

File Location: scripts/inject-via-cdp.sh, lines 7-27
Vulnerability Type: Shell-to-JavaScript command injection
Risk Level: High

Vulnerable Code

bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TARGET_ID="${1}"
CDP_ENDPOINT="${2:-http://127.0.0.1:18800}"

# Use node to inject via CDP Runtime.evaluate
node -e "
const fs = require('fs');
const http = require('http');

const scriptContent = fs.readFileSync('${SCRIPT_DIR}/page-controller-global.js', 'utf8');
const injectContent = fs.readFileSync('${SCRIPT_DIR}/inject.js', 'utf8');
const combined = scriptContent + ';\n' + injectContent;

// Use CDP to evaluate
const ws = require('ws') || null;

async function injectViaCDP() {
  // Get WebSocket URL for the target
  const listUrl = '${CDP_ENDPOINT}/json';
  const resp = await fetch(listUrl);
  const pages = await resp.json();
  const target = pages.find(p => p.id === '${TARGET_ID}');

Technical Analysis

The script constructs a JavaScript program inside a double-quoted shell string passed to node -e. TARGET_ID, CDP_ENDPOINT, and the derived SCRIPT_DIR are inserted directly into single-quoted JavaScript literals without JavaScript escaping or separation between code and data.

A value containing a single quote followed by JavaScript syntax can terminate the intended string literal and inject statements into the generated Node.js program. Shell quoting of the original positional arguments does not prevent this issue because the vulnerable interpretation occurs later, when Node.js parses the assembled source code.

The injected code runs in the local Node.js process rather than merely in the target browser page. It therefore has the filesystem, process, and network privileges of the user who invoked the script.

Attack Path

  1. An attacker gains influence over the target ID or CDP endpoint supplied to inject-via-cdp.sh. This can occur t ...[truncated 1341 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the inline node -e program and delegate to the existing scripts/inject-cdp.mjs implementation using ordinary process arguments.
  • If an inline program must be retained, read values from process.argv or environment variables so they remain data rather than generated source code.
  • Do not interpolate shell variables into JavaScript string literals.
  • Validate TARGET_ID against the expected identifier format, such as a strict allowlist of alphanumeric characters and limited punctuation.
  • Parse CDP_ENDPOINT with the URL API and permit only explicitly approved schemes and hosts. If remote CDP is unnecessary, restrict it to loopback addresses.
  • Pass the script directory as an argument and resolve it using Node.js path APIs.
  • Add regression tests containing quotes, backslashes, newlines, template syntax, and JavaScript metacharacters in every externally supplied argument.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/inject.js:50
Finding

Public Page API Executes Arbitrary JavaScript through eval

Content
View full analysis

Vulnerability Details

File Location: scripts/inject.js, lines 50-53; execution sink in scripts/page-controller-global.js, lines 1951-1957, and scripts/page-controller.js, lines 1951-1957
Vulnerability Type: Unrestricted page-context code execution
Risk Level: Medium

Vulnerable Code

Public wrapper:

javascript
// Execute JS
async execJS(script) {
  return await ctrl.executeJavascript(script);
},

Execution sink:

javascript
/**
 * Execute arbitrary JavaScript on the page
 */
async executeJavascript(script) {
  try {
    const asyncFunction = eval(`(async () => { ${script} })`);
    const result = await asyncFunction();
    return {
      success: true,
      message: `✅ Executed JavaScript. Result: ${result}`
    };

Technical Analysis

The injected global object exposes window.__PA__.execJS, which forwards an arbitrary source string to PageController.executeJavascript. That method embeds the string in a template literal and executes it using eval.

There is no operation allowlist, syntax validation, capability restriction, confirmation boundary, or isolation from the active page origin. The evaluated program executes in the context of the currently loaded page and can use all JavaScript capabilities available to code in that context.

Although arbitrary execution is explicitly represented as a helper feature and no automatic malicious invocation was identified, exposing it broadly exceeds the narrower indexed DOM operations required for clicking, typing, selecting, and scrolling. It creates a dangerous execution sink if an Agent or other caller constructs scripts from attacker-controlled page content.

Attack Path

  1. A user opens an attacker-controlled or compromised page using the browser automation workflow.
  2. The page presents instructions or data crafted to influence an Agent into executing JavaScript through the helper API.
  3. The Agent ...[truncated 1420 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove execJS from the public window.__PA__ interface unless arbitrary code execution is an essential and explicitly approved requirement.
  • Replace source-string evaluation with narrowly scoped methods for required operations.
  • Use structured arguments and fixed implementations rather than dynamically generated JavaScript.
  • If the feature must remain, require explicit user confirmation for every invocation and prominently disclose the target origin and requested operation.
  • Reject scripts derived from page text, model output, URLs, or other untrusted sources.
  • Apply an allowlist of supported operations rather than attempting to sanitize arbitrary JavaScript syntax.
  • Avoid relying on regular expressions or keyword filtering as a sandbox; such controls cannot safely constrain general JavaScript.
  • Run sensitive browsing workflows in an isolated browser profile with no unrelated authenticated sessions.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:68
Finding

Documented Workflow May Download and Execute an Unpinned npm Package

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 68
Vulnerability Type: Unpinned third-party package execution
Risk Level: Medium

Vulnerable Code

markdown
2. **Serve**: Start a local dev server (`npx serve` or framework dev server)

Technical Analysis

The documented workflow recommends npx serve without specifying a version, lockfile, integrity value, or requirement that the package already be installed locally.

Depending on the npm and npx environment, this command can resolve and download the current registry version of the named package when no verified local installation exists. Package installation or execution can run third-party JavaScript with the invoking user's local privileges. Because the resolved artifact is mutable over time, the effective code executed by users may differ from the code reviewed during this audit.

No evidence was found that the referenced serve package is currently malicious. The vulnerability is the unsafe, unpinned supply-chain execution pattern rather than confirmed malicious package content.

Attack Path

  1. A user follows the workflow on a system where a trusted local serve package is not already installed.
  2. npx contacts the configured npm registry and resolves an unspecified package version.
  3. A compromised registry account, package release, dependency, registry mirror, or future package version supplies malicious code.
  4. npx downloads and executes that code.
  5. The package runs with the permissions of the user invoking the Skill workflow.

Impact Assessment

If the resolved package or one of its installation-time dependencies is compromised, it can potentially:

  • Read or modify files accessible to the current user.
  • Access environment variables and development credentials.
  • Modify source code or build artifacts.
  • Communicate with external systems.
  • Compromise subsequent browser automation or development activi ...[truncated 152 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin the server package to a reviewed exact version instead of resolving an unspecified latest version.
  • Declare it in a project manifest and commit a lockfile containing integrity metadata.
  • Install dependencies through a controlled, reviewed dependency-management process before running the workflow.
  • Use npx --no-install serve when execution must be limited to an already installed and verified local dependency.
  • Prefer a trusted server already supplied by the project or runtime.
  • Use an approved registry and verify package provenance and integrity in automated environments.
  • Regularly review pinned dependencies and update them through an explicit security-review process.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

This finding is substantively valid for the same reason: the documented workflow uses CDP injection and page-context execution that exceed a simple 'browser interaction' abstraction. In the context of a skill meant to operate on any page, arbitrary in-page code execution can expose credentials, page contents, CSRF-protected state, or trigger unintended actions as the logged-in user.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

This finding is substantively valid for the same reason: the documented workflow uses CDP injection and page-context execution that exceed a simple 'browser interaction' abstraction. In the context of a skill meant to operate on any page, arbitrary in-page code execution can expose credentials, page contents, CSRF-protected state, or trigger unintended actions as the logged-in user.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
ere `TARGET_ID` is from `browser(action="open", ...)`. The script injects both `page-controller-global.js` and `inject.js` via CDP WebSocket, outputting `✅ inje

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/page-controller.js` — PageController library (72KB, from @page-agent/page-controller@1.5.6)

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The injected API exposes execJS(), which allows arbitrary JavaScript execution in the context of any page where the skill is injected. That capability goes beyond the stated DOM extraction and interaction purpose and can be abused to read sensitive page data, manipulate application state, trigger privileged actions as the user, or evade higher-level safeguards by running raw script directly.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The PageController exposes an executeJavascript(script) method that directly wraps attacker-controlled input in eval and executes it in the page context. This exceeds the skill’s stated DOM interaction purpose and allows arbitrary script execution against any visited site, enabling data extraction, DOM tampering, credential harvesting from page state, and bypass of higher-level safety controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Arbitrary JavaScript execution is exposed as a normal API call with no warning, confirmation, sandboxing, or trust boundary checks. In this skill’s context—injecting into arbitrary web pages—this makes misuse especially dangerous because a caller can silently run code on sensitive sites and interact with page data outside the manifest’s advertised click/type/scroll behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill exposes a general-purpose executeJavascript(script) capability that runs arbitrary code in the page context, which exceeds the declared scope of DOM extraction and interaction. This enables any caller or prompt-influenced workflow to execute unrestricted page-origin JavaScript, potentially reading sensitive DOM data, modifying application state, invoking privileged in-page APIs, or triggering unintended actions on authenticated sites.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Arbitrary script execution is exposed as a normal controller method without any warning, approval, or policy boundary despite operating inside arbitrary web pages. In the context of an automation skill that may browse authenticated sessions, this materially increases the risk of prompt-driven abuse, sensitive data extraction from the DOM, and unauthorized in-page actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
100% confidence
Finding

This implementation uses eval to construct and run attacker-controlled JavaScript: eval((async () => { ${script} })). Using eval here is unjustified for a page-controller skill and creates a direct code-injection primitive, allowing arbitrary execution with access to the current page's DOM, storage-visible data, and authenticated browser state for that origin.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill clearly performs network-capable actions by instructing the user/agent to inject code into arbitrary pages via CDP WebSocket, yet it declares no tool scope or permissions boundary. That omission weakens reviewability and can cause operators to underestimate the reach of the skill, especially because it targets any open page and executes injected code in-page.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description emphasizes convenience and improved browser automation but does not prominently warn that it injects and executes a third-party DOM-manipulation library inside any open web page. This missing warning increases the chance of unsafe use on sensitive sites where injected scripts can access page data and act with the user's session.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
80% confidence
Finding

Using npx serve without pinning a version introduces supply-chain risk because the package resolved at runtime may change over time or be replaced by a compromised release. In a security-sensitive workflow, this can lead to execution of unexpected code on the local machine.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script programmatically injects and executes arbitrary JavaScript into a live browser page through Chrome DevTools Protocol without any access control, origin restriction, or user confirmation. In the context of a browser-operation skill, that behavior is intentional, but it is still security-relevant because it can modify page state, interact with authenticated sessions, and extract sensitive DOM data from whatever target page is selected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill provides arbitrary JavaScript execution without any visible warning, disclosure, or indication to users that page-context code can be run. In this skill context, that is especially risky because the tool is designed to inject into arbitrary web pages, so operators may treat it as a normal browser automation helper while it silently enables much more powerful and dangerous behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The function name and comment imply behavior that patches React compatibility, but the implementation merely marks certain root elements with a data-page-agent-not-interactive attribute. That is an intent/documentation mismatch because it does not actually patch React behavior; it just excludes likely app roots from interaction detection.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/page-controller-global.js:1956

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/page-controller.js:1956