From ce73a7b3e47025ca08c7d7a58930fec30a42a9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Sun, 21 Jun 2026 01:55:25 +0800 Subject: [PATCH] Add files via upload --- internal/project/fact_edges.go | 58 +++++++++++++++++++---------- internal/project/fact_edges_test.go | 14 +++++-- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/internal/project/fact_edges.go b/internal/project/fact_edges.go index 2d11e8fb..d9d15795 100644 --- a/internal/project/fact_edges.go +++ b/internal/project/fact_edges.go @@ -19,8 +19,39 @@ var PathGraphCategories = map[string]struct{}{ } // GraphNodeType 将 fact category 映射为图节点类型(供前端样式与 ELK 分层)。 +// 优先使用 category;仅 synthetic 节点(vuln:)或无 category 时才回退到 fact_key 前缀。 func GraphNodeType(category, factKey string) string { key := strings.ToLower(strings.TrimSpace(factKey)) + if strings.HasPrefix(key, "vuln:") { + return "vulnerability" + } + c := strings.ToLower(strings.TrimSpace(category)) + if c != "" { + switch c { + case FactCategoryTarget: + return "target" + case FactCategoryExploit: + return "exploit" + case FactCategoryPOC: + return "poc" + case FactCategoryChain: + return "chain" + case FactCategoryFinding: + return "finding" + case "vuln": + return "vulnerability" + case FactCategoryAuth: + return "auth" + case FactCategoryInfra, FactCategoryBusiness: + return "infra" + case FactCategoryNote: + return "note" + case "missing": + return "missing" + default: + return c + } + } switch { case strings.HasPrefix(key, "target/"): return "target" @@ -36,25 +67,6 @@ func GraphNodeType(category, factKey string) string { return "auth" case strings.HasPrefix(key, "infra/"), strings.HasPrefix(key, "business/"): return "infra" - case strings.HasPrefix(key, "vuln:"): - return "vulnerability" - } - c := strings.ToLower(strings.TrimSpace(category)) - switch c { - case FactCategoryTarget: - return "target" - case FactCategoryExploit: - return "exploit" - case FactCategoryPOC: - return "poc" - case FactCategoryChain: - return "chain" - case FactCategoryFinding, "vuln": - return "finding" - case "auth": - return "auth" - case "infra", "business": - return "infra" default: return "note" } @@ -258,6 +270,9 @@ func isPathGraphFact(category, factKey string) bool { if _, ok := PathGraphCategories[c]; ok { return true } + if c != "" { + return false + } key := strings.ToLower(strings.TrimSpace(factKey)) for _, p := range []string{"target/", "finding/", "chain/", "exploit/", "poc/", "evidence/"} { if strings.HasPrefix(key, p) { @@ -269,9 +284,12 @@ func isPathGraphFact(category, factKey string) bool { func isDependencyGraphFact(category, factKey string) bool { c := strings.ToLower(strings.TrimSpace(category)) - if c == "auth" || c == "infra" || c == "business" { + if c == FactCategoryAuth || c == FactCategoryInfra || c == FactCategoryBusiness { return true } + if c != "" { + return false + } key := strings.ToLower(strings.TrimSpace(factKey)) return strings.HasPrefix(key, "auth/") || strings.HasPrefix(key, "infra/") || strings.HasPrefix(key, "business/") } diff --git a/internal/project/fact_edges_test.go b/internal/project/fact_edges_test.go index eae1a435..2e4b3775 100644 --- a/internal/project/fact_edges_test.go +++ b/internal/project/fact_edges_test.go @@ -102,11 +102,17 @@ func TestGraphNodeType(t *testing.T) { if GraphNodeType("exploit", "exploit/x") != "exploit" { t.Fatal("exploit category") } - if GraphNodeType("finding", "evidence/x") != "exploit" { - t.Fatal("evidence prefix") + if GraphNodeType("finding", "evidence/x") != "finding" { + t.Fatal("category should override evidence key prefix") } - if GraphNodeType("note", "target/x") != "target" { - t.Fatal("target prefix") + if GraphNodeType("note", "target/x") != "note" { + t.Fatal("category should override target key prefix") + } + if GraphNodeType("vuln", "finding/x") != "vulnerability" { + t.Fatal("vuln category maps to vulnerability node type") + } + if GraphNodeType("", "target/x") != "target" { + t.Fatal("empty category falls back to target key prefix") } }