惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
V
Visual Studio Blog
博客园_首页
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Martin Fowler
Martin Fowler
Recent Announcements
Recent Announcements
J
Java Code Geeks
月光博客
月光博客
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Fortinet All Blogs
P
Privacy & Cybersecurity Law Blog
C
CERT Recently Published Vulnerability Notes
C
CXSECURITY Database RSS Feed - CXSecurity.com
B
Blog RSS Feed
S
Schneier on Security
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
W
WeLiveSecurity
A
Arctic Wolf
U
Unit 42
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
有赞技术团队
有赞技术团队
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
Google DeepMind News
Google DeepMind News
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
量子位
B
Blog
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
博客园 - 三生石上(FineUI控件)
H
Help Net Security
博客园 - 叶小钗
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 热门话题
Hugging Face - Blog
Hugging Face - Blog
Google DeepMind News
Google DeepMind News
小众软件
小众软件
雷峰网
雷峰网
TaoSecurity Blog
TaoSecurity Blog
Schneier on Security
Schneier on Security

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management
Supabase Vault
Michel Pelletier · 2022-08-19 · via Supabase Blog

Supabase Vault

Today we're announcing Supabase Vault, a Postgres extension for managing secrets and encryption inside your database. Vault is a thin usability-layer on top of pgsodium.

❇️ UPDATE JUNE 2023 ❇️

Vault is now available on every Supabase project. Check it out

Transparent Column Encryption with Postgres is a blog post that describes the technology behind Vault - libsodium and pgsodium. Now, we will go through a quick example of storing a secret, like a service access token, into the Vault.

Until now, the industry-standard for PostgreSQL encryption is a built-in extension called pgcrypto. Like most cloud providers, Supabase offers pgcrypto for developers to use in their applications. pgcrypto has been around for a long time, and while it supports some basic encryption and decryption abilities, it lacks features like public key signing, key derivation APIs, streaming encryption, and other modern features required by security-first applications.

Problems with raw keys#

Databases often store sensitive information, and they need tools that guarantee this data is stored and backed-up in an encrypted form. A fundamental issue with pgcrypto is that it lacks the ability to derive keys from outside of SQL. Instead you must have the raw encryption key for the algorithm you wish to use:


_12

create extension pgcrypto;

_12

_12

create table users (

_12

id serial primary key,

_12

email varchar not null unique

_12

);

_12

_12

insert into users

_12

(email)

_12

values

_12

(pgp_sym_encrypt('alice@supabase.io', 's3kr3t_k3y')),

_12

(pgp_sym_encrypt('bob@supabase.io', 's3kr3t_key'));


pgcrypto works with raw keys. In order to encrypt the data with pgcrypto you must pass the key directly to the encryption function. Leaking those raw keys is all too easy - logs, files, clients, tables, replication streams - you name it. Wouldn't it be great if you could encrypt data, but instead of specifying the raw key you reference it indirectly, like with a key ID?

Supabase Vault allows you to store secrets without leaking any sensitive information.

The Vault is a good place to put things like API keys, access tokens, and other secrets from external services that you need to access within your database. The core of the Supabase Vault is a table with some metadata and an encrypted text column where you can put your secrets and any metadata related to them.

We take the pain out of key management by pre-generating a unique, per-database key that is used by default - a “root” key - which is stored outside of the SQL language, accessibly only internally in the Postgres server by the libsodium library. This root key is managed by the pgsodium Postgres extension when the server boots using Server Key Management.

pgsodium provides an Encryption and Key Derivation API based on the libsodium library and can get it's root key from a variety of sources depending on how you configure it. Supabase generates and preserves your project's root key behind the scenes, so you don't have to worry about it. If you install pgsodium locally the default is to generate a random root key from the /dev/urandom device which is then saved in a file in your Postgres data directory.

Installing the vault extension is the same as any other Postgres extension:


_10

create extension supabase_vault with schema vault;


Once enabled, you can insert secrets into the vault.secrets table:


_10

insert into vault.secrets

_10

(secret, associated)

_10

values

_10

('s3kr3t_k3y', 'This is the secret API service key.');


Now when you look in the vault.secrets table, the secret is encrypted:


_10

select * from vault.secrets;



_10

-[ RECORD 1 ]--------------------------------------------------------

_10

id | f6a2fe0a-3471-4eea-a581-75c4d2be396b

