T03 · Remote Payload Retrieval and Execution
- Location
scripts/install_server.py:52- Finding
Remote installer is downloaded and executed without integrity verification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This MCP marketplace skill is mostly purpose-aligned, but it gives agents high-impact install and runtime authority without enough containment or verification.
Review every generated install, update, health-check, Docker, and shell-profile command before allowing the agent to run it. Prefer pinned package versions and verified images, avoid sudo/global installs where possible, do not enable the Docker socket entry unless you accept host-level risk, and run health checks only for servers you trust with your environment variables.
scripts/install_server.py:52Remote installer is downloaded and executed without integrity verification
scripts/install_server.py:89Unpinned third-party packages are downloaded and executed during installation verification
scripts/health_check.py:206Health checks expose the complete parent environment to spawned MCP servers
assets/known_servers.json:1083Unverified mutable Docker image is granted control of the host Docker daemon
scripts/secrets_helper.py:52Secrets-manager shell commands are generated through unsafe string interpolation
The description promises a full-featured MCP server lifecycle and discovery tool, including installation, configuration, registry search, config generation, management operations, and health testing. The actual code does not perform any of those broader tasks. Instead, it only reads two local JSON files and evaluates compatibility between a known server and a specific client using metadata rules. This is related to MCP troubleshooting, but it is a much narrower function than the declared primary purpose. There are no undeclared dangerous behaviors, but the declared description materially overstates what this code chunk actually does.
The code’s primary purpose is contribution tooling for catalog maintenance: it validates server metadata fields, checks for duplicate IDs against a local known_servers.json file, constructs a catalog entry object, and generates a pull request template. While the PR template text mentions install testing and health checks, the script does not actually perform those actions. This is materially different from the declared purpose of end-user MCP server installation, configuration, discovery, and operational management.
The declared description presents a full-featured MCP server management tool. The supplied code chunk is much narrower: it scans the local system for globally installed npm packages, pip packages, and uv tools; loads a local known-server catalog; reads common MCP configuration files; and reports which known MCP servers are installed and whether they are already configured. That is related to MCP server discovery/listing, but it does not implement installation, configuration generation, registry search, health checks, testing, troubleshooting, removal, or updates. Additionally, the code performs local environment/package/config inspection, which is a concrete capability not explicitly declared in the permissions or description. Because the actual behavior is only a subset and includes undeclared system/package scanning, the description does not accurately represent this code chunk.
The declared description promises a full-featured MCP server management capability, including discovery across multiple registries, installation, configuration generation for several clients, lifecycle management, and health checks/troubleshooting. The supplied code does only a small subset: it reads a local known_servers.json file, checks whether local commands like npm/npx/uvx/pip/docker are present, and constructs install-related command strings. It does not search external registries, does not install anything, does not generate config files, does not list/remove/update servers, and does not perform actual health checks of MCP servers. Although prerequisite checking and generating install commands are related to installation, the code's actual behavior is materially narrower than the declared purpose.
The declared description promises a broad MCP server installation, discovery, configuration, and health-check tool. This code chunk only manages bookkeeping for already-installed servers in a JSON state file and reports whether a server appears in certain config files. Its primary purpose is narrower than declared. While list/remove/status/info overlap partially with the description, major advertised capabilities—installing servers, searching registries, generating configs, and actual health checking/troubleshooting—are absent from the supplied code.
The declared description presents a broad MCP server management tool covering installation, configuration generation, registry search, listing, removal, update, and health checking. The supplied code chunk does none of those primary management actions. It loads static template and known-server metadata, scans a project directory for files/patterns, reads existing MCP configuration files only to determine which servers are already configured, and emits recommendation JSON. Reading local Claude/Cursor/.mcp config files is consistent with recommendation context, but the core behavior is materially narrower and different from the declared purpose. Therefore this chunk does not accurately represent the declared functionality.
The declared description focuses on MCP server lifecycle management: searching registries, installing/removing servers, generating client configs, listing servers, and testing server health. The actual code does none of that. Instead, it inspects the local environment for secrets-management tools and outputs JSON containing suggested commands for saving and loading tokens. While secrets handling could be a supporting feature in a broader MCP setup workflow, this code chunk’s primary purpose is materially different from the declared skill purpose and lacks the core server-management behaviors described. Therefore this is a clear description-behavior mismatch.
This code chunk’s primary function is 'smart recommendation' of MCP servers. It loads affinity data and known server metadata from local assets, inspects local installed/configured server state from OpenClaw and Claude/Cursor config files, scores candidate servers, and prints recommendation JSON. The declared description instead emphasizes MCP server lifecycle management and registry search/discovery, including install, configuration generation, removal, status, health checks, and troubleshooting. While recommendation/discovery is loosely adjacent to 'what MCP servers are available,' this script is materially narrower and different in purpose: it recommends complements based on current setup rather than managing servers or searching registries. Therefore the description does not accurately represent what this code chunk actually does.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"GITHUB_TOKEN": "https://github.com/settings/tokens/new?scopes=repo"
},
"requiredEnvDescriptions": {
"GITHUB_TOKEN": "Personal access token with 'repo' scope"
},
"optionalEnv": [],
"verified": true,
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"GITHUB_TOKEN": "https://github.com/settings/tokens/new?scopes=repo"
},
"requiredEnvDescriptions": {
"GITHUB_TOKEN": "Personal access token with 'repo' scope"
},
"optionalEnv": [],
"verified": true,
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"GITHUB_TOKEN": "https://github.com/settings/tokens/new?scopes=repo"
},
"requiredEnvDescriptions": {
"GITHUB_TOKEN": "Personal access token with 'repo' scope"
},
"optionalEnv": [],
"verified": true,
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"GITHUB_TOKEN": "https://github.com/settings/tokens/new?scopes=repo"
},
"requiredEnvDescriptions": {
"GITHUB_TOKEN": "Personal access token with 'repo' scope"
},
"optionalEnv": [],
"verified": true,
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"GITHUB_TOKEN": "https://github.com/settings/tokens/new?scopes=repo"
},
"requiredEnvDescriptions": {
"GITHUB_TOKEN": "Personal access token with 'repo' scope"
},
"optionalEnv": [],
"verified": true,
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"requiredEnv": [],
"requiredEnvLinks": {},
"requiredEnvDescriptions": {},
"optionalEnv": ["KUBECONFIG"],
"verified": true,
"popularity": 2000,
"tags": ["kubernetes", "k8s", "kubectl", "pods", "deployments", "cluster", "devops"]
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"AIRTABLE_API_KEY": "https://airtable.com/create/tokens"
},
"requiredEnvDescriptions": {
"AIRTABLE_API_KEY": "Airtable Personal Access Token"
},
"optionalEnv": [],
"verified": true,
Mounting /var/run/docker.sock into a container gives that container effectively root-equivalent control over the host Docker daemon, enabling container breakout, arbitrary container creation, filesystem mounting, and broad host compromise. In a marketplace/catalog context, shipping this as an installable server definition without a strong warning materially increases the chance users enable a highly privileged integration without understanding the risk.
"package": "mcp/docker",
"dockerImage": "mcp/docker:latest",
"dockerPorts": [],
"dockerVolumes": ["/var/run/docker.sock:/var/run/docker.sock"],
"args": [],
"requiredEnv": [],
"requiredEnvLinks": {},
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
1. Go to [Google Cloud Console → APIs & Services → Credentials](https://console.cloud.google.com/apis/credentials)
2. Create **OAuth 2.0 Client ID** (type: Desktop App)
3. Download the `credentials.json` file
4. Run the server's auth flow (usually `python3 -m <module> --auth`) — this opens a browser for consent
5. The server stores refresh tokens locally (typically in `~/.config/<server>/token.json`)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
5. Copy the **Bot User OAuth Token** (starts with `xoxb-`)
6. Set: `export SLACK_BOT_TOKEN=xoxb-your-token-here`
## GitHub Apps (vs Personal Access Tokens)
Some servers support GitHub App authentication for organization-level access.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
5. Copy the **Bot User OAuth Token** (starts with `xoxb-`)
6. Set: `export SLACK_BOT_TOKEN=xoxb-your-token-here`
## GitHub Apps (vs Personal Access Tokens)
Some servers support GitHub App authentication for organization-level access.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Some servers support GitHub App authentication for organization-level access.
### Personal Access Token (Simple)
1. Go to [GitHub Settings → Developer → Personal Access Tokens](https://github.com/settings/tokens/new)
2. Select required scopes (typically `repo`, `read:org`)
Skill accesses MCP server configuration files (mcp.json). MCP configs contain server URLs, authentication tokens, and tool definitions — reading them allows the skill to discover and potentially abuse other tool integrations.
OpenClaw doesn't see the new MCP server after adding it to `.mcp.json`.
**Fix:**
1. Verify `.mcp.json` is valid JSON: `python3 -c "import json; json.load(open('.mcp.json')); print('OK')"`
2. Verify the file is in the project root directory
3. Restart OpenClaw to reload the configuration
4. Check that the server entry is inside the `"mcpServers"` key
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
proc = None
try:
# Merge with os.environ so PATH and other essentials are inherited
merged_env = dict(os.environ)
merged_env.update(env)
proc = subprocess.Popen(
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"note": "Signed in" if available else "CLI found but not signed in — run 'op signin' first",
})
# Check macOS Keychain
if shutil.which("security"):
managers.append({
"name": "keychain",
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
"note": "Signed in" if available else "CLI found but not signed in — run 'op signin' first",
})
# Check macOS Keychain
if shutil.which("security"):
managers.append({
"name": "keychain",
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Check macOS Keychain
if shutil.which("security"):
managers.append({
"name": "keychain",
"displayName": "macOS Keychain",
"command": "security",
"available": True,
No suspicious patterns detected.