Official agent skill

Safe SQL Execution

by supabase in supabase/supabase

A skill your agent uses whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix…

OfficialApache-2.0Auto-check passedDatabases

Install Safe SQL Execution

skills CLI
$ npx skills add supabase/supabase --skill safe-sql-execution -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install supabase/supabase safe-sql-execution --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/supabase/supabase.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/safe-sql-execution .claude/skills/safe-sql-execution && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
safe-sql-execution
GitHub stars
111k
Token cost
~4.2k tokens
SKILL.md length
1,334 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix…

  • Works in 3 steps: Hardcoded within the application code.… → Third-party influenceable. These are SQL… → User-authored. These are SQL fragments…
  • Code will build
  • SKILL.md covers Security model, Provenance tracking, Security of SQL round-tripped… and Promoting SQL fragments to…, plus 3 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Safe SQL Execution is an agent skill from supabase/supabase, published by the product's own GitHub organization. Use whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix and never says "security," "injection," or "SafeSqlFragment." This covers: writing or editing any pg-meta function, query builder, or endpoint that builds/returns SQL for database objects (tables, views, functions, DB triggers, indexes, RLS policies); interpolating a schema/table/column/search/route-param value into SQL text; storing…

Its SKILL.md is about 4.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Databases, covering SQL, Debugging and Forms and validation. It works with SQL, Supabase and PostgreSQL. The repository describes itself as: The Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications. The licence is Apache-2.0.

When your agent uses it

  • Code will build
  • Execute SQL that runs against a users real Postgres database — even when the request reads like an ordinary feature
  • Bug fix and never says security
  • SafeSqlFragment. This covers: writing

Example prompts

  • “security,”
  • “injection,”
  • “SafeSqlFragment.”
  • “/safe-sql-execution”

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Hardcoded within the application code. These are safe to execute because
  2. Third-party influenceable. These are SQL fragments that can be influenced
  3. User-authored. These are SQL fragments that are authored by the user

What it can do on your machine

Read from SKILL.md and the folder at commit 26c838a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Safe SQL Execution loads about 4.2k tokens when it runs. Until then it costs about 258 tokens; SKILL.md has 1,334 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~258
When it runs · the whole SKILL.md, loaded when a task matches
~4.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from supabase/supabase at commit 26c838a, republished under its Apache-2.0 licence (© supabase). 1,334 words, ~4,181 tokens.

