Back to skill

Security audit

Pmos Search Menu Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed PMOS browser-navigation helper, but its included Node.js script can run unintended local commands if a malicious element reference is entered.

Review before installing. Use only in an authorized PMOS account/session, avoid pasting element references from untrusted sources, and prefer manual browser commands or the quoted shell script over the Node.js script until it validates refs and uses argument-array process execution. The maintainer should also narrow activation keywords and add an explicit authenticated-session warning.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/navigate-pmos.js:28
Finding
Shell Command Injection Through User-Supplied Element References## Vulnerability Details **File Location**: `scripts/navigate-pmos.js:28-39`, `scripts/navigate-pmos.js:58-64`, and `scripts/navigate-pmos.js:151-158` **Vulnerability Type**: OS command injection **Risk Level**: High The Node.js navigation script accepts an element reference from standard input and incorporates it directly into a shell command executed by `execSync()`. **Vulnerable code:** ```js // Execute an OpenClaw command function runCommand(cmd, silent = false) { try { const output = execSync(cmd, { encoding: 'utf-8', stdio: silent ? 'pipe' : 'inherit' }); return output; } catch (error) { if (!silent) { console.error(`Command execution failed: ${cmd}`); console.error(error.message); } throw error; } } // Click a menu item function clickMenuItem(ref, targetId) { console.log(`Clicking menu item (ref: ${ref})...`); const cmd = targetId ? `openclaw browser act click --ref ${ref} --targetId ${targetId}` : `openclaw browser act click --ref ${ref}`; runCommand(cmd); } const ref = await new Promise(resolve => { rl.question('Enter the element reference, for example e78, or leave blank to skip: ', resolve); }); if (ref) { clickMenuItem(ref, currentTabId); } ``` ### Technical Analysis `child_process.execSync()` executes a string through the operating-system shell. The `ref` value is obtained interactively and is concatenated into that command without syntax validation, escaping, or separation into an argument array. Consequently, shell metacharacters contained in `ref` are interpreted by the shell rather than treated as part of an OpenClaw argument. An input conceptually shaped like `e78; attacker-command` can terminate or extend the intended command and invoke an additional local command. The `targetId` value is also interpolated into command strings without validation. It originates from the output of ...[truncated 1469 chars]
Remediation
## Remediation Suggestions 1. Replace `execSync()` with `execFileSync()` or `spawnSync()` and pass each command-line argument as a separate array element. Do not enable shell execution. 2. Validate element references using an allowlist matching the documented format. For example, permit only the letter `e` followed by one or more decimal digits. 3. Validate tab identifiers against the exact format documented by OpenClaw before using them. 4. Reject invalid input explicitly rather than passing it to the command runner. 5. Keep static values such as `openclaw`, `browser`, `act`, and `click` separate from runtime arguments. 6. Add automated tests covering semicolons, command substitutions, pipes, redirection characters, quotes, whitespace, and newline injection. 7. Run the Skill with the least-privileged operating-system account necessary for browser navigation. A safer implementation should follow this structure: ```js const { execFileSync } = require('child_process'); function validateRef(ref) { if (!/^e\d+$/.test(ref)) { throw new Error('Invalid accessibility element reference'); } } function clickMenuItem(ref, targetId) { validateRef(ref); const args = ['browser', 'act', 'click', '--ref', ref]; if (targetId) { validateTargetId(targetId); args.push('--targetId', targetId); } execFileSync('openclaw', args, { encoding: 'utf-8', stdio: 'inherit' }); } ```

T09 · Insecure Skill Coding Practices

