ONNX
security
malware-detection
File size: 7,719 Bytes
d2507b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package types

// SkillFile is the parsed representation of a Claude Code skill markdown file.
type SkillFile struct {
	Name          string   `yaml:"name"`
	Description   string   `yaml:"description"`
	Type          string   `yaml:"type,omitempty"`
	Triggers      []string `yaml:"triggers,omitempty"`
	Body          string   // Markdown body after frontmatter
	RawContent    string   // Original full file content
	FilePath      string
	BodyStartLine int // 1-based line number where Body begins in RawContent
}

// FeatureVector holds numeric features extracted from a SkillFile.
type FeatureVector struct {
	// Structural (7 features)
	BodyLength        float64
	DescriptionLength float64
	LineCount         float64
	CodeBlockCount    float64
	URLCount          float64
	AvgLineLength     float64
	ShannonEntropy    float64

	// Keyword presence scores (count-based per category)
	InjectionKeywordScore  float64
	ExfilKeywordScore      float64
	SystemManipScore       float64
	SocialEngineeringScore float64

	// Regex pattern match counts
	NetworkCommandCount            float64
	EnvAccessCount                 float64
	FilePathSensitiveCount         float64
	Base64PatternCount             float64
	DestructiveCommandCount        float64
	PrivEscalationCount            float64
	RoleOverrideCount              float64
	UrgencyLanguageCount           float64
	HiddenUnicodeCount             float64
	PackageLookalikeCount          float64
	PackageInstallLookalikeCount   float64
	PackageContextLookalikeCount   float64
	PackageRiskContextCount        float64
	SupplyChainCredentialFlowCount float64
	PackageBootstrapHookCount      float64
	HiddenContainerCount           float64
	SensitiveCaptureCount          float64
	HeadSensitiveDirective         float64
	TailSensitiveDirective         float64
	CovertSensitiveDirective       float64
	HeadCovertSensitiveDirective   float64

	// Section-aware features (keywords in code blocks vs prose)
	ProseKeywordRatio     float64 // suspicious keywords in prose / total suspicious keywords
	CodeBlockKeywordRatio float64 // suspicious keywords in code blocks / total suspicious keywords
	KeywordDensity        float64 // suspicious keywords / total words

	// Bigram features (action+target vs educational patterns)
	AttackBigramCount      float64 // "send credentials", "execute command", etc.
	EducationalBigramCount float64 // "prevent attack", "detect injection", etc.
	BigramRatio            float64 // attack bigrams / (attack + educational + 1)

	// Verb intent features (prescriptive policy language vs imperative action commands)
	PrescriptiveVerbCount float64 // must/should/ensure/verify/check/enforce/validate/prevent
	ImperativeVerbCount   float64 // send/post/gather/collect/execute/run/curl/wget
	VerbIntentRatio       float64 // prescriptive / (prescriptive + imperative + 1)

	// Positional features
	FirstSuspiciousPosition float64 // normalized position (0-1) of first suspicious keyword
	SuspiciousInTail        float64 // count of suspicious keywords in last 10% of document

	// TF-IDF features (variable length, flattened for XGBoost)
	TfidfFeatures []float64
}

// ToSlice flattens the feature vector into a []float64 for model input.
func (fv *FeatureVector) ToSlice() []float64 {
	base := []float64{
		fv.BodyLength,
		fv.DescriptionLength,
		fv.LineCount,
		fv.CodeBlockCount,
		fv.URLCount,
		fv.AvgLineLength,
		fv.ShannonEntropy,

		fv.InjectionKeywordScore,
		fv.ExfilKeywordScore,
		fv.SystemManipScore,
		fv.SocialEngineeringScore,

		fv.NetworkCommandCount,
		fv.EnvAccessCount,
		fv.FilePathSensitiveCount,
		fv.Base64PatternCount,
		fv.DestructiveCommandCount,
		fv.PrivEscalationCount,
		fv.RoleOverrideCount,
		fv.UrgencyLanguageCount,
		fv.HiddenUnicodeCount,
		fv.PackageLookalikeCount,
		fv.PackageInstallLookalikeCount,
		fv.PackageContextLookalikeCount,
		fv.PackageRiskContextCount,
		fv.SupplyChainCredentialFlowCount,
		fv.PackageBootstrapHookCount,
		fv.HiddenContainerCount,
		fv.SensitiveCaptureCount,
		fv.HeadSensitiveDirective,
		fv.TailSensitiveDirective,
		fv.CovertSensitiveDirective,
		fv.HeadCovertSensitiveDirective,

		fv.ProseKeywordRatio,
		fv.CodeBlockKeywordRatio,
		fv.KeywordDensity,
		fv.AttackBigramCount,
		fv.EducationalBigramCount,
		fv.BigramRatio,
		fv.PrescriptiveVerbCount,
		fv.ImperativeVerbCount,
		fv.VerbIntentRatio,
		fv.FirstSuspiciousPosition,
		fv.SuspiciousInTail,
	}
	return append(base, fv.TfidfFeatures...)
}

