fix(emails): BCC scrape-alert recipients — never a shared cross-tenant To: line#758
fix(emails): BCC scrape-alert recipients — never a shared cross-tenant To: line#758sweetmantech wants to merge 1 commit into
Conversation
…t To: line sendApifyWebhookEmail put every watcher of a social (resolved across all customer accounts) into one visible To: header, disclosing customer identities and monitoring relationships to each other (observed live: a manager, an internal account, and a label contact in one To: line). Hard-coded: to is always ourselves, recipients ride bcc; a unit test asserts to/cc never carry more than our own address (recoupable/chat#1855 PR #1 of 6). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Warning Review limit reached
Next review available in: 27 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Caller as Apify Webhook
participant Handler as sendApifyWebhookEmail
participant Wrapper as sendEmailWithResend
participant Resend as Resend API
Note over Caller,Handler: Privacy boundary: watchers from different tenants
Caller->>Handler: sendApifyWebhookEmail(profile, emails)
alt emails is empty
Handler-->>Caller: return null (no email sent)
else emails non-empty
Handler->>Handler: generate email body from profile
Note over Handler: To: always our own address<br/>BCC: all recipients (cross-tenant safe)
Handler->>Wrapper: sendEmailWithResend({ to: [RECOUP_FROM_EMAIL], bcc: emails, ... })
Wrapper->>Resend: POST /emails (to=bcc set)
Resend-->>Wrapper: success response
Wrapper-->>Handler: result (e.g., { id })
Handler-->>Caller: return result
end
Auto-approved: Fixes email privacy by moving all recipients to BCC; adds tests for the new behavior. Small, isolated change with low risk.
Re-trigger cubic
Summary
The "{artist} has new posts on Instagram" alert resolved every watcher of a social across all customer accounts into a single visible
To:line — live evidence on the tracking issue shows a customer manager, an internal account, and a label contact (sam.palm@wmg.com) all mutually visible on one send. This PR hard-codes the privacy boundary:tois always our own from-address (Resend requires non-emptyto), all recipients ridebcc.Tracking issue: recoupable/chat#1855 (PR #1 of 6 — ships first and alone; nothing gates it).
What changed
lib/apify/sendApifyWebhookEmail.ts:to: [RECOUP_FROM_EMAIL]+bcc: emails(the Resend wrapper already passesbccthrough natively — no wrapper change).lib/apify/__tests__/sendApifyWebhookEmail.test.ts(new): asserts recipients land inbcc, and a guard-rail test thatto/ccnever contain more than our own address regardless of recipient count — so a future platform copy-paste can't reintroduce the leak.Tests
RED→GREEN: 2 new assertions failed against the old implementation (
to: emails), pass after (3/3). eslint clean.🤖 Generated with Claude Code
Summary by cubic
Fixes a privacy leak in Instagram scrape-alert emails by moving all recipients to BCC and setting To to our own sender address. Prevents cross-tenant addresses from being visible to each other (recoupable/chat#1855).
sendApifyWebhookEmailto useto: [RECOUP_FROM_EMAIL]andbcc: emails.to/cclimited to our address, and no send when recipient list is empty.Written for commit f178c94. Summary will update on new commits.