Anthropic-Cybersecurity-Skills 实战:基于 NIST AI RMF、MITRE ATLAS 与 OWASP LLM08 的向量库与 Embedding 弱点评估指南
【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills
本文基于 Anthropic-Cybersecurity-Skills 仓库中的assessing-vector-and-embedding-weaknesses技能,系统讲解如何对 RAG(检索增强生成)系统的向量存储层执行授权安全评估——覆盖嵌入反转(Embedding Inversion)、成员推断(Membership Inference)、跨租户泄漏、知识库投毒与间接提示注入五类弱点,并给出其在 NIST AI RMF、MITRE ATLAS、OWASP Top 10 for LLM Applications (2025) 三大框架中的权威映射与逐类修复控制项。读完本文,你将掌握一套可复现的六步评估流程,并能直接用仓库提供的agent.py脚本落地执行。
为什么向量层成为 LLM 应用的新攻击面
RAG 系统把文档切块后转换为 embedding 向量,存入向量数据库(Pinecone、Qdrant、Weaviate、Chroma、pgvector、FAISS),再通过检索最近邻向量来支撑 LLM 回答。这个"检索层"恰恰是 OWASPLLM08:2025 Vector and Embedding Weaknesses定义的核心风险区:向量不是单向加密,攻击者可能通过合法查询接口反向恢复源文档、判断语料成员、跨租户取数,甚至注入恶意语料污染检索结果。
本技能(SKILL.md)覆盖以下五类弱点,并统一映射到 MITRE ATLAS 父技术AML.T0024 — Exfiltration via ML Inference API(攻击者滥用合法的推理/查询访问来外泄数据):
- Embedding inversion(嵌入反转):利用训练好的反转模型或黑盒重构攻击,从向量中恢复大量原文(AML.T0024.001 Invert ML Model)。
- Membership inference(成员推断):探测某条记录是否属于语料库(AML.T0024.000)。
- Cross-tenant / multi-tenant leakage(跨租户泄漏):命名空间/集合共享或过滤器隔离缺失时,租户检索到其他租户的分块。
- Knowledge-base poisoning(知识库投毒):能写入语料库的攻击者插入精心构造的分块,使其对预期查询保持高余弦相似度从而主导检索,并携带间接提示注入载荷(AML.T0020)。
- Retrieval manipulation(检索操纵):针对大量无关查询调优的对抗性文档,即"检索劫持"。
适用场景与前置条件
何时使用本技能
- 对任何 RAG / 向量检索应用做安全评估(OWASP LLM08 覆盖);
- 向量库为多租户架构,需要证明 namespace/metadata 隔离有效性;
- 语料库接受用户提交或第三方文档(存在投毒面);
- embedding 端点对外可达(存在反转/成员推断面);
- 上线前验证检索过滤控制。
环境准备
需要:覆盖目标 embedding 端点与向量库的授权和范围;Python 3.10+;对测试集合的读(投毒测试时还需写)权限——绝不能在生产语料上执行。
# Vector DB clients + embeddings + similarity tooling python -m pip install numpy scikit-learn sentence-transformers python -m pip install qdrant-client chromadb pinecone-client weaviate-client # (optional) text-embedding inversion research baseline python -m pip install vec2text框架映射:三大标准如何锚定本次评估
仓库为技能维护了专门的框架映射文档(standards.md),把每类弱点精确挂靠到合规与威胁框架,让评估结论既可用于技术修复,也能直接用于合规举证。
NIST AI RMF 1.0 / GenAI Profile(NIST AI 600-1)
| ID | 名称 | 对应理由 |
|---|---|---|
| MEASURE-2.7 | AI 系统安全性与韧性得到评估并记录 | 对反转、成员推断、隔离与投毒弱点的评估,正衡量 RAG 向量层的安全/韧性 |
该技能在 SKILL.md frontmatter 中以nist_ai_rmf: [MEASURE-2.7]声明,与仓库整体"六框架统一映射"的设计一致(见 README.md)。MEASURE-2.7 属于 NIST AI RMF 的 Measure 职能,要求组织系统性地评估并文档化 AI 系统的安全与韧性——本技能的评估输出恰好就是该子类所需的"已评估、已记录"证据。
MITRE ATLAS(AI/ML 对抗威胁)
| ID | 名称 | 对应理由 |
|---|---|---|
| AML.T0024 | Exfiltration via ML Inference API | 父技术:查询/embedding 访问被滥用,用于外泄源数据 |
| AML.T0024.000 | Infer Training Data Membership | 成员推断探测:判断某条记录是否在语料中 |
| AML.T0024.001 | Invert ML Model | 嵌入反转:从向量重构源文本 |
| AML.T0020 | Poison Training Data | 知识库投毒:向语料库插入对抗性分块 |
| AML.T0051.001 | LLM Prompt Injection: Indirect | 存活于被检索分块中的注入载荷 |
这五条与 SKILL.md 中 "MITRE ATT&CK Mapping" 一节完全对应,其中 AML.T0024 为父技术,AML.T0024.000/001 为子技术,AML.T0020 属于 Resource Development 战术,AML.T0051.001 属于 Initial Access 战术。
OWASP Top 10 for LLM Applications (2025)
| ID | 名称 | 对应理由 |
|---|---|---|
| LLM08 | Vector and Embedding Weaknesses | 被测的核心风险类别(反转、泄漏、投毒) |
| LLM02 | Sensitive Information Disclosure | 反转/成员泄漏公开敏感源数据 |
| LLM01 | Prompt Injection | 通过被投毒的检索传递的间接注入 |
弱点类到控制项的映射
这是评估报告"发现问题 → 给出修复"的关键桥梁,建议直接作为整改清单使用:
| 弱点 | 控制措施 |
|---|---|
| Embedding inversion | 对 embedding 端点做认证 + 限流;避免暴露原始相似度分数 |
| Membership inference | 限制相似度分数暴露;增加查询审计 |
| Cross-tenant leakage | 服务端租户过滤器,或每租户独立集合/命名空间 |
| Knowledge-base poisoning | 溯源标注(provenance tagging)、内容校验、单源检索上限 |
| Indirect injection in chunks | 对检索文本做清洗(sanitize);施加输出护栏(output guardrails) |
六步评估流程(含可运行代码)
技能本体 SKILL.md 定义了六步工作流,配合 api-reference.md 的 API 速查表即可直接执行。
Step 1:盘点 RAG 流水线
记录 embedding 模型与维度、向量库及其租户模型、分块策略、检索top_k与相似度度量(cosine/dot/L2),以及查询时应用的 metadata 过滤器。以 Qdrant 为例:
from qdrant_client import QdrantClient client = QdrantClient(url="http://localhost:6333") info = client.get_collection("docs") print(info.config.params.vectors) # size + distance metric print(client.count("docs")) # corpus sizeStep 2:测试 Embedding Inversion 暴露
相似文本的 embedding 彼此接近;攻击者只要有 embedding 端点,就能迭代构造"其向量匹配目标向量"的文本。度量方式:用候选重构与目标向量之间的余弦相似度衡量恢复程度。
import numpy as np from sentence_transformers import SentenceTransformer from sklearn.metrics.pairwise import cosine_similarity model = SentenceTransformer("all-MiniLM-L6-v2") secret = "Patient John Doe, MRN 553120, diagnosed with hypertension." target_vec = model.encode([secret]) # Attacker has only target_vec and the embedding endpoint. Hill-climb candidate text. candidates = [ "Patient name and medical record number with a diagnosis.", "John Doe medical record hypertension diagnosis", "Patient John Doe MRN diagnosed hypertension", ] cand_vecs = model.encode(candidates) sims = cosine_similarity(target_vec, cand_vecs)[0] for c, s in sorted(zip(candidates, sims), key=lambda x: -x[1]): print(f"{s:.3f} {c}") # High similarity for a near-verbatim guess => inversion risk is real for this model.对兼容的 embedding 模型,可用vec2text作为研究级重构基线实现全文恢复(vec2text.load_pretrained_corrector("gtr-base")+vec2text.invert_embeddings(...),详见 api-reference.md)。
Step 3:成员推断(Membership Inference)
用"精确引用"查询的 top-1 检索相似度判断某文档是否在语料中:语料内条目返回的最大相似度明显高于语料外对照。
def membership_score(client, collection, embed, text): vec = embed([text])[0].tolist() hits = client.search(collection_name=collection, query_vector=vec, limit=1) return hits[0].score if hits else 0.0 in_corpus = membership_score(client, "docs", model.encode, "<exact quote from a known chunk>") control = membership_score(client, "docs", model.encode, "An unrelated random sentence.") print(f"in-corpus={in_corpus:.3f} control={control:.3f} delta={in_corpus-control:.3f}") # A large positive delta indicates the item is in the corpus (membership leak).Step 4:测试多租户隔离
确认租户 B 无法检索租户 A 的分块。用租户 B 的认证身份发起"本应被过滤"的查询,并验证结果中不出现tenant_id == A的行。
from qdrant_client.models import Filter, FieldCondition, MatchValue vec = model.encode(["confidential salary information"])[0].tolist() hits = client.search( collection_name="docs", query_vector=vec, limit=10, query_filter=Filter(must=[FieldCondition(key="tenant_id", match=MatchValue(value="B"))]), ) leaked = [h for h in hits if h.payload.get("tenant_id") != "B"] print("CROSS-TENANT LEAK" if leaked else "isolation OK", "->", len(leaked), "foreign rows") # Critical test: repeat WITHOUT the filter to confirm the server, not the client, # enforces isolation. If unfiltered queries return tenant A data, isolation is client-side only. hits_nofilter = client.search(collection_name="docs", query_vector=vec, limit=10) print("server-side isolation FAILS" if any(h.payload.get("tenant_id") != "B" for h in hits_nofilter) else "OK")关键判据:必须同时测试带过滤器与不带过滤器的查询。若不带过滤器的查询能返回租户 A 数据,说明隔离只是客户端侧的"自觉",服务端并未强制,属于高危发现。
Step 5:知识库投毒(仅限测试集合)
插入一个良性投毒分块(纯标记载荷,不含真实注入),构造其被大量无关查询检索到的场景,再测量它在top_k中出现的频率。
from qdrant_client.models import PointStruct # Benign marker payload (no real injection) to measure retrieval dominance. poison = "POISON-CANARY. " + " ".join( ["password reset billing refund account login support error help"] * 8 ) client.upsert("docs_test", points=[ PointStruct(id=999999, vector=model.encode([poison])[0].tolist(), payload={"tenant_id": "B", "source": "poison-test"}) ]) queries = ["how do I get a refund", "reset my password", "what is the weather"] for q in queries: hits = client.search("docs_test", model.encode([q])[0].tolist(), limit=5) dominated = any(h.payload.get("source") == "poison-test" for h in hits) print(f"{'POISON in top5' if dominated else 'clean'}: {q}")Step 6:检测检索分块中的间接提示注入
在分块文本被拼接进提示词之前,扫描其是否包含注入标记。
import re INJECTION_PATTERNS = [ r"ignore (all|previous|the above) instructions", r"system prompt", r"you are now", r"disregard", r"</?(system|instructions)>", ] def chunk_is_injection(text): low = text.lower() return [p for p in INJECTION_PATTERNS if re.search(p, low)] for hit in client.search("docs", model.encode(["help"])[0].tolist(), limit=10): flags = chunk_is_injection(hit.payload.get("text", "")) if flags: print("INDIRECT INJECTION in chunk", hit.id, flags)一键自动化:仓库自带 agent.py 评估器
除手工脚本外,仓库提供了完整的命令行评估器 scripts/agent.py,将上述四类检查(反转、成员、隔离、注入)封装为四个子命令,可直接在授权的目标上运行:
# 1) 嵌入反转:度量猜测重构与目标向量的余弦相似度 python agent.py inversion --secret "MRN 553120 hypertension" \ --guess "patient MRN hypertension diagnosis" # 2) 成员推断:计算语料内 vs 对照的 top-1 相似度差(Qdrant) python agent.py membership --url http://localhost:6333 --collection docs \ --quote "<exact chunk quote>" --control "unrelated sentence" # 3) 多租户隔离:验证服务端租户过滤(Qdrant) python agent.py isolation --url http://localhost:6333 --collection docs \ --tenant-field tenant_id --tenant B --query "salary information" # 4) 间接注入:扫描检索分块中的提示注入标记 python agent.py injection --url http://localhost:6333 --collection docs \ --query "help" --limit 10从源码结构看,脚本的实现与 SKILL.md 中手工流程一一对应,且内置了可解释的判定阈值(agent.py各子命令的判定逻辑):
- inversion:
cosine_similarity(tv, gv)[0][0]作为度量,>= 0.85判定 HIGH inversion risk,>= 0.6为 moderate,否则 low,并以退出码 1/0 表达判定结果(scripts/agent.py); - membership:
delta = in_corpus - control,>= 0.2即判定 MEMBERSHIP LEAK(scripts/agent.py); - isolation:同时统计 filtered 与 unfiltered 查询返回的外租户行数,filtered 泄漏为 CRITICAL,仅 unfiltered 泄漏则提示"隔离仅客户端侧"(scripts/agent.py);
- injection:复用与 SKILL.md 一致的正则
INJECTION_PATTERNS,统计被标记的分块数(scripts/agent.py)。
脚本还通过模块级 ImportError 检查引导环境(sentence-transformers、qdrant-client缺失时直接退出并给出安装提示,见 scripts/agent.py),保证在干净环境中的可复现性。默认 embedding 模型为all-MiniLM-L6-v2(384 维,可通过--model覆盖,scripts/agent.py)。
跨向量库 API 速查
api-reference.md 提供了多向量库的等价调用,便于把流程迁移到其他存储后端:
| 操作 | Qdrant | Chroma | Pinecone |
|---|---|---|---|
| 连接 | QdrantClient(url="http://localhost:6333") | chromadb.Client()/PersistentClient(path) | Pinecone(api_key=...) |
| 检索 | client.search(collection_name, query_vector, limit, query_filter) | collection.query(query_embeddings=[...], n_results=k, where={...}) | index.query(vector=..., top_k=k, namespace="tenant", filter={...}) |
| 写入 | client.upsert(name, points=[PointStruct(id, vector, payload)]) | collection.add(ids, embeddings, metadatas, documents) | index.upsert(vectors=[(id, vec, meta)], namespace=...) |
| 元数据过滤 | Filter(must=[FieldCondition(key, match=MatchValue(value))]) | where={...} | namespace+filter={...}(namespace 即租户边界) |
Pinecone 的namespace参数天然承担租户边界职责;Chroma 的where与 Qdrant 的query_filter则是 metadata 过滤的对应物——测试时均需验证服务端是否强制这些边界。
评估度量口径
| 度量 | 含义 |
|---|---|
| Inversion cosine | 重构候选与目标向量的相似度;越高越可恢复 |
| Membership delta | top-1(语料内查询)− top-1(对照查询);大正值 = 成员泄漏 |
| Poison dominance | 无关查询在 top_k 中返回投毒分块的比例 |
| Cross-tenant count | 租户查询返回的外租户行数(应为 0) |
报告与修复:把框架映射落到整改动作
评估结束后按弱点类逐项汇报并落实控制(对应 standards.md 的"弱点→控制"映射):
- Inversion / membership:对 embedding 端点做认证 + 限流;避免返回原始相似度分数;限制可查询 embedding 的人员范围。
- Cross-tenant:服务端强制租户过滤器(可行时每租户独立集合/命名空间);绝不依赖客户端提交的过滤器。
- Poisoning:每个摄入分块做内容校验与溯源标注;对输入做注入扫描;限制单一来源在检索结果中的占比。
- Indirect injection:清洗检索到的文本并施加输出护栏(可参考仓库内
defending-llms-with-guardrails技能)。
验收清单
完成评估后逐项勾选:
- RAG 流水线已盘点(embedding 模型、存储、租户模型、度量、top_k、过滤器)
- Embedding 反转暴露已测量并定级
- 已计算语料内 vs 对照的成员推断差值
- 多租户隔离已分别在带/不带客户端过滤器下测试(确认服务端强制)
- 仅在测试集合中测量投毒主导性
- 已扫描检索分块中的间接注入内容
- 每个弱点类均已给出修复建议
- 评估过程中未修改生产语料
结语
向量检索层是 LLM 应用安全中"看不见却致命"的一环:一条MEASURE-2.7的合规要求,背后是 AML.T0024 家族的完整攻击面与 OWASP LLM08/LLM02/LLM01 的真实风险。通过本技能的五类弱点评测与六步流程,配合仓库自带的 agent.py 与 api-reference.md,你可以在授权范围内把"向量层安全"从口号变成可度量、可复现、可整改的工程实践——最终以 standards.md 的框架映射表格,把评估结论无缝转换为审计与合规证据。
【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考