Download SKILL.mdSave it as .claude/skills/safe-sql-execution/SKILL.md (or your agent's skills folder).
name
safe-sql-execution
description
Use whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix and never says "security," "injection," or "SafeSqlFragment." This covers: writing or editing any pg-meta function, query builder, or endpoint that builds/returns SQL for database objects (tables, views, functions, DB triggers, indexes, RLS policies); interpolating a schema/table/column/search/route-param value into SQL text; storing, fetching, or re-running SQL that round-trips from the database (a policy's definition, a function/view definition, a snippet's saved content); and any "Run"/"Apply"/"Execute" action that sends SQL to a project's database (SQL editor run-selection, policy editor apply, snippet runner). Load this BEFORE writing such code, not only when reviewing a finished diff. Skip only for changes that never touch SQL text or execution — styling, unrelated data hooks, non-SQL form validation, or UI layout work.

Safe SQL execution

Supabase Studio executes SQL statements directly against the user's database. Because this is the authenticated user's own database, our security model is different from most frontend applications: a user should be able to execute any SQL statement, as long as it is proven that they themselves authored it. What we SHOULD NOT ALLOW is execution of SQL statements that can be influenced by an attacker, such as through URL parameters.

Security model

The security model for SQL execution in Supabase Studio is based on the principle of "proven authorship". This means that a user should only be able to execute SQL statements that they have explicitly authored, and not statements that can be influenced by external input.

There are three classes of SQL fragments:

  1. Hardcoded within the application code. These are safe to execute because they cannot be influenced by an attacker. They can be marked with the safeSql utility with pg-meta:

    ts
    import { safeSql } from '@supabase/pg-meta'
    
    const sql = safeSql`
      SELECT *
      FROM users
      WHERE id = 1
    `

    safeSql automatically creates a string of the branded type SafeSqlFragment. (See Provenance Tracking below.)

  2. Third-party influenceable. These are SQL fragments that can be influenced by an attacker, such as through URL parameters or LLM output. These should be marked with the untrustedSql utility with pg-meta:

    ts
    import { untrustedSql } from '@supabase/pg-meta'
    
    const unsafeQuery = searchParams.get('query')
    const querySql = untrustedSql(unsafeQuery)

    untrustedSql creates a string of the branded type UntrustedSqlFragment. (See Provenance Tracking below.)

  3. User-authored. These are SQL fragments that are authored by the user themselves within the UI, for example in a text input field. Because the user is the author, these should be considered safe to execute.

    However, there is a caveat, where third-party and user-authored code can mix, contaminating the user-authored code (for example, if an input is prefilled from an unsanitized URL parameter). Provenance tracking helps us track these cases.

    For example, a safe input component could be implemented as follows by requiring that its placeholder and controlled value are of type SafeSqlFragment. In this case we can use its onChange to promote the user input to SafeSqlFragment type, because we know that the user is the author of the input. An implementation of this is in @apps/studio/components/ui/SafeSqlInput.tsx:

    ts
    import { rawSql, type SafeSqlFragment } from '@supabase/pg-meta'
    import type { ChangeEvent, ComponentProps } from 'react'
    import { Input } from 'ui-patterns/DataInputs/Input'
    
    type InputProps = ComponentProps<typeof Input>
    
    export type SafeSqlInputProps = Omit<
      InputProps, 'placeholder' | 'value' | 'onChange'
    > & {
      placeholder?: SafeSqlFragment
      value: SafeSqlFragment
      onChange?:
        (event: ChangeEvent<HTMLInputElement>, value: SafeSqlFragment) => void
    }
    
    export const SafeSqlInput = ({ onChange, ...props }: SafeSqlInputProps) => (
      <Input
        {...props}
        onChange={(event) => onChange?.(event, rawSql(event.target.value))}
      />
    )

    This is pretty much the ONLY VALID USE CASE of the rawSql export from pg-meta, and it should be used with caution.

Provenance tracking

Branded types are used to track the provenance of SQL fragments. The types, exported from pg-meta, are:

  • SafeSqlFragment: represents SQL fragments that are safe to execute, because they are either hardcoded in the application or authored by the user themselves.
  • UntrustedSqlFragment: represents SQL fragments that can be influenced by an attacker, such as through URL parameters or LLM output.

These are valid ways to generate a SafeSqlFragment:

  • Using the safeSql utility from pg-meta to create hardcoded SQL fragments.
  • Using the sanitization utilities from pg-meta to sanitize untrusted input and promote it to a SafeSqlFragment:
    • ident
    • literal
    • keyword
  • Using the safe SQL manipulation utilities:
    • joinSqlFragments (from pg-meta)
    • trimSafeSqlFragment (from apps/studio/lib/sql.ts)

UntrustedSqlFragments can be generated from raw strings using untrustedSql().

There is also a union type, DisplayableSqlFragment, which represents SQL fragments that can be safely displayed in the UI, but not necessarily executed. This includes both SafeSqlFragment and UntrustedSqlFragment.

Security of SQL round-tripped from the user's database

SQL derived directly from catalog tables (e.g., function definitions, RLS expressions, etc.) is considered safe, and it is promoted AT THE POINT OF BEING QUERIED from the database. In most cases, this is in an apps/studio/data/*/.ts file, in the utility function that makes the API or database fetch.

A critical exception to the safety of SQL round-tripped from the database is user snippets. These must NEVER BE CONSIDERED SAFE because they are both (a) externally influenceable and (b) auto-saved. The snippet type uses the unchecked_sql property, which is an UntrustedSqlFragment, to enforce this.

Promoting SQL fragments to SafeSqlFragment type

Given an insecure string or UntrustedSqlFragment, how do we promote it safely to a SafeSqlFragment?

Sanitization utilities

This is the preferred method when the input is sanitizable, e.g., it is a relation name, a column name, will be compared as a literal, etc.

The pg-meta library provides the following sanitization utilities that can be used to safely promote untrusted input to SafeSqlFragment:

  • ident: for sanitizing identifiers such as table names or column names.
  • literal: for sanitizing literal values that will be used in SQL statements.
  • keyword: for sanitizing SQL keywords.
Show full SKILL.md (547 more words)Show less
acceptUntrustedSql

Some untrusted SQL fragments cannot be sanitized with the above utilities. For example, the USING expression in the RLS policy editor is an arbitrary SQL expression.

In these cases, we can promote the SQL fragment upon explicit user action. User action indicates that the user has seen the SQL and is OK with running it. For example, an explicit user action could be clicking a "Run" button.

The promotion happens with the acceptUntrustedSql utility from pg-meta,
which takes an UntrustedSqlFragment and returns a SafeSqlFragment.

This utility MUST ONLY BE USED IN event handlers. It should NEVER be used in a useQuery, direct in the render body of a component, in a useEffect, or anywhere it could auto-run without explicit user action.

This is safe:

ts
import { acceptUntrustedSql } from '@supabase/pg-meta'

function SafeComponent() {
  const { mutate: execute } = useExecuteSqlMutation()

  const handleRun = () => {
    // ✅ GOOD: Safe because it is in an event handler which requires a user
    // click
    execute({ sql: acceptUntrustedSql(/* sql */) })
  }

  return (
    <button onClick={handleRun}>Run</button>
  )
}

