Back to skill

Security audit

Caprover Management

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent CapRover admin helper, but it handles privileged infrastructure credentials in unsafe ways that warrant review before installation.

Review carefully before installing. Use only after changing the helper and examples to verify TLS certificates, preferably by trusting the CapRover server's CA certificate. Do not pass the admin password on the command line or print token material, and require explicit user confirmation before deployments, service overrides, app deletion, or volume deletion.

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/caprover.py:27
Finding
Disabled TLS Verification Exposes CapRover Administrator Credentials and Privileged API Traffic<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caprover.py:27-29` and `scripts/caprover.py:52` **Related Documentation**: `SKILL.md:17-18`, `references/api.md:6` **Vulnerability Type**: Improper TLS certificate and hostname validation **Risk Level**: High ### Vulnerable Code ```python def _make_ctx(): ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE return ctx ``` The insecure SSL context is subsequently used for all API requests: ```python req = urllib.request.Request(f"{self.base}{path}", data=body, headers=headers) try: resp = urllib.request.urlopen(req, context=self._ctx, timeout=timeout) return json.loads(resp.read()) ``` The same insecure behavior is recommended in `SKILL.md`: ```python ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE # self-signed cert on CapRover is common ``` It is also explicitly recommended in `references/api.md`: ```markdown SSL: often self-signed → disable verification in HTTP clients ``` ### Technical Analysis The helper creates a TLS context that accepts certificates from any issuer and does not verify whether the certificate belongs to the requested CapRover hostname. HTTPS encryption without peer authentication does not protect against an active man-in-the-middle attacker. This context is used during authentication, where the CapRover administrator password is placed in a JSON request body: ```python def _login(self, password: str) -> str: r = self._call("/api/v2/login", {"password": password}) return r["data"]["token"] ``` It is also used for all subsequent privileged requests carrying the `x-captain-auth` token: ```python tok = token or getattr(self, "token", None) if tok: headers["x-captain-auth"] = tok ``` Consequently, the exposed data may include: - The CapRover administrator password. - The session bearer token. - Application environment variables, which may cont ...[truncated 2431 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Preserve the secure defaults from `ssl.create_default_context()`: ```python def _make_ctx(cafile: str | None = None): ctx = ssl.create_default_context(cafile=cafile) return ctx ``` 2. For private or self-signed CapRover certificates, require an explicit CA certificate: ```python ctx = ssl.create_default_context() ctx.load_verify_locations(cafile="/secure/path/caprover-ca.pem") ``` 3. Keep hostname verification enabled and ensure the CapRover certificate includes the expected DNS name in its Subject Alternative Name extension. 4. Remove instructions from `SKILL.md` and `references/api.md` that recommend globally disabling TLS verification. Replace them with instructions for installing or specifying the private CA. 5. If an insecure development mode must exist, require an explicit option such as `allow_insecure_tls=False`, keep it disabled by default, and display a prominent warning before credentials are transmitted. It should not be used in production or automated deployments. 6. Consider certificate or public-key pinning for tightly controlled CapRover environments where private CA management is not practical. 7. Rotate the CapRover administrator password and invalidate existing session tokens if the helper has previously been used over an untrusted network. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/caprover.py:247
Finding
CapRover Administrator Password Is Accepted Through Process Arguments and Session Token Material Is Logged<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caprover.py:247-252` **Vulnerability Type**: Insecure credential input and sensitive token disclosure **Risk Level**: Medium ### Vulnerable Code ```python if len(sys.argv) < 3: print("Usage: caprover.py <base_url> <password> [app_name]") sys.exit(1) cap = CapRover(sys.argv[1], sys.argv[2]) print(f"Authenticated. Token: {cap.token[:20]}...") ``` ### Technical Analysis The command-line interface requires the CapRover administrator password as a positional argument. Command-line arguments can be exposed through: - Shell command history. - Process inspection facilities such as `/proc`, subject to operating-system access controls. - Process-monitoring and endpoint-management software. - CI/CD job definitions and execution logs. - Terminal recording or debugging output. - Wrapper scripts that preserve the invoked command. The script also prints the first 20 characters of the authentication token. A partial token normally does not provide enough information to authenticate by itself, but disclosing bearer-token material is unnecessary. If the token is a JWT, the printed prefix may expose part or all of its encoded header and payload metadata. It also creates avoidable sensitive output in terminals and logs. The Skill only needs to receive the password securely and retain the returned token in memory for authenticated requests. Neither passing the password through process arguments nor printing token material is required for its declared functionality. ### Attack Path 1. An administrator runs: ```bash python3 scripts/caprover.py https://captain.example.com administrator-password myapp ``` 2. The complete password becomes part of the shell command and process argument vector. 3. A local user, monitoring agent, CI log reader, shell-history reader, or other party with relevant access retrieves the command. 4. The attacker extracts the administrator password. 5. The attacker authenticates di ...[truncated 1145 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prompt for the password without terminal echo: ```python import getpass if len(sys.argv) < 2: print("Usage: caprover.py <base_url> [app_name]") sys.exit(1) password = getpass.getpass("CapRover administrator password: ") cap = CapRover(sys.argv[1], password) print("Authenticated successfully.") ``` 2. Remove all token output, including partial token values. Log only authentication success or failure. 3. For automation, support a protected secret source such as: - A file readable only by the executing account. - A CI/CD secret-injection mechanism. - A platform credential manager or secrets vault. - Standard input through a documented non-echoing workflow. 4. If an environment-variable fallback is provided, document that environment variables may also be visible to child processes, diagnostic tools, crash dumps, or improperly configured CI systems. Prefer file descriptors or a dedicated secret manager where possible. 5. Avoid placing passwords or tokens in exception messages, debug logs, serialized objects, or application output. 6. Rotate passwords and invalidate tokens if credentials have already appeared in shell history, process-monitoring records, terminal captures, or CI logs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Missing User Warnings

