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

149 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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
""",
)