_10

secret | /eT9bb96POTJ7L2gYrluTZ3r3pG5IMwPSQo6pQP0xdZTarpRrpWPXTWQ

_10

key_id | caabfc28-2ab3-48f5-8978-1b3d4b659911

_10

associated | This is the secret API service key.

_10

nonce | \x77c7381c523630ba72f1f137626a9f9a

_10

created_at | 2022-08-18 19:33:15.312651+00


Notice how the row has a key_id column. This is the ID of the internally derived key that is used to encrypt the secret, not the key itself. The actual raw key is not available to you in SQL, it is managed entirely outside of the SQL language in the Postgres server.

At Supabase, we manage this key for your project automatically and generate a unique default Key ID for you in the secrets table. For self-hosting, pgsodium supports a variety of ways to place the root key into Postgres.

To see the decrypted data, there is a special view created called vault.decrypted_secrets:


_10

select * from vault.decrypted_secrets;



_10

-[ RECORD 1 ]----+---------------------------------------------------------

_10

id | f6a2fe0a-3471-4eea-a581-75c4d2be396b

_10

secret | /eT9bb96POTJ7L2gYrluTZ3r3pG5IMwPSQo6pQP0xdZTarpRrpWPXTWQ

_10

decrypted_secret | s3kr3t_k3y

_10

key_id | caabfc28-2ab3-48f5-8978-1b3d4b659911

_10

associated | This is the secret API service key.

_10

nonce | \x77c7381c523630ba72f1f137626a9f9a

_10

created_at | 2022-08-18 19:33:15.312651+00


Now you can see a new decrypted_secret column that contains the decrypted secret we originally inserted into the table. This vault.decrypted_secrets view automatically decrypts rows in the vault.secrets table “on-the-fly” as you query them, but the secret is stored on disk in encrypted form. If you take a backup, or pause your project, that data remains encrypted. We will keep your hidden root key safe in our backend systems for when you need to restore or un-pause your projects.

If you wish to use your own Key ID for different secrets, instead of the default Key ID we've generated, you can create one using the pgsodium.create_key() function:


_10

select * from pgsodium.create_key('This is a comment for the new key');



_10

-[ RECORD 1 ]-------------------------------------

_10

id | f9f176eb-7069-4743-9403-582c04354ffc

_10

status | valid

_10

created | 2022-08-18 22:31:50.331792

_10

expires |

_10

key_type | aead-det

_10

key_id | 2

_10

key_context | \x7067736f6469756d

_10

comment | This is the comment for the new key

_10

user_data |


Now you can encrypt table secrets with this new key by inserting its ID explicitly:


_10

insert into vault.secrets

_10

(secret, associated, key_id)

_10

values

_10

(

_10

'apikey_XaYrurzcquqhEdBjzfTzfwAZqpd',

_10

'This is some different associated data.',

_10

'f9f176eb-7069-4743-9403-582c04354ffc'

_10

)

_10

returning *;



_10

-[ RECORD 1 ]------------------------------------------------------------

_10

id | 9c58a0f3-aa40-4789-b683-6db48b241f9e

_10

secret | YWxuTnWdF55MuRrZ7xneBvaz2uH59U1dJV/7CCZjSn5B5jELOoy/csq8x/s=

_10

key_id | f9f176eb-7069-4743-9403-582c04354ffc

_10

associated | This is some different associated data.

_10

nonce | \xd39808b07c9ae52c8f02c33a7f87595c

_10

created_at | 2022-08-18 22:34:07.219941+00


The type of encryption used by the Vault is called Authenticated Encryption with Associated Data. The data you insert into the associated column, which is up to you, is combined with the encrypted text when libsodium creates the authentication signature for the secret. This means that when you read the secret, you know that the associated data is also authentic. The associated data could be an account ID or some information that ties your system to the secret. And as always, you can refer to rows in the secrets table by their primary key UUID.

If you only want to store secrets that you know are encrypted on disk and in backups, then all you need to know is shown above. Just insert secrets into the table, optionally creating new keys, and select them from the view when you want to use them.

The Vault is good for a reasonable amount of secure data, like API keys, access tokens, or environment variables. But if you have a lot more sensitive information, like personally Identifiable Information (PII), you may want to break them out into side-tables using pgsodium's Transparent Column Encryption which we will describe soon in a follow-up blog post. Stay tuned!