Back to skill

Security audit

Supabase Dashboard Builder

Security checks for vulnerabilities and agentic risk

Overview

The skill is not deceptive or self-executing, but its dashboard template teaches an unsafe privileged Supabase proxy pattern that could expose sensitive admin data if copied into production.

Review this skill carefully before installing or using it to generate production code. If used, require authentication and authorization on every dashboard endpoint, avoid service-role keys for user-shaped reads where possible, hardcode safe table and column projections, bound pagination, encode upstream query parameters safely, and restrict CORS to explicit trusted origins.

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
SKILL.md:33
Finding
Unauthenticated Privileged Supabase Data Proxy with Caller-Controlled Query Selection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 33-46 **Vulnerability Type**: Unauthenticated access to a privileged database proxy **Risk Level**: High ### Vulnerable Code ```python SUPABASE_KEY = os.environ["SUPABASE_SERVICE_KEY"] HEADERS = {"apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}"} app = FastAPI() @app.get("/api/mc/{table}") async def get_table(table: str, select: str = "*", limit: int = 100, offset: int = 0): allowed = {"ai_agents", "skills", "knowledge_vault", "tools", "workflows"} if table not in allowed: raise HTTPException(403, "Table not allowed") url = f"{SUPABASE_URL}/rest/v1/{table}?select={select}&limit={limit}&offset={offset}" async with httpx.AsyncClient() as client: r = await client.get(url, headers={**HEADERS, "Prefer": "count=exact"}) return r.json() ``` ### Technical Analysis The documented FastAPI endpoint does not perform authentication or authorization before proxying requests to Supabase with `SUPABASE_SERVICE_KEY`. A Supabase service-role credential is typically highly privileged and may bypass row-level security policies. Consequently, the table allowlist alone does not adequately protect individual records or sensitive columns. The endpoint also defaults `select` to `*`, exposing every column in an allowed table. This conflicts with the document's later recommendation to use lightweight, explicit column selections and may disclose large or sensitive fields such as prompts or knowledge records. Additionally, the caller-controlled `select` value is interpolated directly into the URL. Because it is not passed through `httpx` query parameter encoding or restricted to an allowlist of columns, a value containing query delimiters such as `&` could introduce additional PostgREST parameters and alter the upstream request. ### Attack Path 1. An attacker identifies a deployed dashboard API containing `/api/mc/{table}`. 2. The attacker requests an allowl ...[truncated 1280 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication for every dashboard API endpoint. 2. Enforce role-based authorization for each table, operation, row, and column. 3. Avoid using a Supabase service-role credential for user-facing read requests. Prefer a restricted database role or forward a validated user token so row-level security remains effective. 4. Define fixed column allowlists for each permitted table and reject all unapproved columns. 5. Remove the `select="*"` default. Use explicit, minimal defaults that exclude sensitive or large fields. 6. Construct upstream requests through the `params` argument so `httpx` safely encodes query values: ```python params = { "select": validated_select, "limit": validated_limit, "offset": validated_offset, } r = await client.get( f"{SUPABASE_URL}/rest/v1/{table}", params=params, headers={**HEADERS, "Prefer": "count=exact"}, ) ``` 7. Validate and bound `limit` and `offset` to prevent bulk extraction and resource exhaustion. 8. Return controlled errors after checking the upstream status instead of forwarding arbitrary upstream response bodies. 9. Add access logging, rate limiting, and monitoring for unusual pagination or bulk table access. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:154
Finding
Unrestricted Cross-Origin Resource Sharing Configuration<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 154-158 **Vulnerability Type**: Overly permissive CORS policy **Risk Level**: Medium ### Vulnerable Code ```python # CORS issues in dev: Add CORS middleware if frontend is on different port: app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) ``` ### Technical Analysis The recommended middleware configuration allows every web origin to send requests using any HTTP method and arbitrary request headers. This removes the browser's same-origin protection for API responses that satisfy the policy. Although permissive CORS does not independently grant server-side privileges, it significantly expands the attack surface when combined with sensitive or unauthenticated endpoints. In this project pattern, it would allow an attacker-controlled website to invoke and read responses from the privileged Supabase proxy directly from a visitor's browser. The guidance labels this as a development fix but does not include an environment guard or warn against deploying it to production. ### Attack Path 1. A developer applies the suggested wildcard CORS configuration to a deployed FastAPI application. 2. An attacker hosts a malicious web page containing JavaScript that requests an API endpoint such as: ```text GET https://dashboard.example/api/mc/knowledge_vault ``` 3. A user visits the attacker-controlled page. 4. The browser sends the cross-origin request to the dashboard API. 5. The server returns an access-control policy permitting the attacker's origin. 6. The attacker's JavaScript reads the API response and sends the extracted data to infrastructure controlled by the attacker. ### Impact Assessment This configuration permits any website to interact with and read supported API responses from a user's browser. When combined with the unauthenticated service-role proxy documented in the same file, it facilitates cross-origin extraction of Supabas ...[truncated 247 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the wildcard origin with an explicit allowlist of trusted frontend origins: ```python app.add_middleware( CORSMiddleware, allow_origins=["https://dashboard.example.com"], allow_methods=["GET"], allow_headers=["Authorization", "Content-Type"], allow_credentials=False, ) ``` 2. Permit only the HTTP methods and request headers required by the dashboard. 3. Maintain separate development and production CORS configurations. 4. Bind development servers to localhost where practical and never promote a wildcard development policy to production. 5. If cookies or other browser credentials are used, enable credentialed CORS only for exact trusted origins and add CSRF protections where applicable. 6. Test rejected origins as part of deployment security checks. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The example exposes a server endpoint that performs client-driven reads against Supabase using the service-role key, which bypasses row-level security and elevates every allowed read to highly privileged access. Even with a table allowlist, user-controlled table, select, limit, and offset parameters can enable broad extraction of sensitive administrative data from internal tables that were never meant to be readable by dashboard users.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The guidance recommends fully permissive CORS (allow_origins, allow_methods, and allow_headers all set to "*") for an admin dashboard backend without warning about the consequences. For a privileged dashboard API, this weakens origin-based isolation and makes it easier for arbitrary websites to issue cross-origin requests to the backend from a victim's browser, especially if authentication is later added via cookies or other ambient credentials.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
Including wildcard CORS in instructional content for a Supabase-backed admin dashboard, without any security warning or scoping guidance, is unsafe because readers may copy it directly into production. In this context the backend fronts sensitive operational data, so normalizing permissive cross-origin access increases the chance of unintended data exposure or abuse once the API evolves beyond simple local development.