ONNX
security
malware-detection
Vigil / source /pkg /types /types.go
turentomer's picture
Publish self-contained Vigil distribution
d2507b5 verified
Raw
History Blame Contribute Delete
7.72 kB
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"`
}