T09 · Insecure Skill Coding Practices
- Location
scripts/launchpulse.cjs:126- Finding
Authentication and third-party secrets can be redirected to an arbitrary API endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is broadly coherent with LaunchPulse app building, but it also exposes high-impact production, billing, database, publishing, and secret-handling actions with insufficient guardrails.
Review this skill before installing. Use it only with a trusted LaunchPulse account and avoid supplying production payment, GitHub, Fly.io, app-store, or database credentials unless you understand where they are sent and stored. Do not use --api-base or LAUNCHPULSE_API_BASE_URL except for a trusted local backend, and consider removing or permission-hardening the stored auth file after use.
scripts/launchpulse.cjs:126Authentication and third-party secrets can be redirected to an arbitrary API endpoint
scripts/launchpulse.cjs:187LaunchPulse personal access token is stored without explicit restrictive permissions
scripts/launchpulse.cjs:1789Fly.io API token is transmitted in a URL query parameter
The skill obtains a personal access token and stores it locally in a predictable path, while also allowing PAT/JWT injection through environment variables and command flags. These practices materially increase exposure risk through local file compromise, weak file permissions, backups, shell history, debug logs, or accidental disclosure, and the token appears sufficient to access the user's LaunchPulse account and projects.
The first time you run the skill, it automatically starts a device-login flow:
1. OpenClaw prints a sign-in link
2. You open it, sign in with Google on launchpulse.ai, and confirm
3. OpenClaw receives a personal access token (PAT) and stores it locally
Token storage path: `${OPENCLAW_STATE_DIR:-~/.openclaw}/launchpulse/auth.json`
The skill supports writing .env files and passing payment and platform keys, including sensitive secret material, through CLI arguments and files. This is dangerous because secrets can leak through shell history, process listings, logs, workspace files, or accidental inclusion in generated projects, leading to credential compromise and abuse of payment or backend services.
- `/launchpulse storage init`
- `/launchpulse storage upload <projectId> --payload-file ./upload.json`
- `/launchpulse env-files list <projectId>`
- `/launchpulse env-files save <projectId> --file-path vitereact/.env --vars-file ./vars.json`
- `/launchpulse payments inject-env <projectId> --project-type vitereact`
- `/launchpulse payments setup <projectId> --project-type expo --stripe-publishable-key pk_test_... --revenuecat-ios-key appl_... --revenuecat-secret-key sk_...`
The CLI’s declared purpose is app generation, but its exposed command surface also includes deployment, domain registration/mapping, billing upgrades, database access, app-store publishing, storage operations, and payment secret handling. This capability expansion materially increases the attack surface and the chance that an agent or user invokes high-impact operations outside the expected trust boundary.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
--api-base <url> (default: env LAUNCHPULSE_API_BASE_URL or hosted LaunchPulse API)
--pat <token> (default: env LAUNCHPULSE_PAT; or stored device-login token)
--api-key <token> alias for --pat (for API-key style workflows)
--access-token <jwt> (default: env LAUNCHPULSE_ACCESS_TOKEN; Supabase access token)
--user-id <uuid> legacy fallback for older LaunchPulse backends that require userId
--no-login fail instead of starting device-login flow when unauthenticated
--name <project-slug> preferred project id/slug
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
--api-base <url> (default: env LAUNCHPULSE_API_BASE_URL or hosted LaunchPulse API)
--pat <token> (default: env LAUNCHPULSE_PAT; or stored device-login token)
--api-key <token> alias for --pat (for API-key style workflows)
--access-token <jwt> (default: env LAUNCHPULSE_ACCESS_TOKEN; Supabase access token)
--user-id <uuid> legacy fallback for older LaunchPulse backends that require userId
--no-login fail instead of starting device-login flow when unauthenticated
--name <project-slug> preferred project id/slug
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
--api-base <url> (default: env LAUNCHPULSE_API_BASE_URL or hosted LaunchPulse API)
--pat <token> (default: env LAUNCHPULSE_PAT; or stored device-login token)
--api-key <token> alias for --pat (for API-key style workflows)
--access-token <jwt> (default: env LAUNCHPULSE_ACCESS_TOKEN; Supabase access token)
--user-id <uuid> legacy fallback for older LaunchPulse backends that require userId
--no-login fail instead of starting device-login flow when unauthenticated
--name <project-slug> preferred project id/slug
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
--api-base <url> (default: env LAUNCHPULSE_API_BASE_URL or hosted LaunchPulse API)
--pat <token> (default: env LAUNCHPULSE_PAT; or stored device-login token)
--api-key <token> alias for --pat (for API-key style workflows)
--access-token <jwt> (default: env LAUNCHPULSE_ACCESS_TOKEN; Supabase access token)
--user-id <uuid> legacy fallback for older LaunchPulse backends that require userId
--no-login fail instead of starting device-login flow when unauthenticated
--name <project-slug> preferred project id/slug
App-store publishing and 2FA submission are high-trust account actions with irreversible external consequences, including releasing software and handling authentication challenges. Exposing them in a broadly described generation skill makes accidental or induced misuse more likely, especially in agentic contexts where users may not expect publication behavior.
Domain search, checkout, registration, verification, and mapping allow actions that can incur cost, affect public routing, and modify externally visible infrastructure. These operations exceed the expected scope of a quick-start app builder and could be abused by a prompt-injected agent flow to purchase domains or redirect traffic.
The db query action accepts arbitrary SQL and forwards it to a backend project database endpoint, enabling unrestricted reads or mutations if backend authorization is permissive. In an agent skill, this is especially dangerous because natural-language workflows could be steered into exfiltrating data, altering records, or damaging application state.
The payments setup flow collects Stripe and RevenueCat keys, then transmits and stores them through remote API endpoints and env-file save operations. This creates significant secret-handling risk: a compromised agent flow, backend, logs, or mis-scoped permissions could expose payment credentials or inject them into the wrong project.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
throw new Error('Usage: launchpulse.cjs payments setup <projectId> [--project-type <vitereact|expo>] [keys...] [--vars-file <json>]');
}
const projectType = normalizeProjectType(cfg.projectType || args[1]) || 'vitereact';
const envPath = cfg.filePath || (projectType === 'expo' ? 'expo/.env' : 'vitereact/.env');
const generatedVars = [];
if (cfg.stripePublishableKey) {
The skill explicitly directs the assistant to run a Node script, perform networked API operations, and use environment variables/tokens, but it declares no tool scope or permissions boundary. That omission can cause users or hosting platforms to underestimate the skill's capabilities, reducing informed consent and weakening policy enforcement around network and credential use.
The skill says it 'auto-approves' AI-planned MVP features, meaning an autonomous system can decide what will be built and initiated without a manual review checkpoint. In the context of code generation, deployment, and downstream production operations, this raises the risk of unintended functionality, insecure defaults, cost-incurring actions, or propagation of harmful changes from ambiguous prompts.
**What it does:**
1. Creates a new project (web or Expo mobile)
2. Plans MVP features using AI and auto-approves them
3. Starts Quick Start (single-pass background build)
4. Returns immediately with project id/session id so progress can be monitored
5. Iterates on existing projects with change requests
The skill states that a personal access token is obtained and stored locally, and also supports direct token injection via flags/environment variables, but it does not present this as a clear security warning to the user. This is dangerous because users may provide high-value credentials without understanding storage, reuse, exposure, or local compromise risks.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
- `/launchpulse upgrade --tokens 0` (buy 50K token pack)
**Quick Start a web app:**
- `/launchpulse web "Create a landing page for a dog walking business"`
**Quick Start a mobile app (Expo):**
- `/launchpulse mobile "Create an Expo app for habit tracking"`
The documented production operations include deploys, domain changes, database queries, environment-file writes, storage actions, and payment/app-store setup, but there are no user-facing warnings about their security-sensitive or potentially destructive nature. In a user-invocable skill, this increases the chance of accidental deployment changes, credential mishandling, data exposure, or modification of production systems without sufficient confirmation.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
const os = require('node:os');
const path = require('node:path');
const VERSION = '1.1.1';
const DEFAULT_API_BASE_URL = 'https://api.launchpulse.ai/api';
function usage(exitCode) {
const text = `
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
const os = require('node:os');
const path = require('node:path');
const VERSION = '1.1.1';
const DEFAULT_API_BASE_URL = 'https://api.launchpulse.ai/api';
function usage(exitCode) {
const text = `
The device-login PAT is written to a persistent local auth file without any permission hardening or meaningful warning to the user about credential persistence. On multi-user systems or insecure environments, this increases the risk of token theft and unauthorized reuse.
The manifest focuses on building apps from descriptions and starting builds, but the upgrade command implements commerce and account-billing actions. Billing plan management is not an obvious requirement for the core build-from-text workflow and represents an account-management capability outside the stated purpose.
The skill accepts highly sensitive payment/service keys and sends them to remote API endpoints without prominent safety messaging or secure-entry guidance. In an agent setting, users may not realize they are disclosing production secrets to a hosted backend, increasing the chance of mishandling or over-sharing.
Detected: suspicious.env_credential_access, suspicious.potential_exfiltration