vladlen-codes/llm-security-toolkit

GitHub: vladlen-codes/llm-security-toolkit

一个Python中间件库,在应用与LLM提供商之间拦截每次调用,提供提示词注入检测、输出安全扫描和工具调用验证。

Stars: 2 | Forks: 1

# LLM 安全工具包 ### 架构与详细技术规范 ## 目录 1. [这是什么项目?](#1-what-is-this-project) 2. [高层架构](#2-high-level-architecture) 3. [仓库结构](#3-repository-structure) 4. [核心类型与模型](#4-core-types--models) 5. [策略引擎](#5-policy-engine) 6. [防护层](#6-the-guards-layer) 7. [提供商层](#7-providers-layer) 8. [中间件层](#8-middleware-layer) 9. [日志与异常](#9-logging--exceptions) 10. [公共 API 接口](#10-public-api-surface) 11. [测试、示例与文档](#11-tests-examples--docs) 12. [扩展性与设计原则](#12-extensibility--design-principles) 13. [未来路线图](#13-future-roadmap) ## 1. 这是什么项目? **LLM Security Toolkit** 是一个 Python 中间件库,位于您的应用程序代码和任何 LLM 提供商之间 —— 拦截每一次模型调用,以在 AI 响应之前和之后强制执行安全检查。 可以将其视为专为 AI 调用设计的安全防火墙: - 在每个提示词(prompt)到达模型之前,扫描其中的**注入和越狱模式** - 验证每个响应是否存在**不安全内容、凭证泄露或危险命令** - 对模型尝试进行的每次工具/函数调用强制执行**schema 规则** - 应用**可配置策略**来决定是拦截、警告还是记录 该库暴露了一个干净、可导入的 API —— 在任何现有的 Python AI 应用中只需增加几行代码。无需更改基础设施。 | 属性 | 值 | |---|---| | 类型 | Python 库(可导入包,可通过 pip 安装) | | 目的 | 应用代码与 LLM 提供商之间的安全中间件 | | 主要接口 | 装饰器 / 上下文管理器 / 提供商封装器 | | 防护 | 提示词注入、不安全输出、危险工具调用 | | 策略引擎 | YAML 或 Python dict —— 每个端点的策略 | | 提供商支持 | OpenAI (v1),通用可调用对象,可扩展至 Claude, Gemini | | 框架支持 | FastAPI(原生),Flask(计划中) | | 返回类型 | `GuardDecision { allowed, score, reasons, safe_output }` | ## 2. 高层架构 ### 2.1 系统概览 该工具包组织为**五个不同的层**,每一层都有明确界定的职责: ``` ┌─────────────────────────────────────────────────────────────┐ │ Your Application │ └────────────────────────────┬────────────────────────────────┘ │ ┌────────────────────────────▼────────────────────────────────┐ │ Middleware Layer (FastAPI / Flask) │ │ Dependency injection or global middleware │ └────────────────────────────┬────────────────────────────────┘ │ ┌────────────────────────────▼────────────────────────────────┐ │ Providers Layer │ │ OpenAIProvider / GenericProvider (adapters) │ └──────┬─────────────────────┴──────────────────┬────────────┘ │ │ ┌──────▼──────┐ ┌───────▼──────┐ │ Guards │ │ Guards │ │ (Input) │ │ (Output) │ │ prompts.py │ │ outputs.py │ │ tools.py │ │ tools.py │ └──────┬──────┘ └───────┬──────┘ │ │ ┌──────▼─────────────────────────────────────────▼────────────┐ │ Policy Engine │ │ Policy | config.py | policies.py │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.2 请求 / 响应流 每次受保护的 LLM 调用都遵循一个**六阶段流水线**: | # | 阶段 | 发生了什么 | |---|---|---| | 1 | 应用调用受保护的提供商 | `guarded_openai_chat(prompt, tools, policy)` | | 2 | 输入扫描器运行 | 对 prompt + system instructions 执行 `scan_prompt()` | | 3 | 风险决策 | 基于策略阈值执行 Block / Warn / Allow | | 4 | 转发给 LLM | 对 OpenAI / 本地模型的真实 API 调用 | | 5 | 输出扫描器运行 | `scan_output()` + `validate_tool_call()` | | 6 | 返回 GuardDecision | `{ allowed, score, reasons, safe_output }` | ## 3. 仓库结构 该项目遵循 **src-layout** 约定以避免导入冲突,并反映了其五个内部层之间的关注点分离: ``` llm-security-toolkit/ ├── README.md # Project overview and quick-start ├── CONTRIBUTING.md # Fork & contribution guide ├── CODE_OF_CONDUCT.md # Community standards ├── LICENSE # MIT (encourages forks) ├── pyproject.toml # Build config, deps, tool settings ├── .pre-commit-config.yaml # ruff, black, mypy on every commit ├── .github/ │ └── workflows/ci.yml # Tests + lint on push / PR │ ├── src/llm_security/ # Main package (src layout) │ ├── __init__.py # Public re-exports │ ├── types.py # ScanResult, GuardDecision, ToolCall │ ├── policies.py # Policy models + built-in presets │ ├── config.py # YAML / dict → Policy loaders │ ├── exceptions.py # BlockedByPolicyError, etc. │ ├── logging.py # log_decision() + hooks │ ├── guards/ │ │ ├── prompts.py # Input / injection guards │ │ ├── outputs.py # Output / content guards │ │ └── tools.py # Tool-call validation guards │ ├── providers/ │ │ ├── base.py # ProviderAdapter ABC │ │ ├── openai.py # OpenAI concrete adapter │ │ └── generic.py # Generic callable adapter │ └── middleware/ │ ├── fastapi.py # FastAPI dependency + middleware │ └── flask.py # Flask (planned) │ ├── tests/ # Pytest test suite ├── examples/ # Runnable minimal examples └── docs/ # MkDocs documentation ``` ## 4. 核心类型与模型 库的每一部分都使用相同的三种数据结构。这些是整个包的*通用语言*。 ### ScanResult 单个防护检查的输出。每个防护函数都会返回其中一个: ``` @dataclass class ScanResult: allowed: bool # True = safe to proceed score: float # 0.0 (safe) → 1.0 (critical risk) reasons: List[str] # Human-readable explanations safe_output: Optional[str] # Redacted text (output guards only) ``` ### GuardDecision 返回给您应用程序的顶层结果 —— 聚合了所有活动防护的所有 `ScanResult`: ``` @dataclass class GuardDecision: allowed: bool score: float reasons: List[str] safe_output: Optional[str] scan_results: List[ScanResult] # Full audit trail ``` ### ToolCall 表示模型请求的结构化工具/函数调用: ``` @dataclass class ToolCall: name: str # e.g. 'read_file' args: Dict # e.g. { 'path': '/etc/passwd' } schema: Dict # JSON Schema the args must conform to ``` ## 5. 策略引擎 `Policy` 是控制整个安全管道的唯一配置对象。每个 guard、每个 provider、每个 middleware 都从中读取配置。 ### 5.1 Policy 结构 ``` class Policy(BaseModel): # Guard toggles prompt_guard_enabled: bool = True output_guard_enabled: bool = True tool_guard_enabled: bool = True # Thresholds (0.0 – 1.0) block_threshold: float = 0.75 # Score above this → block warn_threshold: float = 0.40 # Score above this → log warning # Allowed tool names (None = allow all) allowed_tools: Optional[List[str]] = None # On block: raise exception OR return GuardDecision raise_on_block: bool = True ``` ### 5.2 内置策略预设 | Policy | 行为 | 最适用于 | |---|---|---| | `StrictPolicy` | 阻断任何风险信号 | 生产环境,敏感应用 | | `BalancedPolicy` | 阻断高风险,警告中风险 | 标准应用(默认) | | `LoggingOnlyPolicy` | 从不阻断 —— 仅记录日志 | 开发 / 测试 | ### 5.3 加载 Policies ``` # 从 YAML 文件 (推荐生产环境使用) policy = load_policy_from_yaml('policies/production.yaml') # 从 dict (适用于测试) policy = load_policy_from_dict({ 'block_threshold': 0.8, 'allowed_tools': ['read_file', 'search_web'], }) ``` ## 6. 防护层 Guards 是工具包的**安全大脑**。每个 guard 模块都小巧、专注且可独立测试 —— 旨在易于 fork 和扩展新的检测规则。 | Guard Module | 检测模式 | 类别 | 默认动作 | |---|---|---|---| | Prompt Guard | `"ignore previous instructions"` | 注入 | 阻断或警告 | | Prompt Guard | `"pretend you are the system"` | 越狱 | 阻断或警告 | | Prompt Guard | 请求揭示隐藏上下文 | 数据窃取 | 阻断 | | Output Guard | API 密钥、token、密码 | 机密泄露 | 脱敏 + 警告 | | Output Guard | Shell 命令(`rm -rf`, `curl` 等) | OS 命令 | 阻断 | | Output Guard | 自残或恶意软件说明 | 内容 | 阻断 | | Tool Guard | 无效的工具名称 | Schema | 阻断 | | Tool Guard | `rm -rf /` 或管理员 API 调用 | 危险操作 | 阻断 | | Tool Guard | 参数与 schema 不匹配 | 验证 | 阻断 | ### 6.1 Prompt Guard — `guards/prompts.py` 在任何 API 调用**之前**运行。扫描用户提示词和系统指令,寻找表明试图颠覆模型行为的模式。 ``` def scan_prompt(prompt: str, policy: Policy) -> ScanResult: """ Heuristic patterns checked: - 'ignore previous instructions' / 'disregard above' - 'you are now the system prompt' - 'repeat everything above' (context exfiltration) - 'DAN' jailbreak variants - Base64 encoded instructions Returns ScanResult with score + reasons. """ ``` ### 6.2 Output Guard — `guards/outputs.py` 在响应的每个 token 到达您的应用程序之前运行。可以选择**脱敏**敏感内容,而不是直接阻断。 ``` def scan_output(text: str, policy: Policy) -> ScanResult: """ Patterns checked: - Credential regexes (API keys, JWTs, SSH private keys) - Shell command patterns (rm, curl, wget, sudo) - Malware / ransomware indicators - Self-harm or violence instructions safe_output field will contain redacted version if score < block_threshold. """ ``` ### 6.3 Tool Call Guard — `guards/tools.py` 拦截模型想要进行的每次函数/工具调用,并根据策略的白名单和工具的 JSON schema 对其进行验证。 ``` def validate_tool_call(call: ToolCall, policy: Policy) -> ScanResult: """ Checks applied: - Tool name in policy.allowed_tools (if allowlist defined) - Args validate against call.schema (jsonschema) - Blocked operation patterns (file deletion, network scanning) - Internal admin API URL detection """ ``` ## 7. 提供商层 Providers 封装了真实的 LLM 客户端。它们编排完整的防护管道 —— 输入扫描 → 转发 → 输出扫描 —— 并向调用者返回一个 `GuardDecision`。 | 文件 | 职责 | |---|---| | `providers/base.py` | 抽象基类 `ProviderAdapter`。定义所有 providers 必须实现的 `chat()` 接口。 | | `providers/openai.py` | 封装 OpenAI Python SDK 的具体适配器。在每次 `chat()` 调用周围自动运行所有 guards。 | | `providers/generic.py` | 接受任何可调用对象作为 LLM。用户传递自己的客户端函数;适配器处理其周围的完整防护流程。 | ### 7.1 ProviderAdapter 接口 ``` class ProviderAdapter(ABC): @abstractmethod def chat( self, *, messages: List[Dict], tools: Optional[List[Dict]] = None, policy: Optional[Policy] = None, ) -> GuardDecision: ... ``` ### 7.2 OpenAI 适配器流程 1. 对所有 user + system 消息执行 `scan_prompt()` 2. 如果允许 → 调用 `openai.chat.completions.create(...)` 3. 对响应内容执行 `scan_output()` 4. 对模型请求的任何 `tool_calls` 执行 `validate_tool_call()` 5. 返回聚合所有结果的 `GuardDecision` ## 8. 中间件层 中间件层使得保护整个 HTTP 端点变得非常简单,几乎无需更改代码。 ### 8.1 FastAPI 集成 ``` # 依赖注入 — 保护所有对 /chat 的调用 def get_guarded_openai(policy: Policy = BalancedPolicy()): return OpenAIProvider(policy=policy) @app.post('/chat') async def chat( req: ChatRequest, provider: OpenAIProvider = Depends(get_guarded_openai), ): decision = provider.chat(messages=req.messages) if not decision.allowed: raise HTTPException(400, detail=decision.reasons) return { 'reply': decision.safe_output } ``` ### 8.2 Middleware vs Dependency | 方式 | 最适用于 | |---|---| | Dependency (`Depends`) | 每个路由的策略。每个端点注入不同的 provider。最灵活。 | | Middleware class | 应用于每个请求的全局策略。适用于组织范围的默认设置。 | | Flask middleware | 计划在 v1.1 中推出。适配 Flask `before/after_request` 钩子的相同模式。 | ## 9. 日志与异常 ### 9.1 结构化日志 — `logging.py` 每个 `GuardDecision` 都可以传递给 `log_decision()`,该函数发出与任何日志后端兼容的结构化 JSON 日志条目: ``` def log_decision(decision: GuardDecision, logger: logging.Logger) -> None: logger.info({ 'allowed': decision.allowed, 'score': decision.score, 'reasons': decision.reasons, 'timestamp': datetime.utcnow().isoformat(), }) # 未来: OpenTelemetry spans, Datadog trace hooks ``` ### 9.2 异常层次结构 — `exceptions.py` | Exception | 触发时机 | |---|---| | `BlockedByPolicyError` | Prompt 或 output 超过 `block_threshold` 且 `raise_on_block=True` | | `InvalidToolCallError` | 工具名称不在白名单中,或参数未通过 schema 验证 | ## 10. 公共 API 接口 顶层包重新导出用户所需的一切。不公开任何特定于实现的内容: ``` from .providers.openai import OpenAIProvider from .providers.generic import GenericProvider from .policies import StrictPolicy, BalancedPolicy, LoggingOnlyPolicy from .config import load_policy_from_dict, load_policy_from_yaml from .types import ScanResult, GuardDecision, ToolCall from .exceptions import BlockedByPolicyError, InvalidToolCallError __all__ = [ 'OpenAIProvider', 'GenericProvider', 'StrictPolicy', 'BalancedPolicy', 'LoggingOnlyPolicy', 'load_policy_from_dict', 'load_policy_from_yaml', 'ScanResult', 'GuardDecision', 'ToolCall', 'BlockedByPolicyError', 'InvalidToolCallError', ] ``` ## 11. 测试、示例与文档 ### 11.1 测试套件 — `tests/` | 文件 | 覆盖范围 | |---|---| | `test_policies.py` | 从 dict 和 YAML 加载 Policy,阈值逻辑,预设验证 | | `test_guards_prompts.py` | 每种注入和越狱模式:通过和失败案例 | | `test_guards_outputs.py` | 凭证正则表达式,OS 命令模式,内容类别 | | `test_guards_tools.py` | Schema 验证,白名单强制执行,被阻断的操作 | | `test_providers_openai.py` | 带有模拟 API 的 OpenAI 适配器 —— 全流水线测试 | | `test_middleware_fastapi.py` | FastAPI TestClient 集成 —— 依赖注入 | ### 11.2 示例 — `examples/` - `basic_openai_guard.py` — 15 行代码的最小 OpenAI 防护 - `fastapi_endpoint_guard.py` — 带有策略注入的完整 FastAPI 端点 - `custom_policy_example.py` — 编写和加载自定义 YAML 策略 ### 11.3 文档 — `docs/` - `getting-started.md` — 安装,首次调用,首个策略 - `configuration.md` — 完整的 Policy 参考和 YAML schema - `providers.md` — 如何添加新的 ProviderAdapter - `middleware.md` — FastAPI 和 Flask 集成指南 - `contributing.md` — 添加新的 guard 规则,运行测试 ## 12. 扩展性与设计原则 该工具包经过刻意设计,对 **fork 友好**且**易于贡献**。这些原则指导着每一个架构决策: ### 小而专注的 Guards 每个 guard 函数都是单一职责的 Python 函数。添加新的检测规则意味着添加一个函数和一个测试 —— 无需浏览类层次结构。 ### 策略优先设计 所有安全决策都通过 `Policy` 对象进行。运维人员可以通过更改配置文件来改变安全态势(严格 vs. 仅记录日志)—— 无需更改代码。 ### Provider 抽象 `ProviderAdapter` ABC 意味着可以封装任何 LLM 客户端。添加 Claude、Gemini 或本地 Ollama 模型只需要实现一个方法:`chat()`。 ### 零基础设施要求 该工具包是一个纯 Python 包。没有 sidecar,没有 agent,没有 proxy。它在与您现有应用相同的进程中运行。 ## 13. 未来路线图 | 版本 | 功能 | 状态 | |---|---|---| | v1.0 | OpenAI 适配器 + prompt/output/tool guards + FastAPI | 计划中 | | v1.1 | Anthropic (Claude) provider adapter | 计划中 | | v1.1 | Flask 中间件 | 计划中 | | v1.2 | OpenTelemetry 追踪集成 | 构想中 | | v1.3 | Gemini + 本地模型 (Ollama) 适配器 | 构想中 | | v2.0 | 可选的托管 SaaS 网关配对 | 未来 | *LLM Security Toolkit — 架构文档 v1.0*
标签:AI基础设施, AI防火墙, AppSec, CISA项目, LLM护栏, Naabu, OpenAI安全, Schema验证, 人工智能安全, 内容安全, 函数调用过滤, 合规性, 大语言模型安全, 安全中间件, 安全工具包, 安全规则引擎, 提示词注入防护, 敏感数据泄露, 机密管理, 策略引擎, 网络安全, 网络安全挑战, 越狱检测, 逆向工具, 防御 evasion, 隐私保护