High
Confidence
98% confidence
Finding
The documentation explicitly instructs clients to disable TLS certificate verification for API connections. That defeats server authentication and enables man-in-the-middle interception or modification of authenticated CapRover API traffic, including JWT tokens, app configs, registry credentials, and deployment payloads. In this skill context, the API performs privileged deployment and infrastructure actions, which makes insecure transport guidance especially dangerous.

Missing User Warnings

High
Confidence
99% confidence
Finding
The SSL context explicitly disables certificate validation and hostname checking for all HTTPS requests, including login and authenticated API calls. This makes the helper vulnerable to man-in-the-middle interception, allowing an attacker on the network path to capture the CapRover admin password and session token or tamper with deployment actions.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill includes concrete network-capable code that authenticates to and manages a remote CapRover instance, but it does not declare any tool scope or permission boundary. That omission increases the chance an agent could use network access without clear user visibility or policy enforcement, enabling unintended remote administrative actions against infrastructure.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill instructs users to authenticate with a CapRover password and bearer-like auth token, but provides no guidance on secret handling, storage, redaction, or avoidance of logging. In this context the credentials grant administrative control over apps, deployments, env vars, volumes, and logs, so accidental disclosure could lead to full compromise of the CapRover-managed environment.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Base URL: `https://<captain-domain>`
Auth header: `x-captain-auth: <token>`
All bodies: `Content-Type: application/json`
SSL: often self-signed → disable verification in HTTP clients

## Table of Contents
1. [Authentication](#authentication)
Confidence
91% confidence
Finding
The phrase 'disable verification in HTTP clients' encourages the agent or consuming code to make an unsafe security decision automatically rather than preserving certificate validation. When applied to a management API that controls apps, volumes, env vars, logs, and registry credentials, this can expose administrative sessions and allow an attacker on-path to tamper with deployments or steal secrets.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The CLI path prints a live authentication token prefix after login, which exposes sensitive credential material to terminals, shell history capture, logs, screenshots, or CI job output. Even partial token disclosure increases the attack surface and is unnecessary for normal operation, especially in a deployment/admin helper that handles privileged CapRover access.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The CLI prints the first portion of the authentication token immediately after successful login, which can leak privileged session material into console logs and other monitoring surfaces. In this skill's context, the token grants administrative control over app deployment and configuration, so even limited exposure is more dangerous than in a low-privilege tool.

Static analysis

No suspicious patterns detected.