久久一级二级,日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕,中文字慕五区,欧美日韩精品一级,9干视频在线,一线在线不卡免费,亚洲天堂久久在线观看,亚洲天堂激情一区,丁香激情四月

?? MCP生態(tài)

MCP協(xié)議安全配置指南:防范Supabase式數(shù)據(jù)庫暴露的實戰(zhàn)要點

發(fā)布時間:2026-04-17 分類: MCP生態(tài)
摘要:MCP協(xié)議安全:避免Supabase式數(shù)據(jù)庫暴露的實戰(zhàn)要點Supabase事件復盤:不是“漏洞”,是配置與邊界失控Hacker News上那場關于Supabase MCP組件導致數(shù)據(jù)庫直連公網(wǎng)的討論,根源不在代碼里埋了后門,而在于兩處可避免的失控:默認配置放行了數(shù)據(jù)庫連接池:MCP服務啟動時未強制隔離數(shù)據(jù)庫訪問通道,DATABASE_URL 環(huán)境變量被直接注入到客戶端可觸達的連接上下文中;請...

封面

MCP協(xié)議安全:避免Supabase式數(shù)據(jù)庫暴露的實戰(zhàn)要點

Supabase事件復盤:不是“漏洞”,是配置與邊界失控

Hacker News上那場關于Supabase MCP組件導致數(shù)據(jù)庫直連公網(wǎng)的討論,根源不在代碼里埋了后門,而在于兩處可避免的失控:

  • 默認配置放行了數(shù)據(jù)庫連接池:MCP服務啟動時未強制隔離數(shù)據(jù)庫訪問通道,DATABASE_URL 環(huán)境變量被直接注入到客戶端可觸達的連接上下文中;
  • 請求解析層缺失數(shù)據(jù)范圍約束:MCP協(xié)議允許客戶端傳入原始SQL片段或表名參數(shù),但服務端未校驗這些輸入是否落在預設白名單內(nèi),也未綁定用戶身份與數(shù)據(jù)租戶(tenant)。

結(jié)果是:攻擊者用 curl -X POST https://your-app.supabase.co/mcp/query -d '{"table":"users","where":"1=1"}' 就能拉走全量用戶記錄。

這不是MCP協(xié)議本身的設計缺陷,而是實現(xiàn)時跳過了權限錨點和數(shù)據(jù)沙箱。

關鍵防御點:從協(xié)議層落地到代碼

1. 權限控制必須綁定租戶上下文

JWT認證只是起點。真正的權限控制發(fā)生在每次MCP請求進入時——必須將用戶身份、角色、租戶ID三者綁定,并在數(shù)據(jù)庫查詢前完成校驗。

不要只驗證token是否有效,要驗證token聲明中tenant_id是否匹配當前請求目標資源所屬租戶。

// ? 正確:在MCP handler中做租戶級攔截
app.post('/mcp/query', authenticateJWT, (req, res) => {
  const { table, where } = req.body;
  
  // 檢查該用戶是否有權訪問此表(基于租戶+角色策略)
  if (!isTableAccessible(req.user.tenant_id, req.user.role, table)) {
    return res.status(403).json({ error: 'Forbidden: table access denied' });
  }

  // 構(gòu)造查詢時強制注入租戶過濾條件
  const safeWhere = { ...where, tenant_id: req.user.tenant_id };
  db.query(table, safeWhere).then(data => res.json(data));
});

2. 數(shù)據(jù)邊界校驗不能依賴客戶端輸入

MCP協(xié)議不禁止客戶端傳表名或字段名,但服務端必須用白名單機制兜底:

  • 表名只允許出現(xiàn)在預定義列表中(如 ['posts', 'comments', 'profiles']);
  • 字段名需映射到實體屬性,禁止原始SQL拼接;
  • where 條件必須通過結(jié)構(gòu)化解析器(如 objection.jsQueryBuilderknex().where())生成,禁用字符串模板。