// FeatureNames returns ordered names for the base features (excluding TF-IDF).
func FeatureNames() []string {
	return []string{
		"body_length",
		"description_length",
		"line_count",
		"code_block_count",
		"url_count",
		"avg_line_length",
		"shannon_entropy",
		"injection_keyword_score",
		"exfil_keyword_score",
		"system_manip_score",
		"social_engineering_score",
		"network_command_count",
		"env_access_count",
		"file_path_sensitive_count",
		"base64_pattern_count",
		"destructive_command_count",
		"priv_escalation_count",
		"role_override_count",
		"urgency_language_count",
		"hidden_unicode_count",
		"package_lookalike_count",
		"package_install_lookalike_count",
		"package_context_lookalike_count",
		"package_risk_context_count",
		"supply_chain_credential_flow_count",
		"package_bootstrap_hook_count",
		"hidden_container_count",
		"sensitive_capture_count",
		"head_sensitive_directive",
		"tail_sensitive_directive",
		"covert_sensitive_directive",
		"head_covert_sensitive_directive",
		"prose_keyword_ratio",
		"code_block_keyword_ratio",
		"keyword_density",
		"attack_bigram_count",
		"educational_bigram_count",
		"bigram_ratio",
		"prescriptive_verb_count",
		"imperative_verb_count",
		"verb_intent_ratio",
		"first_suspicious_position",
		"suspicious_in_tail",
	}
}

// RuleMatch represents a single line-level detection from a heuristic rule.
type RuleMatch struct {
	RuleName string `json:"rule_name"`
	Line     int    `json:"line"`               // 1-based line in the original file
	EndLine  int    `json:"end_line,omitempty"` // end line for multi-line matches (0 = same as Line)
	Text     string `json:"text"`               // matched text or indicator description
	// File is the originating sibling (RelPath) for cross-file/bundle findings.
	// Empty for single-file rules (omitted in JSON), so existing single-.md
	// output is byte-for-byte identical. Enables per-sibling suppression by
	// (RuleName + File) instead of only global-by-RuleName. Purely additive:
	// does NOT touch FeatureVector / ToSlice / FeatureNames / the frozen vector.
	File string `json:"file,omitempty"`
}

// CategoryScore represents the detection score for a single threat category.
type CategoryScore struct {
	Category   string      `json:"category"`
	Score      float64     `json:"score"`
	Triggered  bool        `json:"triggered"`
	Indicators []string    `json:"indicators,omitempty"`
	RuleNames  []string    `json:"rule_names,omitempty"`
	Matches    []RuleMatch `json:"matches,omitempty"`
}

// HeuristicResult is the output of the rule-based engine.
type HeuristicResult struct {
	Flagged         bool            `json:"flagged"`
	Score           float64         `json:"score"`
	Categories      []CategoryScore `json:"categories"`
	VerbIntentRatio float64         `json:"verb_intent_ratio"` // prescriptive / (prescriptive + imperative + 1)
}

// Verdict is the final classification output.
type Verdict struct {
	Label      string          `json:"label"`
	Confidence float64         `json:"confidence"`
	MLScore    float64         `json:"ml_score"`
	BERTScore  float64         `json:"bert_score,omitempty"`
	Heuristic  HeuristicResult `json:"heuristic"`
	Categories []CategoryScore `json:"categories"`
	Reasons    []string        `json:"reasons"`
}