Skip to content

feat: per-mailbox sender-graph BEC detector (closes #26)#301

Open
schmug wants to merge 1 commit into
mainfrom
claude/wizardly-einstein-PguCz
Open

feat: per-mailbox sender-graph BEC detector (closes #26)#301
schmug wants to merge 1 commit into
mainfrom
claude/wizardly-einstein-PguCz

Conversation

@schmug
Copy link
Copy Markdown
Owner

@schmug schmug commented May 19, 2026

Summary

  • Adds a sender_graph SQLite table to the per-mailbox Durable Object tracking (display_name, sender_address) history, seeded on every inbound email.
  • Introduces a Detector interface (workers/security/detectors.ts) and SenderGraphDetector implementing BEC / display-name impersonation detection: flags when a new sender address claims a display name previously seen from a different address in that mailbox.
  • Wires the detector score (+10–25, capped at +30) as a post-aggregation boost in the verdict stage alongside the existing intel-feed and off-hours boosts.
  • Adds detectors.sender_graph.enabled to MailboxSecuritySettings (default: true); setting to false disables the signal and returns scoring to baseline.

Closes #26

Authz / false-positive design

Fresh mailboxes produce zero detector contribution — the table starts empty, so there is no history to trigger on. The +30 cap and the graduated scoring (1 message → +10, 2–4 → +15, ≥5 → +25) ensure the detector can only tilt borderline verdicts until the mailbox has built real sender history.

Size note

9 files touched, ~480 lines. All 9 files are tightly coupled to deliver a single atomic feature (schema → migration → DO methods → detector → settings → pipeline integration → tests). They cannot be split into two independently useful PRs.

Test plan

  • npm test passes — 1092 tests (84 files), including 13 new tests in test/security/sender-graph-detector.test.ts
  • npm run typecheck passes — 0 errors
  • BEC scenario: mailbox with sender history → impersonation email → BEC signal in verdict signals
  • Fresh mailbox: impersonation email → no BEC signal (no history to compare)
  • Known sender re-emailing → no BEC signal
  • detectors.sender_graph.enabled: false → no BEC signal regardless of history
  • upsertSenderGraph called after pipeline run (sender graph updated on every inbound)
  • Detector score bounded at +30 by construction (Math.min(30, result.score))

Acceptance shipped

  • ✅ Per-mailbox sender graph tracking display name + address + message count
  • Detector interface for pluggable future detectors
  • SenderGraphDetector BEC signal
  • ✅ Per-mailbox enable/disable (detectors.sender_graph.enabled)
  • ✅ Bounded contribution (+30 max)
  • ✅ BEC scenario: impersonation flagged, fresh mailbox not flagged, disabling returns to baseline

Acceptance deferred

  • UI toggle in Settings → Security for the detectors.sender_graph.enabled knob (the setting is writable via the settings API; a dedicated UI surface is a follow-up)
  • v2 trainable classifiers and embedding-based writing-style detection (as noted in issue Per-tenant pluggable detectors via DO compute #26 v2 section)

Spec follow-up needed

No — this feature adds a new scoring component and does not change or contradict any existing rule in SECURITY_SPEC.md.

https://claude.ai/code/session_01BDrRMH9q5V7G3V1ruLns6J


Generated by Claude Code

Adds a `sender_graph` table to the per-mailbox SQLite DO tracking
(display_name, sender_address) pairs. The `SenderGraphDetector` flags
BEC-style impersonation when a new address claims a display name already
seen from different addresses in that mailbox, scoring +10–25 (capped at
+30). The boost is applied as a post-aggregation step in the verdict stage
alongside the existing intel-feed and off-hours boosts.

Per-mailbox `detectors.sender_graph.enabled` setting (default: true)
lets operators disable the signal. Fresh mailboxes produce 0 contribution
until sender history accumulates, so there are no false positives on
first use.

https://claude.ai/code/session_01BDrRMH9q5V7G3V1ruLns6J
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ais-hub 4ffc977 Commit Preview URL

Branch Preview URL
May 19 2026, 12:27 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Per-tenant pluggable detectors via DO compute

2 participants