Agent Skills: Klaviyo Security Basics

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/klaviyo-security-basics

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/klaviyo-pack/skills/klaviyo-security-basics

Skill Files

Browse the full folder contents for klaviyo-security-basics.

Download Skill

Loading file tree…

plugins/saas-packs/klaviyo-pack/skills/klaviyo-security-basics/SKILL.md

Skill Metadata

Name
klaviyo-security-basics
Description
'Apply Klaviyo security best practices for API key management and access

Klaviyo Security Basics

Overview

Security best practices for Klaviyo: API key types, OAuth scopes, webhook HMAC-SHA256 signature verification, and secret rotation procedures.

Prerequisites

  • Klaviyo account with API key access
  • Understanding of environment variables and secret management
  • Access to Klaviyo dashboard (Settings > API Keys)

Instructions

Step 1: Understand Key Types

| Key Type | Format | Use Case | Sensitivity | |----------|--------|----------|-------------| | Private API Key | pk_* (40+ chars) | Server-side REST API | CRITICAL -- never expose client-side | | Public API Key | 6 alphanumeric chars | Client-side Track/Identify only | Low -- safe in browser JS |

Private keys authenticate via Authorization: Klaviyo-API-Key pk_*** header. Public keys pass as company_id query parameter.

Step 2: Store Keys in Environment Variables

Keep every private key and the webhook signing secret out of source: load them from .env (git-ignored) through a validated config loader that throws on a missing secret, so misconfiguration fails at boot instead of at first API call.

// src/config/klaviyo.ts -- validated config loader (skeleton)
export const klaviyoConfig = {
  privateKey: requireEnv('KLAVIYO_PRIVATE_KEY'),        // throws if absent
  publicKey: process.env.KLAVIYO_PUBLIC_KEY || '',
  webhookSecret: process.env.KLAVIYO_WEBHOOK_SIGNING_SECRET || '',
};

Full .env template, .gitignore entries, and the requireEnv helper: implementation.md → Environment Variable Configuration.

Step 3: Scope Keys per Environment (Least Privilege)

Issue a separate key for each environment with only the scopes that environment needs — read-only in dev and CI, full read/write in staging, the exact production scope set in prod — so a leaked key has the smallest possible blast radius. Scope table and per-environment env-var layout: implementation.md → Least-Privilege API Key Scopes.

Step 4: Verify Webhook Signatures (HMAC-SHA256)

Klaviyo signs each webhook payload with your signing secret. Recompute the HMAC-SHA256 digest over the raw body and compare with crypto.timingSafeEqual to defeat timing attacks; reject anything that does not match with 401.

const expected = crypto.createHmac('sha256', secret)
  .update(rawBody).digest('base64');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

Full verifier plus the Express raw-body middleware that returns 401 Invalid signature: implementation.md → Webhook Signature Verification and Express Webhook Middleware.

Step 5: Rotate Keys with Zero Downtime

Rotate private keys on a schedule (quarterly) or immediately on suspected leak: generate a replacement with identical scopes, deploy it to the secret store, verify with a curl against /api/accounts/, then revoke the old key and watch logs for 401s. Full five-step runbook with per-platform commands: implementation.md → API Key Rotation Procedure.

Security Checklist

  • [ ] Private API keys stored in environment variables / secret manager
  • [ ] .env files in .gitignore
  • [ ] Different API keys per environment (dev/staging/prod)
  • [ ] Minimal scopes per environment
  • [ ] Webhook signatures verified with HMAC-SHA256
  • [ ] API key rotation scheduled (quarterly recommended)
  • [ ] No private keys in client-side code
  • [ ] CI/CD uses read-only key for tests
  • [ ] Git history scanned for leaked keys (git log -p | grep pk_)

Error Handling

| Security Issue | Detection | Mitigation | |----------------|-----------|------------| | Leaked private key | Git scanning, trufflehog | Revoke immediately, rotate | | Excessive scopes | Scope audit | Reduce to minimum required | | Missing webhook verification | Code review | Add HMAC check | | Key not rotated | Age > 90 days | Schedule rotation | | 401s after rotation | Log monitoring | Verify all services updated |

Output

Applying this skill produces a hardened Klaviyo integration:

  • A git-ignored .env plus a src/config/klaviyo.ts loader that fails fast on a missing private key.
  • Environment-scoped API keys (dev/staging/prod/CI) each holding minimum scopes.
  • A webhook endpoint that returns 200 { "received": true } only for payloads whose HMAC-SHA256 signature verifies, and 401 { "error": "Invalid signature" } for everything else.
  • A documented, zero-downtime rotation runbook and a completed security checklist.

Examples

Three worked scenarios — validated config loader, rejecting a forged webhook, and zero-downtime key rotation — with inputs and expected results are in examples.md. Quick sketch of the webhook case:

POST /webhooks/klaviyo  (tampered body, original signature)
  → verifyKlaviyoWebhookSignature() recomputes HMAC → mismatch
  → 401 { "error": "Invalid signature" }, logged as rejected

See examples.md for the full walkthrough of each.

Resources

Next Steps

For production hardening beyond secrets — rate limits, monitoring, and deploy gates — see the klaviyo-prod-checklist skill in this pack.