CodeReview/backend/app/services/agent/knowledge/frameworks/supabase.py

149 lines
3.5 KiB
Python
Raw Permalink Normal View History

"""
Supabase 安全知识
"""
from ..base import KnowledgeDocument, KnowledgeCategory
SUPABASE_SECURITY = KnowledgeDocument(
id="framework_supabase",
title="Supabase Security",
category=KnowledgeCategory.FRAMEWORK,
tags=["supabase", "postgresql", "rls", "auth", "baas"],
content="""
Supabase 是一个开源的Firebase替代品安全性主要依赖于Row Level Security (RLS)
## 核心安全机制
1. Row Level Security (RLS)
2. JWT认证
3. PostgreSQL权限系统
## 常见漏洞模式
### RLS未启用
```sql
-- 危险 - 表没有启用RLS
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
user_id UUID,
content TEXT
);
-- 任何人都可以访问所有数据
-- 安全 - 启用RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can only see their own posts"
ON posts FOR SELECT
USING (auth.uid() = user_id);
```
### RLS策略不完整
```sql
-- 危险 - 只有SELECT策略
CREATE POLICY "select_policy" ON posts FOR SELECT
USING (auth.uid() = user_id);
-- INSERT/UPDATE/DELETE没有策略可能被绕过
-- 安全 - 完整的CRUD策略
CREATE POLICY "insert_policy" ON posts FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "update_policy" ON posts FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "delete_policy" ON posts FOR DELETE
USING (auth.uid() = user_id);
```
### 服务端密钥泄露
```javascript
// 危险 - 在前端使用service_role密钥
const supabase = createClient(url, 'service_role_key');
// service_role绕过RLS
// 安全 - 前端只使用anon key
const supabase = createClient(url, 'anon_key');
```
### 不安全的函数
```sql
-- 危险 - SECURITY DEFINER函数
CREATE FUNCTION get_all_users()
RETURNS SETOF users
LANGUAGE sql
SECURITY DEFINER -- 以函数所有者权限执行
AS $$
SELECT * FROM users;
$$;
-- 安全 - 使用SECURITY INVOKER或添加检查
CREATE FUNCTION get_user_data(target_user_id UUID)
RETURNS SETOF users
LANGUAGE sql
SECURITY INVOKER
AS $$
SELECT * FROM users WHERE id = target_user_id;
$$;
```
### 存储桶权限
```sql
-- 危险 - 公开存储桶
INSERT INTO storage.buckets (id, name, public)
VALUES ('uploads', 'uploads', true);
-- 任何人都可以访问所有文件
-- 安全 - 私有存储桶 + RLS
INSERT INTO storage.buckets (id, name, public)
VALUES ('uploads', 'uploads', false);
CREATE POLICY "Users can access own files"
ON storage.objects FOR SELECT
USING (auth.uid()::text = (storage.foldername(name))[1]);
```
### JWT验证绕过
```javascript
// 危险 - 不验证JWT
const { data } = await supabase
.from('posts')
.select('*')
.eq('user_id', userIdFromRequest); // 用户可以伪造
// 安全 - 使用auth.uid()
// RLS策略中使用auth.uid()自动从JWT获取用户ID
```
### Edge Functions安全
```typescript
// 危险 - 不验证请求来源
Deno.serve(async (req) => {
const { userId } = await req.json();
// 直接使用用户提供的userId
});
// 安全 - 从JWT获取用户
import { createClient } from '@supabase/supabase-js';
Deno.serve(async (req) => {
const authHeader = req.headers.get('Authorization');
const supabase = createClient(url, anonKey, {
global: { headers: { Authorization: authHeader } }
});
const { data: { user } } = await supabase.auth.getUser();
// 使用验证过的user.id
});
```
## 安全检查清单
1. 所有表都启用了RLS
2. 每个表都有完整的CRUD策略
3. 前端只使用anon key
4. service_role key只在服务端使用
5. 存储桶有适当的访问策略
6. 函数使用SECURITY INVOKER
7. Edge Functions验证JWT
""",
)