VC005A08:2021·CWE-345

Unprotected Stripe Webhook Endpoint

Stripe webhook endpoints that act on events without verifying Stripe's signature. Anyone who finds the URL can post a forged payment event.

What this rule detects

VC005 looks at Stripe webhook handlers (a file under a webhooks/stripe path, or code that mentions Stripe and handles events such as checkout.session.completed, invoice.paid, payment_intent or customer.subscription) and flags the POST handler or event-type check when the file never calls `stripe.webhooks.constructEvent` and never references the `stripe-signature` header or a webhook signing secret.

Vulnerable vs. safe code

Vulnerable
// app/api/webhooks/stripe/route.ts
// Trusts whatever JSON arrives. Anyone who finds this URL can post
// a fake "checkout.session.completed" and get paid access.
export async function POST(req: Request) {
  const event = await req.json();
  if (event.type === "checkout.session.completed") {
    await grantAccess(event.data.object.customer);
  }
  return new Response("ok");
}
Safe
// app/api/webhooks/stripe/route.ts
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(req: Request) {
  let event: Stripe.Event;
  try {
    // Throws unless the payload was signed with your webhook secret.
    event = stripe.webhooks.constructEvent(
      await req.text(),
      req.headers.get("stripe-signature")!,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch {
    return new Response("Invalid signature", { status: 400 });
  }
  if (event.type === "checkout.session.completed") {
    await grantAccess(event.data.object.customer);
  }
  return new Response("ok");
}

About A08:2021 — Software & Data Integrity

Integrity failures happen when an app trusts data or code it shouldn't — running unsigned updates, deserializing untrusted JSON into native objects, pulling code from a CDN without subresource integrity. The SolarWinds breach was a software-integrity failure on a national scale.

Impact: Insecure deserialization can mean remote code execution: the attacker sends a crafted payload that, when deserialized, instantiates dangerous classes or triggers method calls. Missing subresource integrity means a CDN compromise becomes your compromise.

How to fix it: Don't deserialize untrusted input into native objects — use plain JSON parsing and validate the shape. Add subresource integrity hashes to third-party scripts. Sign software updates and verify signatures before applying. Prefer signed-commits and pinned versions in dependency management.

Common patterns in this category:

  • `JSON.parse` followed by direct property access without schema validation
  • Native deserialization (e.g. node-serialize, pickle) on user input
  • `<script src="https://cdn...">` without `integrity=` attribute
  • Auto-update mechanisms that don't verify package signatures
  • CI/CD pipelines that pull from un-pinned tags

Framework mapping

Findings from this rule map to the following framework controls. This is an informational mapping, not an audit, certification, or attestation.

SOC 2
CC6.1, CC6.6
ISO 27001
A.8.26, A.8.28
OWASP Top 10
A08:2021 — Software & Data Integrity
CWE
CWE-345

See the full compliance coverage page for how every rule maps to OWASP Top 10 and CWE, and which rules also carry informational SOC 2 and ISO 27001 cross-references.

Scan your code for VC005

Free, no signup: paste code or upload a file, or run npx xploitscan@latest scan . The free scan runs 30 core rules; paid plans run all 223.

Scan Your Code →

Related rules in A08:2021