SIEM Detection Rules for SOC Teams
SentinelOSS emits structured JSON events to Splunk HEC and Datadog Logs Intake. Field names follow a loose ECS (Elastic Common Schema) convention so the same rules translate across SIEMs.
Event Schema
{
"@timestamp": "2026-04-23T12:34:56.789Z",
"event.kind": "alert",
"event.category": ["vulnerability"],
"event.module": "sentineloss",
"event.dataset": "sentineloss.scan",
"event.action": "scan.completed",
"event.severity": "critical | high | medium | low | info",
"event.outcome": "success | failure",
"organization.id": "org_โฆ",
"vcs.repo": "owner/name",
"vcs.branch": "main",
"vcs.commit": "abcdef1234โฆ",
"user.name": "github-username",
"vulnerability.counts": { "critical": 0, "high": 0, "medium": 0, "low": 0, "total": 0 },
"packages.total": 123,
"ssl.host": "example.com",
"ssl.grade": "A+",
"guardian.risk": "CRITICAL | HIGH | MEDIUM | LOW | CLEAN",
"guardian.score": 56,
"report.url": "https://sentineloss.cloudrf.xyz/report/โฆ",
"message": "โฆ"
}R1Critical CVE introduced on main/master
Page on-call when a critical CVE lands on a protected branch.
Splunk SPL
sourcetype="sentineloss:scan"
"event.action"="scan.completed"
"vulnerability.counts.critical">0
"vcs.branch" IN ("main","master","production","release")
| stats count by "vcs.repo","vcs.commit","user.name","report.url"Datadog
source:sentineloss @event.action:scan.completed @vulnerability.counts.critical:>0 @vcs.branch:(main OR master OR production OR release)
Monitor โ Log Alert โ threshold > 0 in 5 min โ @pagerduty-oncall
R2Spike in high-severity findings
Detects mass CVE disclosure affecting your stack, or compromised upstream package.
Splunk SPL
sourcetype="sentineloss:scan" "event.action"="scan.completed"
| bucket _time span=1h
| stats sum("vulnerability.counts.high") as high_total by _time, "organization.id"
| where high_total > 10Datadog
sum:sentineloss.vulnerability.counts.high{*} by {organization.id}
โ alert > 10 over 1hR3Guardian AI flagged code as HIGH or CRITICAL
The AI code analyzer catches logic bugs and secrets. Non-zero score deserves human review.
Splunk SPL
sourcetype="sentineloss:scan" "guardian.risk" IN ("HIGH","CRITICAL")
| table _time, "vcs.repo", "vcs.branch", "user.name", "guardian.risk", "guardian.score", "report.url"Datadog
source:sentineloss @guardian.risk:(HIGH OR CRITICAL)
R4SSL grade degradation
Cert misconfiguration or expiry โ catches before users notice.
Splunk SPL
sourcetype="sentineloss:scan" "ssl.host"=*
| eval gradebad=if("ssl.grade" IN ("C","D","E","F","T"), 1, 0)
| where gradebad=1
| stats latest(_time) as last_seen, latest("ssl.grade") as grade by "ssl.host"Datadog
source:sentineloss @ssl.grade:(C OR D OR E OR F OR T)
R5Scans by unfamiliar user (possible compromised account)
Alert when a GitHub username scans for the first time in 30 days โ could be credential theft or insider threat.
Splunk SPL
sourcetype="sentineloss:scan" earliest=-30d | stats earliest(_time) as first_seen by "organization.id","user.name" | where first_seen > relative_time(now(), "-24h")
Datadog
Log-based anomaly detection on @user.name per @organization.id โ alert on new values
R6Repository scanned outside approved list
Defend against exfiltration via repo fork. Maintain an approved-repos lookup and alert on anything outside it.
Splunk SPL
sourcetype="sentineloss:scan" | lookup approved_repos.csv repo AS "vcs.repo" OUTPUT repo AS approved | where isnull(approved) | table _time, "organization.id", "vcs.repo", "user.name"
Datadog
Use Reference Table โ alert when @vcs.repo NOT IN @ref_table
R7Zero scans for N hours (silent failure)
Tells SOC that the SentinelOSS pipeline is broken before an auditor does.
Splunk SPL
sourcetype="sentineloss:scan" earliest=-2h | stats count as scan_count by "organization.id" | where scan_count < 1
Datadog
count:sentineloss.events{*} < 1 over 2hR8Sudden drop in packages.total (supply-chain tamper)
A repo that normally has ~500 deps suddenly scans as 0 โ someone deleted the lockfile to hide CVEs.
Splunk SPL
sourcetype="sentineloss:scan" "event.action"="scan.completed"
| stats median("packages.total") as baseline, latest("packages.total") as current by "vcs.repo"
| where baseline > 50 AND current < baseline * 0.2Severity-to-Routing Mapping
| event.severity | SOC action |
|---|---|
| critical | Page on-call (PagerDuty P1) |
| high | Slack #sec-alerts + Jira ticket |
| medium | Weekly review |
| low / info | Dashboard only, no alert |
Enrichment Lookups
Add these tables in your SIEM for richer alerts:
repo_owner.csvโrepo,owner_email,team: route alerts to the correct teamprod_repos.csvโrepo,is_prod: separate prod vs sandbox prioritiescve_whitelist.csvโcve_id,reason,expires: suppress known-accepted risks