FastAPI-MCP安全测试:发现和修复MCP工具安全问题的方法
概述:为什么MCP工具安全至关重要
在现代AI应用开发中,Model Context Protocol(MCP,模型上下文协议)已成为连接AI模型与外部工具的重要桥梁。FastAPI-MCP作为零配置的FastAPI端点自动暴露工具,让开发者能够轻松将现有API转换为MCP工具。然而,这种便利性也带来了新的安全挑战。
核心安全风险:当你的FastAPI端点自动转换为MCP工具时,原本面向人类用户的API现在直接暴露给AI模型使用,这可能导致:
- 权限绕过问题
- 敏感数据暴露
- 认证机制失效
- 注入攻击风险
本文将深入探讨FastAPI-MCP的安全测试方法,帮助你构建安全的MCP工具生态系统。
安全测试框架:构建全面的防护体系
1. 认证与授权测试
测试用例示例:
# 测试认证依赖是否正确配置
def test_auth_dependency_integration():
"""验证MCP工具是否正确集成认证依赖"""
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer
# 模拟认证依赖
token_auth = HTTPBearer()
async def verify_token(token = Depends(token_auth)):
if token.credentials != "valid-token":
raise HTTPException(status_code=401, detail="Invalid token")
return {"user_id": "test-user"}
# 创建MCP实例并测试
mcp = FastApiMCP(
app,
auth_config=AuthConfig(dependencies=[Depends(verify_token)])
)
# 测试未认证请求
with pytest.raises(Exception) as exc_info:
await mcp._execute_api_tool(
client=mock_client,
tool_name="protected_tool",
arguments={},
operation_map=operation_map
)
assert "401" in str(exc_info.value)
2. 输入验证测试
常见输入验证问题:
| 问题类型 | 风险等级 | 测试方法 |
|---|---|---|
| SQL注入 | 高危 | 特殊字符测试 |
| XSS攻击 | 中危 | HTML/JS payload测试 |
| 路径遍历 | 高危 | ../ 序列测试 |
| 命令注入 | 高危 | 系统命令测试 |
# 输入验证测试套件
@pytest.mark.parametrize("malicious_input", [
"' OR 1=1 --",
"<script>alert('xss')</script>",
"../../etc/passwd",
"; rm -rf /"
])
def test_malicious_input_handling(malicious_input):
"""测试MCP工具对恶意输入的防护能力"""
result = await mcp._execute_api_tool(
client=mock_client,
tool_name="user_input_tool",
arguments={"input": malicious_input},
operation_map=operation_map
)
# 验证输入被正确过滤或拒绝
assert not any([
"syntax error" in str(result).lower(),
"permission denied" in str(result).lower(),
"unexpected token" in str(result).lower()
])
3. 头信息转发安全测试
FastAPI-MCP支持头信息转发功能,但这可能带来安全风险:
头信息转发测试:
def test_header_forwarding_security():
"""测试头信息转发的安全性"""
# 测试敏感头信息是否被过滤
sensitive_headers = {
"cookie": "session=malicious",
"authorization": "Bearer valid-token", # 这个应该被转发
"x-custom-token": "sensitive-data",
"user-agent": "malicious-bot"
}
# 只有authorization头应该被转发
expected_forwarded_headers = {"authorization": "Bearer valid-token"}
# 模拟MCP请求上下文
http_request_info = HTTPRequestInfo(
method="POST",
path="/api/test",
headers=sensitive_headers,
cookies={},
query_params={},
body=None
)
# 执行工具调用
result = await mcp._execute_api_tool(
client=mock_client,
tool_name="test_tool",
arguments={},
operation_map=operation_map,
http_request_info=http_request_info
)
# 验证只有允许的头信息被转发
assert mock_client.last_request.headers == expected_forwarded_headers
问题发现与修复实战
1. 认证绕过问题
问题描述:当MCP工具的认证依赖配置不当时,攻击者可能绕过认证直接访问受保护的工具。
修复方案:
# 错误的配置:缺少认证依赖
mcp = FastApiMCP(app) # 无auth_config
# 正确的配置:明确设置认证依赖
from fastapi import Depends
from fastapi.security import HTTPBearer
token_auth = HTTPBearer()
mcp = FastApiMCP(
app,
auth_config=AuthConfig(
dependencies=[Depends(token_auth)],
# 明确设置需要认证
setup_proxies=True
)
)
2. 敏感信息暴露
问题场景:MCP工具可能返回过多的错误信息,暴露系统内部细节。
安全配置:
# 生产环境的安全配置
import logging
# 禁用详细错误信息
logging.getLogger("fastapi_mcp").setLevel(logging.WARNING)
# 配置MCP服务器不返回详细错误
mcp = FastApiMCP(
app,
auth_config=AuthConfig(
dependencies=[Depends(token_auth)],
# 其他安全配置
)
)
# 自定义错误处理
@app.exception_handler(Exception)
async def generic_exception_handler(request, exc):
return JSONResponse(
status_code=500,
content={"message": "Internal server error"}
)
3. OAuth配置安全
安全最佳实践:
# 安全的OAuth配置示例
mcp = FastApiMCP(
app,
auth_config=AuthConfig(
version="2025-03-26",
issuer="https://your-domain.auth0.com/",
client_id=os.getenv("OAUTH_CLIENT_ID"),
client_secret=os.getenv("OAUTH_CLIENT_SECRET"),
audience=os.getenv("OAUTH_AUDIENCE"),
dependencies=[Depends(verify_auth)],
setup_proxies=True,
setup_fake_dynamic_registration=True,
metadata_path="/.well-known/oauth-authorization-server"
)
)
自动化安全测试方案
1. 集成安全测试到CI/CD
# .github/workflows/security-test.yml
name: Security Testing
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
security-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install bandit safety pytest
- name: Run security scanner (Bandit)
run: bandit -r fastapi_mcp/ -ll
- name: Check for vulnerable dependencies
run: safety check
- name: Run security tests
run: pytest tests/test_security.py -v
2. 安全测试用例模板
# tests/test_security.py
import pytest
from fastapi_mcp import FastApiMCP, AuthConfig
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer
class TestSecurity:
"""MCP工具安全测试套件"""
@pytest.fixture
def secured_mcp(self, app):
"""创建配置了认证的MCP实例"""
token_auth = HTTPBearer()
async def verify_token(token = Depends(token_auth)):
if token.credentials != "test-valid-token":
raise HTTPException(status_code=401)
return {"user": "test"}
return FastApiMCP(
app,
auth_config=AuthConfig(dependencies=[Depends(verify_token)])
)
def test_unauthenticated_access(self, secured_mcp):
"""测试未认证访问被拒绝"""
# 模拟未认证请求
with pytest.raises(Exception) as exc_info:
secured_mcp._execute_api_tool(
client=mock_client,
tool_name="protected_tool",
arguments={},
operation_map={}
)
assert "401" in str(exc_info.value)
def test_authenticated_access(self, secured_mcp):
"""测试认证访问成功"""
# 模拟认证请求上下文
http_request_info = HTTPRequestInfo(
method="GET",
path="/api/protected",
headers={"authorization": "Bearer test-valid-token"},
cookies={},
query_params={},
body=None
)
result = secured_mcp._execute_api_tool(
client=mock_client,
tool_name="protected_tool",
arguments={},
operation_map={},
http_request_info=http_request_info
)
assert result is not None
安全监控与响应
1. 实时安全监控
# security_monitor.py
import logging
from datetime import datetime
from typing import Dict, Any
class SecurityMonitor:
"""MCP安全监控器"""
def __init__(self):
self.suspicious_activities = []
self.rate_limits = {}
def log_suspicious_activity(self, tool_name: str, details: Dict[str, Any]):
"""记录可疑活动"""
event = {
"timestamp": datetime.now().isoformat(),
"tool": tool_name,
"details": details,
"severity": "medium"
}
self.suspicious_activities.append(event)
# 实施速率限制
if tool_name not in self.rate_limits:
self.rate_limits[tool_name] = []
self.rate_limits[tool_name].append(datetime.now())
# 清理旧记录
self._cleanup_old_records()
logging.warning(f"Suspicious activity detected: {event}")
def _cleanup_old_records(self):
"""清理过期的速率限制记录"""
cutoff = datetime.now() - timedelta(minutes=5)
for tool in list(self.rate_limits.keys()):
self.rate_limits[tool] = [
ts for ts in self.rate_limits[tool] if ts > cutoff
]
2. 应急响应计划
安全事件响应流程:
- 检测:通过监控系统发现异常活动
- 分析:确定问题性质和影响范围
- 遏制:临时禁用受影响工具或功能
- 修复:部署安全补丁
- 恢复:重新启用服务并验证修复
- 总结:编写事件报告并改进防护措施
总结与最佳实践
通过系统的安全测试和防护措施,你可以确保FastAPI-MCP工具的安全性。关键要点包括:
- 始终配置认证依赖:不要依赖默认配置
- 实施输入验证:对所有用户输入进行严格验证
- 监控和日志记录:实时监控可疑活动
- 定期安全审计:定期检查配置和代码安全性
- 保持更新:及时更新FastAPI-MCP和相关依赖
通过遵循这些安全实践,你可以构建既强大又安全的MCP工具生态系统,为AI应用提供可靠的外部工具支持。
安全不是一次性的任务,而是一个持续的过程。定期回顾和更新你的安全策略,确保你的FastAPI-MCP部署始终处于最佳的安全状态。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