This is unsafe:

ts
import { acceptUntrustedSql } from '@supabase/pg-meta'

function UnsafeComponent() {
  const { data } = useQuery({
    queryKey: ['execute-sql', sql],
    queryFn: () => {
      // 🛑 BAD: Unsafe because it is in a query which could auto-run without
      // explicit user action
      return execute({ sql: acceptUntrustedSql(/* sql */) })
    },
  })
}

Type guarantees

SQL run against the user's Postgres database runs through the executeSql function, which only takes arguments of type SafeSqlFragment for the SQL parameter. Raw strings or UntrustedSqlFragments will error at compile time.

Examples

Hard-coded SQL
ts
// ✅ GOOD: Automatically safe with `safeSql` utility
const selectStatement = safeSql`select 1`
SQL with sanitizable interpolations
ts
// ✅ GOOD: `pg-meta` utilities sanitize the input
const tableName = ident(userInputTableName)
const searchString = literal(userInputSearchString)
const sqlStatement = safeSql`
  SELECT *
  FROM ${tableName}
  WHERE search_column = ${searchString}
`
ts
// 🛑 BAD: Passing raw strings will type error
const tableName = 'my_table'
const sqlStatement = safeSql`
  SELECT *
  FROM ${tableName}
`
Non-sanitizable SQL from a user input
ts
// ✅ GOOD: SafeSqlInput only allows a value that is a SafeSqlFragment
import { SafeSqlInput } from '@apps/studio/components/ui/SafeSqlInput'

function MyComponent() {
  const [sql, setSql] = useState<SafeSqlFragment>(safeSql``)

  return (
    <SafeSqlInput
      placeholder={safeSql`Enter your SQL query here...`}
      value={sql}
      onChange={(event, value) => setSql(value)}
    />
  )
}
ts
// 🛑 BAD: This input mixes SafeSqlFragments and unsafe strings

function MyBadComponent() {
  const [sql, setSql] = useState<SafeSqlFragment>(safeSql``)

  return (
    <Input
    // 🛑 BAD: This is unsafe because the placeholder is a raw string
      placeholder="Enter your SQL query here..."
      value={sql}
      onChange={(event) => setSql(event.target.value)}
    />
  )
}
Round-tripping SQL from the database (NOT snippet content)
ts
// ✅ GOOD: SQL from the database is promoted to SafeSqlFragment at the point
// of fetching

// data/function-definitions.ts
function markFunctionDefinitionSafe(
  functionDefinition: FunctionDefinition
): SafeFunctionDefinition {
  return {
    ...functionDefinition,
    definition: functionDefinition.definition as SafeSqlFragment,
  }
}