Error
Location
pmos-search-menu-skill/scripts/navigate-pmos.js:28
Finding
Shell Command Injection in the Duplicated Node.js Navigation Script## Vulnerability Details **File Location**: `pmos-search-menu-skill/scripts/navigate-pmos.js:28-39`, `pmos-search-menu-skill/scripts/navigate-pmos.js:58-64`, and `pmos-search-menu-skill/scripts/navigate-pmos.js:151-158` **Vulnerability Type**: OS command injection **Risk Level**: High The nested project copy contains the same vulnerable Node.js implementation. A user-supplied element reference is concatenated into a command string and executed through a shell. **Vulnerable code:** ```js // Execute an OpenClaw command function runCommand(cmd, silent = false) { try { const output = execSync(cmd, { encoding: 'utf-8', stdio: silent ? 'pipe' : 'inherit' }); return output; } catch (error) { if (!silent) { console.error(`Command execution failed: ${cmd}`); console.error(error.message); } throw error; } } // Click a menu item function clickMenuItem(ref, targetId) { console.log(`Clicking menu item (ref: ${ref})...`); const cmd = targetId ? `openclaw browser act click --ref ${ref} --targetId ${targetId}` : `openclaw browser act click --ref ${ref}`; runCommand(cmd); } const ref = await new Promise(resolve => { rl.question('Enter the element reference, for example e78, or leave blank to skip: ', resolve); }); if (ref) { clickMenuItem(ref, currentTabId); } ``` ### Technical Analysis String-form `execSync()` invokes the system shell. Because `ref` is read from standard input and inserted into the command without validation or shell-safe argument handling, an attacker-controlled value can introduce shell operators and additional commands. The same unsafe construction is used for `targetId`, which is derived from external command output. Although the interactive reference is the clearest exploitation source, both values must be treated as untrusted. ### Attack Path 1. The nested copy is executed with `node pmos ...[truncated 789 chars]
Remediation
## Remediation Suggestions 1. Apply the same security correction to both project copies so that an outdated vulnerable duplicate cannot be packaged or executed accidentally. 2. Use `execFileSync('openclaw', args)` or `spawnSync('openclaw', args)` with an argument array and shell execution disabled. 3. Restrict `ref` to the expected accessibility-reference syntax, such as the letter `e` followed only by decimal digits. 4. Validate `targetId` according to OpenClaw's documented identifier format. 5. Reject malformed values before invoking any child process. 6. Add command-injection regression tests and consolidate the duplicated package into one authoritative source tree. Example hardened pattern: ```js const { execFileSync } = require('child_process'); function clickMenuItem(ref, targetId) { if (!/^e\d+$/.test(ref)) { throw new Error('Invalid accessibility element reference'); } const args = ['browser', 'act', 'click', '--ref', ref]; if (targetId) { validateTargetId(targetId); args.push('--targetId', targetId); } execFileSync('openclaw', args, { encoding: 'utf-8', stdio: 'inherit' }); } ```
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (14)

Ae1

High
Category
analysis-evasion
Content
node scripts/navigate-pmos.js
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file presents all user-facing instructions in Chinese and does not indicate that the skill is limited to Chinese-speaking users or provide an alternative language option. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The trigger phrases include broad terms such as "甘肃电力交易平台" and "sgcc.com.cn", which can match ordinary discussion of the external platform rather than a clear request to invoke browser automation. Because this skill drives navigation on an authenticated site, accidental activation could cause unintended browsing actions in a logged-in session and expose sensitive workflow context.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger list includes broad terms such as the target domain and general references to the platform, which can cause the skill to activate when a user merely mentions PMOS or sgcc.com.cn rather than requesting automated browser navigation. Because this skill opens a site and guides privileged post-login interaction, overbroad activation increases the chance of unintended actions in an authenticated session.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The document is written entirely in Chinese and presents the navigation steps, labels, and usage guidance as the only supported language. Under the policy rule for natural-language violations, forcing a specific language without user opt-in or an explicit justified locale scope is a reportable issue.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The file’s natural-language description, comments, and interactive prompts are entirely in Chinese, and the script provides no option to choose another language or indication that it is intentionally limited to Chinese-speaking users. Under the policy criteria, forcing a specific language without user opt-in is a locale/language policy issue.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
All user-facing comments, prompts, and operational messages in the script are written exclusively in Chinese, including required interaction steps. This effectively forces a specific language/locale for use without any opt-in or alternative, which matches the policy-violation category for language or locale constraints.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The user-facing comments, prompts, and status messages are written entirely in Chinese, including usage instructions and interactive prompts. This imposes a specific language on all users without any visible opt-in, fallback, or documented locale restriction.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The skill explicitly requires a valid login to an external power trading platform but does not warn users about the risks of operating within an authenticated session. Without that warning, users may invoke automation on sensitive pages without understanding that actions and page contents may involve protected account data or regulated operational information.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The description forces a specific language presentation in the skill metadata, and the file does not state that the skill is intended only for Chinese-speaking users or a China-specific deployment. Under the policy, locale or language constraints should be documented and justified, or offered as an opt-in choice.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The skill documentation is written entirely in Chinese, including usage and warnings, with no indication that users may choose another language or that the skill is explicitly limited to Chinese-speaking users. Under the policy rule, a fixed language without opt-in can be a natural-language locale violation unless clearly justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
74% confidence
Finding
All user-facing instructions, trigger phrases, and usage guidance are presented only in Chinese, and the trigger section implies Chinese-language invocation terms. There is no statement that the skill is China-specific or that users may choose another language, which can create an avoidable language/locale policy issue.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This markdown file contains user-facing operational instructions exclusively in Chinese, and nowhere indicates that the skill is China-specific or that users may choose another language. Under the policy rule for language/locale constraints, forcing a single language without opt-in can be a natural-language policy issue.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This JavaScript file contains its descriptive comments and all interactive prompts exclusively in Chinese, including the tool description and runtime instructions. That imposes a specific language/locale on all users without offering a choice or documenting a justified region-specific constraint.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
pmos-search-menu-skill/scripts/navigate-pmos.js:31

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/navigate-pmos.js:31