Lesson 14 of 15Security and Abuse Prevention

Security and Abuse Prevention

Notification systems touch email addresses, phone numbers, device tokens, invoices, login alerts, and provider credentials. They also cost money. That makes them attractive to attackers.

Threats

Email spoofing
SMS OTP abuse
Provider API key leakage
Webhook forgery
Template injection
Notification spam
Sensitive data in logs
Open redirect deep links

API Authentication

Only trusted services should create notifications.

app.post("/notifications", authenticateServiceToken, async (req, res) => {
  await notificationService.create(req.body);
  res.status(202).json({ accepted: true });
});

Use service-to-service auth, scoped API keys, or mTLS depending on the environment. Do not expose a general send endpoint to browsers.

Rate Limiting

Rate limit expensive or sensitive operations.

OTP by phone: 3 / 10 minutes
OTP by IP: 20 / hour
SMS by tenant: budget limit / day
Email by user: product activity digest limits

Rate limits should be visible in monitoring. Silent drops are hard to debug.

Secret Management

Provider keys should live in a secrets manager or secure environment variables. Rotate keys. Restrict permissions. Separate staging and production provider accounts.

Never log provider secrets or full authorization headers.

Webhook Validation

Providers send delivery events. Attackers can fake webhooks unless you verify signatures.

function verifyProviderWebhook(rawBody: string, signature: string) {
  const expected = createHmac("sha256", process.env.PROVIDER_WEBHOOK_SECRET!)
    .update(rawBody)
    .digest("hex");

  return timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Use the raw request body. Parsing and re-stringifying JSON can change the bytes and break verification.

Email Spoofing

Configure:

SPF: which servers can send mail
DKIM: cryptographic signature
DMARC: policy for failed checks

Without these, attackers can impersonate your domain more easily, and providers may mark legitimate mail as suspicious.

Template Injection

Escape variables. Do not allow arbitrary HTML from user input in templates.

const safeName = escapeHtml(user.name);

If a notification includes a user comment, render it as text, not trusted HTML.

Signed URLs

Invoices, exports, and private files should use expiring signed URLs.

https://cdn.example.com/invoices/inv_123.pdf?signature=...&expires=...

Do not put permanent private file URLs in emails.

Notifications often move sensitive data outside your app. Design them with the same care as APIs.

Common Mistakes

  1. Exposing notification creation to untrusted clients.
  2. Not verifying provider webhooks.
  3. Storing raw OTPs or secrets in logs.
  4. Including sensitive data in push payloads.
  5. Sending private files through permanent URLs.

Interview Questions

  1. How do you prevent SMS OTP abuse?
  2. Why must webhook signatures use the raw body?
  3. What do SPF, DKIM, and DMARC do?
  4. What data should not be included in push payloads?

Exercise

Write a security checklist for a password reset notification flow, including rate limits, token expiry, email content, and logging rules.

What you will learn

How attackers abuse notification systems.

How to protect provider credentials and webhooks.

How rate limits reduce SMS and OTP fraud.

How email spoofing and signed URLs are handled.

Production checklist

  • API access is authenticated
  • Secrets are stored securely
  • Provider webhooks are verified
  • Rate limits exist
  • PII is minimized
  • Signed URLs expire
Security and Abuse Prevention - Production Notification System Design | Niraj Kumar