T09 · Insecure Skill Coding Practices
- Location
SKILL.md:15- Finding
Unnecessary Plaintext Collection of a CapRover Master Password
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent CapRover deployment helper, but it should be reviewed carefully because it stores high-value credentials and can trigger live deployments without strong scoping or confirmation.
Install only if you are comfortable giving the skill deployment authority. Prefer per-app CapRover tokens over the master password, avoid storing secrets in plaintext config files, add a real gitignore for local config, require manual confirmation before deploys, redact webhook URLs from logs, and pin GitHub Actions or package versions before using the templates in production.
SKILL.md:15Unnecessary Plaintext Collection of a CapRover Master Password
scripts/deploy.py:187CapRover Application Token Exposed Through Process Arguments
scripts/deploy.py:137Credential-Bearing CapRover Webhook URL Partially Disclosed in Logs
SKILL.md:163Deployment Workflows Execute Dependencies Referenced by Mutable Versions
The skill claims it can scaffold workflows, generate deployment files, and configure secrets, but the documented behavior mainly covers triggering existing deploy paths and listing status. This mismatch can mislead operators about what automation will do, causing unsafe assumptions and potentially prompting manual secret handling or deployment steps outside expected review paths.
The skill explicitly describes network calls and shell-based deployment actions but declares no tool restrictions or permission boundaries. In an agent environment, that increases the chance of the skill being invoked with capabilities to trigger real external changes without clear sandboxing or authorization controls.
The trigger phrases are broad enough that ordinary deployment-related conversation could activate a skill that performs live deployment actions. In this context, over-broad activation is risky because the skill can contact GitHub and CapRover and may initiate production-impacting changes.
The skill is designed to trigger remote deployments and mutate live systems, but it does not prominently warn that these are state-changing actions. Without explicit warning and confirmation, users may invoke it casually and unintentionally deploy code, rebuild apps, or affect production availability.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -X POST \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/OWNER/REPO/actions/workflows/deploy.yml/dispatches \
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return False
ref = branch or app_config.get("default_branch", "main")
url = f"https://api.github.com/repos/{repo}/actions/workflows/{workflow}/dispatches"
headers = {
"Authorization": f"Bearer {token}",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return False
ref = branch or app_config.get("default_branch", "main")
url = f"https://api.github.com/repos/{repo}/actions/workflows/{workflow}/dispatches"
headers = {
"Authorization": f"Bearer {token}",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return False
ref = branch or app_config.get("default_branch", "main")
url = f"https://api.github.com/repos/{repo}/actions/workflows/{workflow}/dispatches"
headers = {
"Authorization": f"Bearer {token}",
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return False
ref = branch or app_config.get("default_branch", "main")
url = f"https://api.github.com/repos/{repo}/actions/workflows/{workflow}/dispatches"
headers = {
"Authorization": f"Bearer {token}",
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
return False
# Check if caprover CLI is installed
result = subprocess.run(["which", "caprover"], capture_output=True)
if result.returncode != 0:
print("❌ caprover CLI not installed. Run: npm install -g caprover")
return False
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
cmd += ["--branch", branch]
print(f" App: {app_name}")
result = subprocess.run(cmd, capture_output=False)
if result.returncode == 0:
print("✅ Deployed successfully!")
return True
No suspicious patterns detected.