mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-20 06:27:53 +02:00
feat: verify attack-chain nodes against real tool calls
A node claiming something ran must cite a tool_call_id the host issued in the trajectory. A citation absent from the trajectory is invented, so the node is dropped along with its edges; a missing citation counts as invented only when every real ID survived budget fitting, so a trimmed payload cannot silently empty a graph. Judging is skipped where the evidence cannot be enumerated: the process-detail supplement dumps raw event JSON and the messages-table fallback carries no call IDs. Verified citations land in node metadata rather than tool_execution_id, which is foreign-keyed to tool_executions. Also close two smaller holes: fact text can no longer carry the host index delimiters, which would close the block early and spill the remaining index into the system prompt; and the console fact endpoints reject the reserved note/context-* prefix, matching the MCP tool layer.
This commit is contained in:
1 parent
16189e0b76
commit
3d2dfdac36
10 files changed
+341
-15
No files matched your search
@@ -422,6 +422,9 @@ func (h *ProjectHandler) GetFactGraph(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, graph)
|
||||
}
|
||||
|
||||
// note/context-* 由压缩流程独占写入;手工改写会让目标会话把它当成当前工作记录。
|
||||
const reservedContextCheckpointError = "note/context-* 为系统续接记录,不能在控制台创建或改写;项目共享事实请使用独立 fact_key"
|
||||
|
||||
// CreateFact POST /api/projects/:id/facts
|
||||
func (h *ProjectHandler) CreateFact(c *gin.Context) {
|
||||
var req upsertFactRequest
|
||||
@@ -429,6 +432,10 @@ func (h *ProjectHandler) CreateFact(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if database.IsContextCheckpointKey(req.FactKey) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": reservedContextCheckpointError})
|
||||
return
|
||||
}
|
||||
projectID := c.Param("id")
|
||||
f := &database.ProjectFact{
|
||||
ProjectID: projectID,
|
||||
@@ -463,6 +470,10 @@ func (h *ProjectHandler) UpdateFact(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
oldFactKey := existing.FactKey
|
||||
if database.IsContextCheckpointKey(oldFactKey) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": reservedContextCheckpointError})
|
||||
return
|
||||
}
|
||||
var req updateFactRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
@@ -470,6 +481,10 @@ func (h *ProjectHandler) UpdateFact(c *gin.Context) {
|
||||
}
|
||||
if req.FactKey != nil {
|
||||
if k := strings.TrimSpace(*req.FactKey); k != "" {
|
||||
if database.IsContextCheckpointKey(k) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": reservedContextCheckpointError})
|
||||
return
|
||||
}
|
||||
existing.FactKey = k
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user