Back to skill

Security audit

Tencent Cloud Lighthouse

Security checks for vulnerabilities and agentic risk

Overview

This skill is for Tencent Cloud Lighthouse administration, but it stores cloud API keys in plaintext and runs unpinned npm packages with those credentials, so users should review it carefully before installing.

Install only if you are comfortable giving this skill a Tencent Cloud API key and allowing npm-sourced code to run with that key. Use a dedicated least-privilege CAM identity, restrict or rotate credentials, check permissions on ~/.mcporter/mcporter.json, and prefer a pinned or locally reviewed MCP server package before using remote command or firewall operations.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:125
Finding
JavaScript Code Injection Through Unsafely Interpolated Setup Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 125-139 **Vulnerability Type**: User-controlled data embedded directly into JavaScript source **Risk Level**: High ### Vulnerable Code ```bash node -e " const fs = require('fs'); let config = {}; try { config = JSON.parse(fs.readFileSync('$CONFIG_PATH', 'utf8')); } catch {} if (!config.mcpServers) config.mcpServers = {}; config.mcpServers.lighthouse = { command: 'npx', args: ['-y', 'lighthouse-mcp-server'], env: { TENCENTCLOUD_SECRET_ID: '$SECRET_ID', TENCENTCLOUD_SECRET_KEY: '$SECRET_KEY' } }; fs.writeFileSync('$TEMP_CONFIG', JSON.stringify(config, null, 2)); " ``` ### Technical Analysis The script inserts `CONFIG_PATH`, `SECRET_ID`, `SECRET_KEY`, and `TEMP_CONFIG` directly into a JavaScript program passed to `node -e`. These values are not encoded as JavaScript string literals. A value containing a single quote can terminate the surrounding JavaScript string and append arbitrary JavaScript. Because Node.js exposes modules such as `child_process`, successful injection can lead directly to operating-system command execution. This path is reached whenever the selected configuration file already exists. Shell quoting at argument parsing does not mitigate the issue because the injection occurs later when the script constructs JavaScript source. ### Attack Path 1. An attacker supplies a malicious SecretId, SecretKey, or configuration path to the setup workflow. 2. The targeted configuration file already exists, causing the update branch to run. 3. The malicious value closes the JavaScript string and introduces additional JavaScript statements. 4. `node -e` evaluates the resulting source. 5. Attacker-controlled JavaScript invokes system commands with the privileges of the user running `setup.sh`. For example, the structural form of a malicious value could be: ```text '; require('child_process').execSync('ATTACKER_COMMAND'); // ``` The e ...[truncated 512 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not construct executable JavaScript by interpolating shell variables. Pass values through environment variables or positional arguments and retrieve them as data: ```bash CONFIG_PATH="$CONFIG_PATH" \ TEMP_CONFIG="$TEMP_CONFIG" \ SECRET_ID="$SECRET_ID" \ SECRET_KEY="$SECRET_KEY" \ node <<'NODE' const fs = require('fs'); const { CONFIG_PATH, TEMP_CONFIG, SECRET_ID, SECRET_KEY } = process.env; let config = {}; try { config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')); } catch (error) { throw new Error(`Unable to parse existing configuration: ${error.message}`); } config.mcpServers ??= {}; config.mcpServers.lighthouse = { command: 'npx', args: ['-y', 'lighthouse-mcp-server'], env: { TENCENTCLOUD_SECRET_ID: SECRET_ID, TENCENTCLOUD_SECRET_KEY: SECRET_KEY } }; fs.writeFileSync(TEMP_CONFIG, JSON.stringify(config, null, 2), { mode: 0o600 }); NODE ``` Additionally: - Validate `CONFIG_PATH` against an expected directory. - Reject unexpected control characters in credential identifiers. - Do not silently replace malformed existing JSON. - Add regression tests using quotes, newlines, backslashes, and JavaScript-like input. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/setup.sh:97
Finding
Unpinned npm Packages Are Downloaded and Executed During Setup and Runtime<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 97-152 **Vulnerability Type**: Unpinned remote dependency installation and execution **Risk Level**: High ### Vulnerable Code ```bash # Step 1: Check/install mcporter if command -v mcporter &>/dev/null; then echo "[OK] mcporter already installed" else echo "[INSTALL] Installing mcporter via npm..." npm install -g mcporter ``` The generated MCP configuration also invokes an unpinned package through `npx`: ```javascript config.mcpServers.lighthouse = { command: 'npx', args: ['-y', 'lighthouse-mcp-server'], env: { TENCENTCLOUD_SECRET_ID: '$SECRET_ID', TENCENTCLOUD_SECRET_KEY: '$SECRET_KEY' } }; ``` The newly generated configuration has the same behavior: ```json "lighthouse": { "command": "npx", "args": ["-y", "lighthouse-mcp-server"], "env": { "TENCENTCLOUD_SECRET_ID": "$SECRET_ID", "TENCENTCLOUD_SECRET_KEY": "$SECRET_KEY" } } ``` ### Technical Analysis Both npm dependencies are referenced only by package name. No exact version, integrity digest, lockfile, or trusted artifact checksum is used. `npm install -g mcporter` installs whichever version the configured registry currently resolves as current. Similarly, `npx -y lighthouse-mcp-server` can retrieve and execute a remotely supplied package without interactive confirmation. Consequently, the effective code executed by the skill can change after the audited skill package has been published. A compromised package publisher, npm account, registry, dependency, or package release could introduce code that is executed automatically. The MCP server receives Tencent Cloud API credentials in its environment, making compromise especially sensitive. ### Attack Path 1. An attacker compromises an upstream package, maintainer account, transitive dependency, or configured npm registry. 2. A malicious release becomes the version selected for `mcporter` or `lighthouse-mcp-server`. 3. The setup script ...[truncated 887 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin both packages to reviewed exact versions, for example `mcporter@X.Y.Z` and `lighthouse-mcp-server@A.B.C`. - Use a committed lockfile and deterministic installation such as `npm ci`. - Verify package integrity against an expected SHA-512 digest or distribute reviewed, signed artifacts. - Avoid `npx -y` for security-sensitive runtime execution. - Install dependencies locally in a dedicated, least-privileged directory rather than globally. - Disable unnecessary npm lifecycle scripts where compatible, using `--ignore-scripts`. - Review and pin transitive dependencies. - Execute the MCP server in a sandbox with restricted filesystem and network access. - Use a dedicated Tencent CAM identity with only the minimum Lighthouse permissions. - Establish an explicit dependency-update process that requires review before changing pinned versions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:111
Finding
Tencent Cloud Credentials Are Stored in Plaintext Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 111-155 **Vulnerability Type**: Insecure storage of cloud API credentials **Risk Level**: High ### Vulnerable Code The directory is created without explicitly restricting its permissions: ```bash CONFIG_DIR="$(dirname "$CONFIG_PATH")" if [[ ! -d "$CONFIG_DIR" ]]; then mkdir -p "$CONFIG_DIR" echo "[OK] Created config directory: $CONFIG_DIR" fi ``` Credentials are then written directly into the JSON configuration: ```bash cat > "$CONFIG_PATH" <<JSONEOF { "mcpServers": { "lighthouse": { "command": "npx", "args": ["-y", "lighthouse-mcp-server"], "env": { "TENCENTCLOUD_SECRET_ID": "$SECRET_ID", "TENCENTCLOUD_SECRET_KEY": "$SECRET_KEY" } } } } JSONEOF ``` The existing-file branch likewise stores the credentials as plaintext environment values: ```javascript env: { TENCENTCLOUD_SECRET_ID: '$SECRET_ID', TENCENTCLOUD_SECRET_KEY: '$SECRET_KEY' } ``` ### Technical Analysis The configuration contains reusable Tencent Cloud credentials in plaintext. The script does not run `umask 077`, does not create the destination file with mode `0600`, and does not validate or repair permissions after writing it. For a newly created file, final permissions depend on the caller's current `umask`. Under a common `022` umask, shell redirection generally creates a file with mode `0644`, allowing other local users to read it. The configuration directory may similarly be created with broadly traversable permissions. Although `mktemp` generally creates a restrictive temporary file in the existing-file branch, the script does not explicitly guarantee or verify the final destination's owner and mode. The credentials are also accepted as command-line arguments, which may expose them through process inspection while setup is running. ### Attack Path 1. A user runs setup with valid Tencent Cloud credentials. 2. The script creates the configuration w ...[truncated 1022 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Enforce restrictive permissions before creating any credential-bearing file: ```bash umask 077 mkdir -p -- "$CONFIG_DIR" chmod 700 -- "$CONFIG_DIR" install -m 600 /dev/null "$CONFIG_PATH" ``` After an atomic replacement, explicitly verify and repair ownership and permissions: ```bash chmod 600 -- "$CONFIG_PATH" [[ -O "$CONFIG_PATH" ]] || { echo "[ERROR] Configuration is not owned by the current user" >&2 exit 1 } ``` Further hardening should include: - Store credentials in an operating-system secret manager or Tencent-supported credential provider instead of directly in JSON. - Prefer short-lived credentials or role-based authentication. - Use a dedicated CAM identity with narrowly scoped Lighthouse permissions. - Avoid passing secrets on the command line; read them from a protected file descriptor, secret manager, or hidden prompt. - Validate that the destination is not a symbolic link and is a regular file owned by the current user. - Rotate any credentials that may already have been written with permissive permissions. - Never print credential values in logs or diagnostics. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The skill’s declared purpose emphasizes Lighthouse management, but its first-use flow collects Tencent Cloud SecretId/SecretKey and persists them into a local mcporter configuration file. That credential-handling behavior is materially more sensitive than simple cloud-instance management guidance and is not clearly disclosed in the description, creating a trust and secret-exposure risk if users provide long-lived API keys to the agent workflow.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
The script installs `mcporter` globally via npm, which introduces execution of general-purpose package manager tooling and lifecycle scripts outside narrowly scoped Lighthouse management. While this may be operationally convenient, it expands the trust boundary to the npm ecosystem and allows package-install-time code execution on the host.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script persists `TENCENTCLOUD_SECRET_ID` and `TENCENTCLOUD_SECRET_KEY` directly into a JSON config file on disk, with no permission hardening, encryption, or warning to the user. If the file is readable by other local users, backed up insecurely, or later exposed through logs or tooling, long-lived cloud credentials can be stolen and used to access or manipulate Lighthouse resources.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The script writes configuration that causes future execution of `npx -y lighthouse-mcp-server`, which delegates runtime code retrieval and execution to the npm ecosystem. In this skill context, that is more dangerous because the executed package receives cloud credentials through environment variables and is intended to manage Tencent Cloud resources, increasing the blast radius of any package compromise.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
The script configures the MCP server to run via `npx lighthouse-mcp-server` without pinning a specific version or integrity source. That means future executions may fetch and run whatever package version is current at the time, creating a supply-chain risk where a compromised, typo-squatted, or maliciously updated package could execute arbitrary code with the user's privileges and access to Tencent Cloud credentials.

Static analysis

No suspicious patterns detected.