external-integration-patterns
Provides patterns for reliable integration with external services like Stripe and Sendgrid, ensuring observability and error handling.
Install this skill
Security score
The external-integration-patterns skill was audited on Feb 9, 2026 and we found 36 security issues across 4 threat categories. Review the findings below before installing.
Categories Tested
Security Issues
Template literal with variable interpolation in command context
| 39 | throw new Error(`Missing required env var: ${key}`); |
Template literal with variable interpolation in command context
| 42 | throw new Error(`${key} has trailing whitespace — check dashboard for invisible characters`); |
Template literal with variable interpolation in command context
| 252 | ```bash |
Curl to non-GitHub URL
| 272 | HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api/health) |
Webhook reference - potential data exfiltration
| 14 | - File path contains `webhook`, `api/`, `services/` |
Webhook reference - potential data exfiltration
| 18 | - Reviewing webhook handlers |
Webhook reference - potential data exfiltration
| 24 | Silent failures are the worst failures. When Stripe doesn't deliver a webhook, when Clerk JWT validation fails, when Sendgrid rejects an email — you need to know immediately, not when a user complains |
Webhook reference - potential data exfiltration
| 34 | const REQUIRED = ['SERVICE_API_KEY', 'SERVICE_WEBHOOK_SECRET']; |
Webhook reference - potential data exfiltration
| 120 | ### 4. Webhook Reliability |
Webhook reference - potential data exfiltration
| 122 | Webhooks are inherently unreliable. Build for this reality. |
Webhook reference - potential data exfiltration
| 125 | export async function handleWebhook(req: Request) { |
Webhook reference - potential data exfiltration
| 132 | event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!); |
Webhook reference - potential data exfiltration
| 136 | source: 'webhook', |
Webhook reference - potential data exfiltration
| 147 | source: 'webhook', |
Webhook reference - potential data exfiltration
| 155 | await db.insert(webhookEvents).values({ |
Webhook reference - potential data exfiltration
| 173 | Don't rely 100% on webhooks. Periodically sync state as a backup. |
Webhook reference - potential data exfiltration
| 204 | Don't wait for webhook to grant access. Verify payment immediately after redirect. |
Webhook reference - potential data exfiltration
| 219 | // Webhook will come later as backup |
Webhook reference - potential data exfiltration
| 234 | ### Webhook Configuration |
Webhook reference - potential data exfiltration
| 235 | - [ ] Webhook URL uses canonical domain (no redirects) |
Webhook reference - potential data exfiltration
| 260 | for var in ${SERVICE}_API_KEY ${SERVICE}_WEBHOOK_SECRET; do |
Webhook reference - potential data exfiltration
| 290 | // ❌ BAD: Trusting webhook without verification |
Webhook reference - potential data exfiltration
| 293 | // ❌ BAD: 100% reliance on webhooks |
Webhook reference - potential data exfiltration
| 294 | // If webhook fails, user never gets access |
Webhook reference - potential data exfiltration
| 303 | - Use `stripe.webhooks.constructEvent()` for signature verification |
Webhook reference - potential data exfiltration
| 304 | - Check Stripe Dashboard > Developers > Webhooks for delivery logs |
Webhook reference - potential data exfiltration
| 308 | - `CONVEX_WEBHOOK_TOKEN` must match exactly between Clerk and Convex |
Webhook reference - potential data exfiltration
| 310 | - Webhook URL must not redirect |
Webhook reference - potential data exfiltration
| 314 | - Inbound parse webhooks need signature verification |
Access to .env file
| 37 | const value = process.env[key]; |
Access to .env file
| 47 | export const apiKey = process.env.SERVICE_API_KEY!; |
Access to .env file
| 132 | event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!); |
Access to .env file
| 178 | const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); |
Access to .env file
| 229 | - [ ] All required vars in `.env.example` |
Access to .env file
| 285 | const apiKey = process.env.API_KEY || ''; |
External URL reference
| 272 | HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api/health) |