// ? 危險:拼接SQL
const query = `SELECT * FROM ${req.body.table} WHERE ${req.body.where}`;

// ? 安全:白名單 + 結(jié)構(gòu)化構(gòu)建
const allowedTables = new Set(['posts', 'comments']);
if (!allowedTables.has(req.body.table)) {
  throw new Error('Invalid table name');
}

// 使用Knex構(gòu)建帶租戶約束的查詢
const result = await knex(req.body.table)
  .where({ tenant_id: req.user.tenant_id })
  .andWhere(req.body.where || {});

3. 加密不是選項,是通信基線

MCP Server必須強制HTTPS,且所有Agent通信鏈路默認啟用TLS 1.3。別在開發(fā)環(huán)境留HTTP后門——.env里寫NODE_ENV=development不等于可以關掉證書校驗。

對敏感字段(如API key、token、PII),額外做應用層加密:

// 使用AES-GCM加密存儲敏感字段(非僅哈希)
const crypto = require('crypto');
const algorithm = 'aes-256-gcm';
const secretKey = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');

function encrypt(text) {
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  return `${iv.toString('hex')}:${encrypted}:${cipher.getAuthTag().toString('hex')}`;
}

實戰(zhàn):Yitb Server鑒權中間件與Agent設計原則

鑒權中間件要覆蓋MCP入口點

MCP請求常走獨立路由(如 /mcp/ 前綴),不能復用Web頁面的鑒權邏輯。中間件必須:

  • 解析 Authorization 頭中的Bearer token;
  • 校驗簽名、過期時間、租戶聲明;
  • user.tenant_id 注入 req,供后續(xù)handler使用。
// middleware/mcp-auth.js
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing or invalid Authorization header' });
  }

  const token = authHeader.split(' ')[1];
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    if (!payload.tenant_id) {
      throw new Error('Missing tenant_id in token');
    }
    req.user = payload;
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid or expired token' });
  }
};

在路由中顯式掛載:

const mcpAuth = require('./middleware/mcp-auth');

// ? 專用于MCP協(xié)議的入口
app.post('/mcp/query', mcpAuth, handleMCPQuery);
app.post('/mcp/insert', mcpAuth, handleMCPInsert);

Agent安全設計三條鐵律

  1. 永遠不持有長期數(shù)據(jù)庫憑證
    Agent運行時只獲取短期、作用域受限的訪問令牌(如PostgreSQL的pgbouncer動態(tài)用戶,或Supabase的service_role臨時token),用完即焚。
  2. 所有出站請求強制雙向TLS
    Agent調(diào)用外部API時,不僅驗證服務端證書,還要用自己的客戶端證書發(fā)起請求(mTLS),防止中間人偽造響應。
  3. 日志脫敏是硬性要求
    記錄MCP請求時,自動過濾password、api_keytoken等字段,且不記錄原始SQL——只記操作類型、表名、影響行數(shù)、耗時。
// 日志中間件示例
app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    const safeBody = { ...req.body };
    delete safeBody.password;
    delete safeBody.api_key;
    
    console.log({
      method: req.method,
      path: req.path,
      status: res.statusCode,
      duration,
      body: safeBody,
      timestamp: new Date().toISOString()
    });
  });
  next();
});
返回首頁
三河市| 南宁市| 西城区| 融水| 青神县| 侯马市| 个旧市| 盘山县| 攀枝花市| 南京市| 道孚县| 泰州市| 大竹县| 文化| 洪泽县| 武宣县| 伊宁县| 淄博市| 灌阳县| 乌苏市| 曲周县| 黄浦区| 乐平市| 潢川县| 嘉峪关市| 阿尔山市| 穆棱市| 浦东新区| 浦城县| 泸溪县| 金堂县| 聂荣县| 德钦县| 元阳县| 曲水县| 镇康县| 小金县| 广东省| 芜湖市| 朝阳市| 宁晋县|