[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81354":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":13,"stars30d":13,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":15,"rankGlobal":9,"rankLanguage":9,"license":16,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":9,"pushedAt":9,"updatedAt":21,"readmeContent":22,"aiSummary":23,"trendingCount":14,"starSnapshotCount":14,"syncStatus":24,"lastSyncTime":25,"discoverSource":26},81354,"SIEMTriage","rod-trent\u002FSIEMTriage","rod-trent","A Triage Agent for reducing junior analyst manual activiites",null,"TypeScript",41,6,1,0,2.54,"MIT License",false,"main",true,[],"2026-06-12 02:04:14","# SIEMTriage\n\nAn AI SOC triage agent for **Microsoft Sentinel** and **Defender XDR**, built on the [Claude Agent SDK](https:\u002F\u002Fdocs.claude.com\u002Fen\u002Fagent-sdk\u002Ftypescript). It does the work of a Tier-1 analyst — pulls the incident, enriches the entities, runs hunting queries, and produces a verdict with a full evidence trail — then hands off to a human analyst with a proposed deep-dive plan.\n\nThe agent **never closes incidents or takes response actions on its own**. It produces verdicts; analysts decide.\n\n## What it does\n\nGiven a Sentinel or Defender XDR incident ID, the agent:\n\n1. Pulls the incident envelope, alerts, and entities (Microsoft Graph Security API).\n2. Enriches entities — IPs\u002Fhashes\u002Fdomains through VirusTotal, GreyNoise, AbuseIPDB, MS Threat Intel; users through Entra ID risky-user score + MFA state; devices through MDE timeline.\n3. Runs targeted KQL hunts in both Sentinel Log Analytics and Defender XDR Advanced Hunting.\n4. Returns a **strictly-typed verdict** (zod-validated): classification, confidence, evidence chain, deep-dive plan, recommended actions.\n5. Streams every step to the UI so analysts can watch and intervene.\n\nThree example incidents shipped with the repo demonstrate the spectrum:\n\n| Fixture | Truth | Agent verdict | What it shows |\n|---|---|---|---|\n| `inc-001-failed-signins-fp` | False positive | `FalsePositive` 95% | Failed sign-ins resolved by a self-service password reset. The agent spots the AuditLog row between the failures and the success and clears it. |\n| `inc-002-brute-force-investigate` | True positive | `TruePositive` 97% · deep dive | Password spray from a known-bad IP succeeds against a no-MFA service account, followed by SharePoint downloads. The agent independently flags the CA-policy gap and the PII-breach angle. |\n| `inc-003-malware-tp` | True positive | `TruePositive` 98% · deep dive | Wacatac trojan with C2 callout. The agent notes Defender's remediation was **partial** and proposes memory forensics + tenant-wide IOC sweep. |\n\n## Architecture\n\n```\n┌─────────────────────┐    ┌──────────────────┐    ┌────────────────────┐\n│ Sentinel automation │──▶ │ \u002Fapi\u002Fingest\u002F     │──▶ │ Redis queue        │\n│  → Logic App        │    │   sentinel       │    │  (BullMQ)          │\n└─────────────────────┘    └──────────────────┘    └─────────┬──────────┘\n                                                              │\n                                                              ▼\n                ┌─────────────────────────────────────────────────────┐\n                │ Worker service — Claude Agent SDK                    │\n                │   • Triage Agent (Sonnet 4.6, read-only tools)       │\n                │   • SOC MCP tools → Microsoft Graph + Log Analytics  │\n                │   • submit_verdict (zod-validated)                   │\n                │   • Streams every step to Redis pub\u002Fsub + Postgres   │\n                └────────────────────────┬────────────────────────────┘\n                                          │\n                                          ▼\n┌────────────────────┐    ┌──────────────────────────────────────────┐\n│ Postgres           │◀── │ Next.js UI                                │\n│   • incidents      │    │   • Queue (verdict pills, status)         │\n│   • triage_runs    │───▶│   • Incident detail (verdict + evidence + │\n│   • tool_calls     │    │     deep-dive plan + decision panel)      │\n│   • agent_thoughts │    │   • SSE stream of live agent reasoning    │\n│   • decisions      │    │   • Eval report (accuracy, FN rate)       │\n└────────────────────┘    └──────────────────────────────────────────┘\n```\n\n## Quickstart — demo mode (no infrastructure)\n\nThis is the fastest way to see the UI. No Postgres, no Redis, no Azure access — the UI reads pre-computed verdicts from `replay-output\u002F`.\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Frod-trent\u002FSIEMTriage.git\ncd SIEMTriage\nnpm install\ncp .env.example .env                       # add ANTHROPIC_API_KEY for the replay step\nnpm run replay -- --all                    # generates replay-output\u002F*.json\necho \"TRIAGE_DEMO_MODE=1\" > apps\u002Fweb\u002F.env.local\nnpm run dev:web                            # http:\u002F\u002Flocalhost:3000\n```\n\nPages:\n- `\u002F` — incident queue\n- `\u002Fincidents\u002F\u003Cid>` — verdict, evidence, deep-dive plan, decision panel, live-streaming agent reasoning\n- `\u002Feval` — accuracy, false-negative rate, confusion matrix, per-case results\n\n## Quickstart — full stack (local DB + queue)\n\nFor end-to-end with persistence, ingestion, and analyst decisions:\n\n```bash\n# 1. Bring up Postgres + Redis\ndocker compose up -d\n\n# 2. Env\ncp .env.example .env\n# Fill in ANTHROPIC_API_KEY, leave TRIAGE_BACKEND=fixture for now\n\n# 3. Apply schema\ncd packages\u002Fdb && npx drizzle-kit push && cd ..\u002F..\n\n# 4. Run the worker in one terminal\nnpm run worker\n\n# 5. Run the web app in another\nnpm run dev:web\n\n# 6. Enqueue a fixture incident\ncurl -X POST http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fingest\u002Fsentinel \\\n  -H \"content-type: application\u002Fjson\" \\\n  -d '{\"id\":\"inc-001-failed-signins-fp\",\"title\":\"Failed sign-ins\",\"severity\":\"Medium\",\"source\":\"Sentinel\",\"createdTimeUtc\":\"2026-05-10T14:32:00Z\"}'\n```\n\nThe worker picks it up, runs the agent, streams every step to the incident page in real time, and stops at `awaiting_decision` for you to click Close or Proceed.\n\n## Wiring to live Microsoft Sentinel + Defender XDR\n\n```bash\n# In .env\nTRIAGE_BACKEND=azure\nAZURE_TENANT_ID=\u003Cyour-tenant>\nAZURE_LOG_ANALYTICS_WORKSPACE_ID=\u003Cworkspace-guid>\n\n# Optional threat-intel keys — missing keys mean the source is silently skipped\nVIRUSTOTAL_API_KEY=\nGREYNOISE_API_KEY=\nABUSEIPDB_API_KEY=\n```\n\n**Auth**: uses `DefaultAzureCredential`. Locally run `az login`; in Azure use a managed identity granted:\n\n- Microsoft Graph: `SecurityIncident.Read.All`, `SecurityAlert.Read.All`, `ThreatHunting.Read.All`, `User.Read.All`, `IdentityRiskyUser.Read.All`, `UserAuthenticationMethod.Read.All`\n- Log Analytics workspace: `Log Analytics Reader`\n\n**Sentinel ingestion**: in the Sentinel portal create an automation rule that triggers a Logic App on incident creation. The Logic App posts the incident envelope to `https:\u002F\u002F\u003Cyour-host>\u002Fapi\u002Fingest\u002Fsentinel` with header `X-Ingest-Secret: \u003CINGEST_SECRET>`.\n\n## Eval — measure agent agreement against analyst-closed incidents\n\nBefore letting the agent auto-close anything, replay it against your historical incidents and measure:\n\n```bash\nTRIAGE_BACKEND=azure npm run eval -- --since 2026-02-01 --until 2026-05-01 --max 200\n```\n\nOutput:\n\n```\nTotal incidents:     187\nOverall accuracy:    164\u002F187 (87.7%)\nFalse negatives:     2\u002F64 real TPs (3.1%)  ← the number that gates autonomy\nNo verdict:          1\u002F187 (0.5%)\nMean tool calls:     10.3\nMean duration:       86.7s\n\n=== Auto-close gate ===\nCases meeting auto-close criteria (FP\u002FBenign + !deepDive + conf >= 0.9): 47\n  …of which were actually TPs: 0  ← MUST be zero before enabling auto-close\n```\n\nThe **dangerous auto-close** count must be zero before any production auto-closure of incidents. The eval CLI exits non-zero when it isn't.\n\n## Repo layout\n\n```\nSIEMTriage\u002F\n├── packages\u002F\n│   ├── shared\u002F              Zod schemas: Incident, Verdict, Evidence, KQL, Enrichment\n│   ├── mcp-soc-tools\u002F       SDK MCP server. Backend interface with two impls:\n│   │   ├── backend\u002Ffixture  Reads from packages\u002Fmcp-soc-tools\u002Ffixtures\u002F\n│   │   └── backend\u002Fazure    Microsoft Graph + Log Analytics + XDR + Entra + MDE\n│   ├── agent-core\u002F          Triage Agent (system prompt + submit_verdict gate)\n│   ├── db\u002F                  Drizzle ORM schema for incidents\u002Fruns\u002Ftools\u002Fdecisions\n│   └── queue\u002F               BullMQ + Redis pub\u002Fsub for SSE event streaming\n├── apps\u002F\n│   ├── replay\u002F              CLI: run the agent against fixture incidents\n│   ├── eval\u002F                CLI: replay against closed incidents + metrics\n│   ├── worker\u002F              Long-running service that consumes the queue\n│   └── web\u002F                 Next.js 15 UI (queue, incident detail, eval)\n├── docker-compose.yml       Local Postgres + Redis\n└── .env.example\n```\n\n## Key design decisions\n\n- **Two-agent split (Triage + Investigation)** — the Triage Agent runs fast and cheap on every incident; the Investigation Agent only runs when an analyst clicks \"Proceed deep dive.\" This keeps per-incident cost down when 80% close at triage, and means the analyst is approving \"go deeper,\" not \"do whatever.\"\n- **`submit_verdict` as the completion signal** — the agent doesn't free-text its answer; it calls a tool whose zod schema *is* the verdict. Schema validation enforces evidence-with-every-claim by construction.\n- **`tools: []`** in the agent config strips all built-in tools. The agent can only call SOC MCP tools and `submit_verdict` — no file system, no shell, no surprises.\n- **Read-only at the agent layer.** Response actions (isolate host, disable user, revoke sessions) are recommended in the verdict but only executed by an analyst clicking through the UI's decision panel. The audit trail is the analyst's, not the agent's.\n- **Cite numbers, not adjectives.** The system prompt drills this in: \"8 failed sign-ins followed by a successful auth at 14:30:08 UTC\" beats \"had some failures then succeeded.\" Tier-2 needs to reproduce the evidence.\n- **Eval gates autonomy.** The `dangerousAutoCloses` metric in the eval harness must be zero before enabling any auto-closure path in production.\n\n## What's stubbed\n\n- **Entra SSO** — `apps\u002Fweb\u002Fsrc\u002Flib\u002Fauth.ts` returns a dev user from a cookie. Replace with NextAuth + the Azure AD provider for production. Every UI\u002FAPI surface reads through `getCurrentUser()`, so it's literally one file.\n- **Investigation Agent** — the second-phase agent (broader tools, runs after an analyst clicks \"Proceed deep dive\") isn't implemented yet. The decision panel already calls `getTriageQueue().add(\"deep_dive\", ...)` so the wiring is there.\n- **Production deployment** — no infra-as-code yet. The intended target is Azure Container Apps for both worker and web, Azure Database for PostgreSQL, Azure Cache for Redis, managed identity for auth.\n\n## License\n\nMIT\n","SIEMTriage 是一个用于减少初级分析师手动活动的AI SOC分类代理，专为Microsoft Sentinel和Defender XDR设计。它基于Claude Agent SDK构建，能够自动提取事件、丰富实体信息（如通过VirusTotal、GreyNoise等服务）、执行针对性查询，并生成带有完整证据链的结论，随后将结果提交给人类分析师进行进一步审查。该代理不会自行关闭事件或采取响应措施，而是提供分析结论供分析师决策。适用于需要快速准确地处理安全事件并减轻一线分析师工作负担的安全运营中心。",2,"2026-06-11 04:04:43","CREATED_QUERY"]