// data/function-definitions.ts
function getFunctionDefinitions() {
  return GET(`/function-definitions`).then((functionDefinitions) =>
    functionDefinitions.map(markFunctionDefinitionSafe)
  )
}
ts
// 🛑 BAD: Strings are promoted to SafeSqlFragment in a utility function, where
// it is impossible to easily determine the safety of the input

// utils.ts
function markFunctionDefinitionSafe(
  functionDefinition: FunctionDefinition
): SafeFunctionDefinition {
  return {
    ...functionDefinition,
    definition: functionDefinition.definition as SafeSqlFragment,
  }
}

// Component.ts
function MyComponent() {
  const { data: functionDefinitions } = useFunctionDefinitions()
  const safeFunctionDefinitions = functionDefinitions.map(markFunctionDefinitionSafe)
}
Snippet content is ALWAYS UNSAFE

Snippets are auto-persisted to the database and can be created or modified through externally influenceable channels (e.g., prefilled from URL params). The unchecked_sql property is typed as UntrustedSqlFragment to enforce this — it must only be promoted to SafeSqlFragment via acceptUntrustedSql in an event handler that requires explicit user action.

ts
// 🛑 BAD: Snippet content is executed automatically via useQuery, with no
// explicit user action confirming that the user has reviewed the SQL.
import { acceptUntrustedSql } from '@supabase/pg-meta'

function UnsafeSnippetPreview({ snippet }: { snippet: Snippet }) {
  const { data } = useExecuteSqlQuery({
    sql: acceptUntrustedSql(snippet.content.unchecked_sql),
  })

  return <Results data={data} />
}
ts
// 🛑 BAD: Casting bypasses the type system entirely. The snippet's
// `unchecked_sql` is `UntrustedSqlFragment` for a reason — never cast it.
function UnsafeSnippetRunner({ snippet }: { snippet: Snippet }) {
  const { mutate: execute } = useExecuteSqlMutation()

  useEffect(() => {
    execute({ sql: snippet.content.unchecked_sql as SafeSqlFragment })
  }, [snippet])
}
ts
// ✅ GOOD: Snippet content is only promoted to SafeSqlFragment inside an event
// handler, after the user clicks Run. The user has seen the SQL in the editor
// and explicitly chosen to execute it.
import { acceptUntrustedSql } from '@supabase/pg-meta'

function SnippetRunner({ snippet }: { snippet: Snippet }) {
  const { mutate: execute } = useExecuteSqlMutation()

  const handleRun = () => {
    execute({ sql: acceptUntrustedSql(snippet.content.unchecked_sql) })
  }

  return (
    <>
      <SnippetEditor snippet={snippet} />
      <button onClick={handleRun}>Run</button>
    </>
  )
}

Analytics SQL (BigQuery / ClickHouse)

The same security model applies to analytics queries, which target BigQuery or ClickHouse via the /platform/projects/{ref}/analytics/endpoints/logs.all{,.otel} endpoints. Filter keys and values from URL parameters and UI inputs are spliced into SQL that runs against the project's logs, so the same injection risk exists.

Analytics SQL uses its own SafeLogSqlFragment brand (apps/studio/data/logs/safe-analytics-sql.ts), intentionally disjoint from the pg-meta SafeSqlFragment brand. The brands are kept separate because escape semantics differ — Postgres-safe E'…' strings, ::jsonb casts, and double-quoted identifiers are unsafe for BigQuery and/or ClickHouse, and vice versa. Crossing the brands would silently emit unsafe SQL.

The wire boundary is executeAnalyticsSql in apps/studio/data/logs/execute-analytics-sql.ts, analogous to pg-meta's executeSql; it accepts only SafeLogSqlFragment, and an eslint no-restricted-syntax rule in apps/studio/eslint.config.cjs blocks direct post()/get() calls to the logs.all endpoints from any other file.

