T09 · Insecure Skill Coding Practices
- Location
templates/scripts/supabase/provision-preview-branch.ts:154- Finding
Supabase Service-Role Key Exposed Through Command-Line Arguments and Error Logs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is coherent for preview database management, but its bundled scripts handle powerful database secrets and can delete or rewrite cloud database resources with too little scoping.
Review before installing in a real project. Use only with a Supabase/Vercel/GitHub setup you intend it to manage, pin dependencies, require dry-run and explicit execute modes for cleanup, restrict orphan cleanup to managed preview branches, avoid passing service-role keys through CLI arguments, keep service-role values server-only, and enable auth/data/storage copying only after a written hydration policy and user approval.
templates/scripts/supabase/provision-preview-branch.ts:154Supabase Service-Role Key Exposed Through Command-Line Arguments and Error Logs
templates/scripts/supabase/provision-preview-branch.ts:365TLS Certificate Validation Disabled for Privileged PostgreSQL Connections
templates/scripts/supabase/cleanup-orphan-preview-branches.ts:128Orphan Cleanup Can Delete Unrelated Supabase Branches
templates/package-dev-dependencies.json:3Floating Dependency Versions and Registry-Fallback Execution for Credentialed CLI Tools
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- applying migrations
- linking production for `supabase db push`
Store access tokens in GitHub Actions secrets or local CLI auth. Non-secret project refs can be stored in config if the user approves.
## Vercel
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Keep the default conservative. Enable auth/data/storage copying only after the user chooses a hydration policy.
Pass `--dry-run` to the provision script to print the full plan (create vs reuse, hydration source, what would be copied, which env vars would be set) without making changes. This also smoke-tests the access token and branch listing.
## Persistent Preview Environments
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Do not point feature or agent branches at production.
- Do not apply feature-branch migrations to shared develop until merge.
- Do not copy production data into preview databases without explicit user approval.
- Do not commit secrets, service role keys, access tokens, preview passwords, or `.env.local`.
- Before changing GitHub Actions, Vercel env vars, Supabase branches, or database hydration behavior, explain the change and the credentials needed.
- When changing database schema, validate migrations locally or in preview before shared environments.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Do not point feature or agent branches at production.
- Do not apply feature-branch migrations to shared develop until merge.
- Do not copy production data into preview databases without explicit user approval.
- Do not commit secrets, service role keys, access tokens, preview passwords, or `.env.local`.
- Before changing GitHub Actions, Vercel env vars, Supabase branches, or database hydration behavior, explain the change and the credentials needed.
- When changing database schema, validate migrations locally or in preview before shared environments.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Do not point feature or agent branches at production.
- Do not apply feature-branch migrations to shared develop until merge.
- Do not copy production data into preview databases without explicit user approval.
- Do not commit secrets, service role keys, access tokens, preview passwords, or `.env.local`.
- Before changing GitHub Actions, Vercel env vars, Supabase branches, or database hydration behavior, explain the change and the credentials needed.
- When changing database schema, validate migrations locally or in preview before shared environments.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Do not point feature or agent branches at production.
- Do not apply feature-branch migrations to shared develop until merge.
- Do not copy production data into preview databases without explicit user approval.
- Do not commit secrets, service role keys, access tokens, preview passwords, or `.env.local`.
- Before changing GitHub Actions, Vercel env vars, Supabase branches, or database hydration behavior, explain the change and the credentials needed.
- When changing database schema, validate migrations locally or in preview before shared environments.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Do not point feature or agent branches at production.
- Do not apply feature-branch migrations to shared develop until merge.
- Do not copy production data into preview databases without explicit user approval.
- Do not commit secrets, service role keys, access tokens, preview passwords, or `.env.local`.
- Before changing GitHub Actions, Vercel env vars, Supabase branches, or database hydration behavior, explain the change and the credentials needed.
- When changing database schema, validate migrations locally or in preview before shared environments.
The function begins a replication-mode session and truncates target public tables with restart identity cascade before repopulating them from the source branch. This is a destructive, irreversible data operation, but the code provides no confirmation prompt or explicit warning before execution beyond generic row-count logs after the fact.
The script pushes the Supabase service-role key into Vercel preview environment variables, making a highly privileged secret available to preview deployments. If preview application code, build steps, logs, third-party integrations, or contributors with preview access are compromised, the key could be abused to bypass RLS and fully administer the preview database and related services.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// the Supabase CLI token out of .env(.local) ourselves if it isn't already set.
function loadAccessTokenFromEnvFiles(): void {
if (process.env.SUPABASE_ACCESS_TOKEN) return;
for (const path of ['.env.local', '.env']) {
if (!existsSync(path)) continue;
const match = readFileSync(path, 'utf8').match(/^\s*SUPABASE_ACCESS_TOKEN\s*=\s*(.*)$/m);
if (match) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// the Supabase CLI token out of .env(.local) ourselves if it isn't already set.
function loadAccessTokenFromEnvFiles(): void {
if (process.env.SUPABASE_ACCESS_TOKEN) return;
for (const path of ['.env.local', '.env']) {
if (!existsSync(path)) continue;
const match = readFileSync(path, 'utf8').match(/^\s*SUPABASE_ACCESS_TOKEN\s*=\s*(.*)$/m);
if (match) {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
// the Supabase CLI token out of .env(.local) ourselves if it isn't already set.
function loadAccessTokenFromEnvFiles(): void {
if (process.env.SUPABASE_ACCESS_TOKEN) return;
for (const path of ['.env.local', '.env']) {
if (!existsSync(path)) continue;
const match = readFileSync(path, 'utf8').match(/^\s*SUPABASE_ACCESS_TOKEN\s*=\s*(.*)$/m);
if (match) {
This script writes SUPABASE_SERVICE_ROLE_KEY, along with the URL and anon key, into .env.local. The service-role key is a highly privileged server secret; placing it into a generic project-local env file increases the chance it is accidentally consumed by the wrong runtime, exposed to local tooling, leaked in logs, or committed/mishandled by developers.
}
function updateEnvLocal(values: Record<string, string>): void {
const path = '.env.local';
const existing = existsSync(path) ? readFileSync(path, 'utf8') : '';
const { lines, seenKeys } = parseEnvFile(existing);
const nextLines = lines.map((line) => {
In local mode, the script retrieves local Supabase branch details and persists the service-role key into .env.local. Even in a dev context, automatically materializing a privileged database secret into a common local env file expands the attack surface and makes accidental disclosure more likely.
[config.envKeys.supabaseAnonKey]: details.SUPABASE_ANON_KEY,
[config.envKeys.supabaseServiceRoleKey]: details.SUPABASE_SERVICE_ROLE_KEY,
});
console.log(`.env.local now points to local Supabase: ${details.SUPABASE_URL}`);
return;
}
For remote branch switching, the script fetches branch credentials and writes the service-role key into .env.local. In the context of a tool designed to manage preview/develop/production database workflows, this is more dangerous because it automates distribution of a high-privilege secret across multiple branch environments, increasing the chance of misuse or accidental exposure.
[config.envKeys.supabaseServiceRoleKey]: details.SUPABASE_SERVICE_ROLE_KEY,
});
console.log(`.env.local now points to Supabase branch "${branch.name}" for Git branch "${gitBranch}".`);
}
try {
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
} catch (error) {
if ((process.argv[2] || 'status') === 'auto') {
console.warn(`Skipping Supabase env auto-switch: ${error instanceof Error ? error.message : String(error)}`);
console.warn('Continuing with existing .env / .env.local values.');
process.exit(0);
}
console.error(error instanceof Error ? error.message : String(error));
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
} catch (error) {
if ((process.argv[2] || 'status') === 'auto') {
console.warn(`Skipping Supabase env auto-switch: ${error instanceof Error ? error.message : String(error)}`);
console.warn('Continuing with existing .env / .env.local values.');
process.exit(0);
}
console.error(error instanceof Error ? error.message : String(error));
The skill clearly contemplates environment-variable handling, external credential use, and cloud/CI interactions, but it does not declare an explicit tool scope such as allowed tools or permissions. In an agent environment, that ambiguity can lead to broader-than-necessary access being granted at runtime, increasing the chance of unintended network calls or secret exposure during execution.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
## Credential Rule
Before running commands that require external access, explain what credentials are needed, why they are needed, where they will be stored, and ask the user for permission. Do not ask the user to paste secrets into committed files.
Read `references/credentials.md` for the exact checklist.
Referencing npx skills add without a pinned package version introduces supply-chain risk because the command may fetch the latest published package at execution time. A compromised or newly malicious release could be installed and run in the user's environment with little visibility.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
For npx skills add Aidan945/SafeAgentDB, keep the canonical skill at:
skills/safeagentdb/SKILL.md
The skills CLI discovers SKILL.md files at the repository root and under top-level skill container folders such as skills/ and .agents/skills/.
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
For npx skills add Aidan945/SafeAgentDB, keep the canonical skill at:
skills/safeagentdb/SKILL.md
The skills CLI discovers SKILL.md files at the repository root and under top-level skill container folders such as skills/ and .agents/skills/.
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
For npx skills add Aidan945/SafeAgentDB, keep the canonical skill at:
skills/safeagentdb/SKILL.md
The skills CLI discovers SKILL.md files at the repository root and under top-level skill container folders such as skills/ and .agents/skills/.
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
For npx skills add Aidan945/SafeAgentDB, keep the canonical skill at:
skills/safeagentdb/SKILL.md
The skills CLI discovers SKILL.md files at the repository root and under top-level skill container folders such as skills/ and .agents/skills/.
Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.insecure_tls_verification