Build fragments with the helpers in safe-analytics-sql.ts:

  • safeSql — template tag that only accepts SafeLogSqlFragment interpolations; plain strings and Postgres SafeSqlFragments are rejected at compile time.
  • analyticsLiteral(value) — sanitizes string/number/boolean literals.
  • quotedIdent(name) — validates and backtick-quotes dotted identifiers.
  • keyword(value, allowed) — resolves a value against an allow-list of fragments (e.g. AND/OR); never returns the raw input.
  • joinSqlFragments(fragments, separator) — composes already-branded fragments.
ts
import { executeAnalyticsSql } from '@/data/logs/execute-analytics-sql'
import { analyticsLiteral, quotedIdent, safeSql } from '@/data/logs/safe-analytics-sql'

// ✅ GOOD: every interpolation is sanitized.
const sql = safeSql`
  SELECT timestamp, event_message
  FROM ${quotedIdent(table)}
  WHERE id = ${analyticsLiteral(id)}
`

await executeAnalyticsSql({ projectRef, endpoint, sql, iso_timestamp_start, iso_timestamp_end })
ts
// 🛑 BAD: raw string interpolation. This fails to type-check at the
// executeAnalyticsSql boundary because the result is `string`, not
// `SafeLogSqlFragment`.
const sql = `SELECT * FROM ${table} WHERE id = '${id}'`
await executeAnalyticsSql({ projectRef, endpoint, sql, iso_timestamp_start, iso_timestamp_end })

The only path that runs SQL not built from these helpers is user-authored editor text: untrustedLogSql(text) marks it UntrustedLogSqlFragment (displayable and storable, never executable), and acceptUntrustedLogsSql promotes it to SafeLogSqlFragment. That promotion is a security boundary — call it only from a run gesture (Run button click, Cmd+Enter) or an approval-gated tool call (the AI notebook tools). Never from render, useEffect, or any automatic path. The notebook persist path also promotes cells because the writable notebook type requires the safe brand; that is storage typing, not execution approval, and is not precedent for promoting anywhere else. The same rule as acceptUntrustedSql on the Postgres side.

Endpoint selection, the OTEL query builders, and the rest of the Studio wiring live in the clickhouse-logs-queries skill (references/codebase-integration.md).

© supabase, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/safe-sql-execution of supabase/supabase.

Open the folder on GitHubat commit 26c838a

Compare with similar skills

Safe SQL Execution next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Safe SQL Execution compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Safe SQL Execution this skillsupabase/supabase111k—~4.2kAutomated safety check: PassApache-2.0
Stash Postgrescipherstash/stack157—~6.3kAutomated safety check: PassMIT
Database FundamentalsDanielPodolsky/ownyourcode2901 repos~1.6kAutomated safety check: PassMIT
Golang Databaseunxed/f42412 repos~2.9kAutomated safety check: PassMIT
Srtd CLIt1mmen/srtd105—~360Automated safety check: PassMIT
Drizzle Ormgrowupanand/ConvoForm1011 repos~2.7kAutomated safety check: PassApache-2.0

Similar skills

  • Stash Postgres

    cipherstash/stack

    Query EQL v3 encrypted columns from hand-written Postgres SQL over pg (node-postgres) or postgres (postgres-js) — no ORM.

    157 GitHub stars~6.3k tokensUpdated today
    DatabasesAuto-check passed
  • Database Fundamentals

    DanielPodolsky/ownyourcode

    Reviews schema design, SQL queries, ORM patterns. An agent skill from DanielPodolsky/ownyourcode.

    290 GitHub starsUsed in 1 repo~1.6k tokens
    DatabasesAuto-check passed
  • Comprehensive guide for Go database access — parameterized queries, struct scanning, NULLable columns, transactions, isolation levels, SELECT FOR UPDATE, connection pool, batch processing, context…

    241 GitHub starsUsed in 2 repos~2.9k tokens
    DatabasesAuto-check passed
  • Srtd CLI

    t1mmen/srtd

    This skill should be used when the user mentions "srtd", "sql templates", "migrations-templates", "live reload sql", "supabase functions", when working with files in supabase/migrations-templates/…

    105 GitHub stars~360 tokensUpdated 1 mo ago
    DatabasesAuto-check passed
  • Drizzle Orm

    growupanand/ConvoForm

    Type-safe SQL ORM for TypeScript with zero runtime overhead. An agent skill from growupanand/ConvoForm.

    101 GitHub starsUsed in 1 repo~2.7k tokens
    DatabasesAuto-check passed
  • Expert Database

    ReJeCtAll/ExpertTeam-Codex

    数据库优化专家入口。用于 Codex CLI 的 $expert-database 调用. An agent skill from ReJeCtAll/ExpertTeam-Codex.

    113 GitHub stars~692 tokensUpdated 3 mo ago
    DatabasesAuto-check passed

More from supabase/supabase

All 22 skills in this repo
  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    Auto-check passed
  • Clickhouse Logs Queries

    supabase/supabase

    Official

    Write, review, and migrate Supabase logs queries against the ClickHouse-backed logs table (the logs.all.otel analytics endpoint).

    111k GitHub stars~2.4k tokensUpdated today
    Auto-check passed
  • Review The Docs

    supabase/supabase

    Official

    Review Supabase docs changes locally in your supabase/supabase checkout — either an open PR (triage, classify, verify) or your own branch before opening a PR (local self-review).

    111k GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • Vitest

    supabase/supabase

    Official

    Vitest API and config reference (Jest-compatible) — mocking with vi., spies, fake timers, coverage configuration, fixtures, snapshots, and test filtering.

    111k GitHub starsUsed in 12 repos~1.1k tokens
    Auto-check passed
  • Studio E2E Tests

    supabase/supabase

    Official

    Write and run Playwright E2E tests for Supabase Studio (e2e/studio).

    111k GitHub stars~2.8k tokensUpdated today
    Auto-check passed
  • Studio Error Handling

    supabase/supabase

    Official

    Error display and troubleshooting pattern for Supabase Studio.

    111k GitHub stars~1.3k tokensUpdated today
    Auto-check passed

Categories

Questions about Safe SQL Execution

What does Safe SQL Execution do?

A skill your agent uses whenever code will build, return, fetch, or execute SQL that runs against a user's real Postgres database — even when the request reads like an ordinary feature or bug fix…. Safe SQL Execution is an agent skill from supabase/supabase, published by the product's own GitHub organization.

When should I use Safe SQL Execution?

Safe SQL Execution fits situations like: code will build; execute SQL that runs against a users real Postgres database — even when the request reads like an ordinary feature; bug fix and never says security; safeSqlFragment. This covers: writing.

How do I install Safe SQL Execution in Claude Code?

Run `npx skills add supabase/supabase --skill safe-sql-execution -a claude-code`. Or copy the skill folder (.agents/skills/safe-sql-execution in supabase/supabase) into .claude/skills/safe-sql-execution in your project. Claude Code loads it when a task matches its description.

How do I install Safe SQL Execution in Codex?

Run `npx skills add supabase/supabase --skill safe-sql-execution -a codex`. Or copy the skill folder (.agents/skills/safe-sql-execution in supabase/supabase) into .agents/skills/safe-sql-execution in your project. Codex loads it when a task matches its description.

Can I use Safe SQL Execution in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add supabase/supabase --skill safe-sql-execution -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/safe-sql-execution, .gemini/skills/safe-sql-execution, .github/skills/safe-sql-execution and .opencode/skills/safe-sql-execution in your project.

What does Safe SQL Execution need to run?

SKILL.md names no scripts, command-line tools or credentials: Safe SQL Execution is instructions for the agent only.

Does Safe SQL Execution access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Safe SQL Execution safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Safe SQL Execution use?

Safe SQL Execution is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Safe SQL Execution use?

About 4.2k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Safe SQL Execution?

Skills that share tags, products or a category with Safe SQL Execution: Stash Postgres (cipherstash/stack, 157 stars), Database Fundamentals (DanielPodolsky/ownyourcode, 290 stars), Golang Database (unxed/f4, 241 stars) and Srtd CLI (t1mmen/srtd, 105 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Safe SQL Execution?

supabase (a GitHub organization, an official publisher) maintains it in supabase/supabase, which has 111,222 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 8, 2026.

Source: supabase/supabase on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.