
Secure Checkout
- 69 installs
- 41 repo stars
- Updated March 13, 2026
- finsilabs/awesome-ecommerce-skills
Harden checkout with HTTPS enforcement, Content Security Policy headers, input sanitization, and card-data tokenization.
About
Secures the checkout flow through HTTPS enforcement, CSP headers, input sanitization, and card tokenization. A developer uses it to protect a checkout against common web and payment attacks.
- CSP headers and HTTPS enforcement on checkout
- Input sanitization and card-data tokenization
Secure Checkout by the numbers
- 69 all-time installs (skills.sh)
- Ranked #1,182 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill secure-checkoutAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 69 |
|---|---|
| repo stars | ★ 41 |
| Last updated | March 13, 2026 |
| Repository | finsilabs/awesome-ecommerce-skills ↗ |
What it does
Harden checkout with HTTPS enforcement, Content Security Policy headers, input sanitization, and card-data tokenization.
Files
Secure Checkout
Overview
Payment pages are the highest-value target for attackers — a single XSS vulnerability can lead to Magecart-style card skimming attacks that steal thousands of card numbers. Securing checkout requires enforcing TLS everywhere, implementing strict Content Security Policies (CSP) to prevent script injection, using payment tokenization to minimize PCI scope, and removing non-essential third-party scripts from payment pages. The good news: Shopify and BigCommerce handle most of this infrastructure automatically. WooCommerce merchants need to configure hosting and install security plugins. Custom storefronts require implementing all of these controls from scratch.
When to Use This Skill
- When building or auditing a checkout flow that accepts payment information
- When a penetration test or security scan surfaces XSS, CSP, or header vulnerabilities on payment pages
- When reviewing third-party script loading on pages that have access to payment form context
- When preparing for PCI DSS SAQ A-EP or SAQ D compliance assessment
- When migrating from a hosted payment page to a custom UI (increases PCI scope)
Core Instructions
Step 1: Understand your checkout security responsibility by platform
| Platform | HTTPS / TLS | CSP Headers | Payment Tokenization | Third-Party Script Control |
|---|---|---|---|---|
| Shopify | Automatic — Shopify provisions and renews SSL certificates | Shopify manages checkout CSP; your theme pages need review | Shopify Payments and all gateway integrations use tokenization | Use Shopify's Script Manager and Customer Events to control what loads on checkout |
| WooCommerce | Your hosting responsibility — install SSL from Let's Encrypt or your host | Your server responsibility — configure via hosting or plugin | Determined by your gateway choice (Stripe Elements = SAQ A-EP) | WordPress plugin and theme scripts load globally; use conditional loading to exclude checkout |
| BigCommerce | Automatic — BigCommerce provisions SSL and enforces HTTPS | BigCommerce manages checkout CSP for hosted checkout | Handled by your payment gateway choice through BigCommerce checkout | BigCommerce Script Manager controls third-party script placement |
| Custom / Headless | Your infrastructure responsibility | Your application responsibility — implement per-request CSP with nonces | Implement with Stripe Elements or Braintree Drop-in UI | Full control and full responsibility — must implement explicitly |
Step 2: Platform-specific checkout security setup
---
Shopify
Shopify's hosted checkout is one of the most secure available — it runs on Shopify's own domain (checkout.shopify.com or your custom domain with SSL), uses Shopify Payments tokenization, and is protected by Shopify's CDN and WAF.
HTTPS enforcement:
- Shopify automatically provisions free SSL certificates for all stores and custom domains
- Go to Online Store → Domains to verify SSL is active on your custom domain
- Enable Redirect all traffic to HTTPS under Online Store → Preferences → Checkout and accounts
Third-party scripts on checkout: Shopify's checkout extension model (Checkout Extensibility) limits what can run on the checkout page — this is by design for PCI compliance.
1. Go to Settings → Customer events to manage tracking pixels and scripts 2. Scripts added via Customer Events run in a sandboxed context and cannot access payment data 3. Do not inject JavaScript into the checkout page via theme code or ScriptTag API — this is prohibited for SAQ A compliance and may be blocked by Shopify
Theme security review: 1. Go to Online Store → Themes → Edit code 2. Search your theme for any references to document.cookie, localStorage, or fetch on cart/checkout pages — these are red flags if you did not add them intentionally 3. Review installed apps: go to Settings → Apps and sales channels and remove apps you no longer use; each installed app can inject scripts into your storefront
Admin account security (reduces attack surface): 1. Go to Settings → Users and permissions 2. Require 2FA for all staff accounts — a compromised admin account is the most common way attackers modify checkout behavior 3. Limit staff access to only the permissions needed for their role
---
WooCommerce
WooCommerce checkout security depends almost entirely on your hosting configuration and payment gateway. Your hosting provider is responsible for TLS, and the gateway you choose determines whether card data ever touches your server.
Step 1 — Force HTTPS on your store: 1. In your WordPress hosting control panel (cPanel, Kinsta, WP Engine), enable free SSL via Let's Encrypt or your host's built-in certificate 2. Install Really Simple SSL (free plugin) — it forces HTTPS sitewide, updates internal links, and fixes mixed content warnings in one step 3. After activating, verify at Settings → SSL that the redirect is active and no mixed content warnings appear
Step 2 — Choose a payment gateway that keeps card data off your server:
- Stripe (WooCommerce Stripe Payment Gateway) — uses Stripe Elements; card data entered in a Stripe iframe never touches your server (SAQ A-EP)
- Stripe Checkout (redirect) — customer is redirected to Stripe's hosted page; even simpler (SAQ A)
- PayPal Standard — redirect to PayPal; SAQ A
- Avoid any gateway that requires your server to receive raw card numbers
Step 3 — Install security plugins: 1. Install Wordfence Security (free): go to Wordfence → Firewall and set protection level to "Extended Protection" — this adds a WAF rule at the WordPress application layer 2. Install WP Activity Log (~$99/year) or Simple History (free): logs all admin actions including order edits, plugin installs, and setting changes 3. Go to Settings → Discussion — disable comments on checkout/cart pages if enabled (reduces XSS attack surface)
Step 4 — Remove scripts from checkout pages: WooCommerce loads all active plugins on every page by default. Use Asset CleanUp Pro ($25 one-time) or add conditional PHP to prevent non-essential scripts from loading on checkout:
Go to WooCommerce → Settings → Advanced and verify:
- Debug logging is off (
WP_DEBUGmust befalseinwp-config.phpin production) - No custom code logs order data or payment details
Step 5 — Configure SSL security headers via hosting or plugin: 1. If using Nginx hosting (Kinsta, WP Engine, Nexcess), ask your host to add HSTS and X-Frame-Options headers — these are commonly pre-configured on managed WordPress hosts 2. Alternatively, install HTTP Headers (free plugin) to add security headers via WordPress without editing server config
---
BigCommerce
BigCommerce's hosted checkout is PCI-DSS Level 1 certified and handles TLS, CSP, and payment tokenization automatically when you use a supported gateway.
HTTPS enforcement:
- BigCommerce automatically provisions and renews SSL for all stores
- Go to Store Setup → Store Settings → Security — verify Force secure checkout is enabled
- Go to Storefront → SSL Certificate to confirm your custom domain has SSL active
Controlling third-party scripts: 1. Go to Storefront → Script Manager 2. Review all installed scripts — for each script, check the Placement setting 3. For scripts that do not need to run on checkout (analytics, advertising, chat), set Placement to exclude checkout pages 4. Scripts in Script Manager run in the storefront context; BigCommerce's checkout itself is protected by a separate, more restrictive CSP
Checkout payment security:
- BigCommerce Payments and certified payment gateways (Stripe, Braintree, PayPal) use tokenization — card data never touches BigCommerce's or your application servers
- Go to Store Setup → Payments and review your active gateway — ensure you are not using a gateway that uses "direct post" to your server
Admin account security: 1. Go to Account Settings → Users 2. Review all user accounts — remove former employees and contractors 3. Ensure all active accounts have 2FA enabled under their individual account security settings 4. Go to Settings → Advanced Settings → API Accounts — review OAuth credentials; revoke any unused API tokens
---
Custom / Headless
For custom storefronts, you implement all checkout security controls. The three most critical are: payment tokenization (so your server never sees card numbers), strict CSP on payment pages (to prevent Magecart injection), and HTTPS with security headers.
Payment tokenization with Stripe Elements (SAQ A-EP):
// Client-side: Stripe handles card data in an iframe — your code never sees card numbers
const stripe = await loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);
const elements = stripe.elements({ clientSecret });
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
// On submit: Stripe handles card capture; your server receives only a paymentIntentId
const { error, paymentIntent } = await stripe.confirmPayment({
elements,
confirmParams: { return_url: `${window.location.origin}/order-confirmation` },
});
// Your server confirms via paymentIntentId — never a card numberHTTPS and security headers (Next.js example):
// next.config.ts
export default {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=(), payment=()' },
],
},
{
// No caching on checkout; no indexing by search engines
source: '/checkout(.*)',
headers: [
{ key: 'Cache-Control', value: 'no-store, no-cache, must-revalidate' },
{ key: 'X-Robots-Tag', value: 'noindex' },
],
},
];
},
};Content Security Policy with per-request nonces (prevents Magecart):
// middleware.ts — generate a new nonce per request; static nonces can be bypassed
export function middleware(request: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString('base64');
const csp = [
`default-src 'self'`,
`script-src 'self' 'nonce-${nonce}' https://js.stripe.com`,
`style-src 'self' 'nonce-${nonce}'`,
`frame-src https://js.stripe.com https://hooks.stripe.com`,
`connect-src 'self' https://api.stripe.com`,
`img-src 'self' data: https:`,
`object-src 'none'`,
`base-uri 'self'`,
`form-action 'self'`,
`upgrade-insecure-requests`,
`report-uri /api/csp-report`,
].join('; ');
const response = NextResponse.next();
response.headers.set('Content-Security-Policy', csp);
response.headers.set('x-nonce', nonce); // Pass to layout for script nonce attributes
return response;
}CSP violation monitoring:
// app/api/csp-report/route.ts — log violations; alert on checkout page violations
export async function POST(req: NextRequest) {
const body = await req.json();
const violation = body['csp-report'];
await logger.warn('CSP Violation', {
documentUri: violation['document-uri'],
violatedDirective: violation['violated-directive'],
blockedUri: violation['blocked-uri'],
});
// A CSP violation on a payment page may indicate an active Magecart attack
if (violation['document-uri']?.includes('/checkout')) {
await alertSecurityTeam('CSP violation on checkout page', violation);
}
return new NextResponse(null, { status: 204 });
}Server-side input validation with Zod:
import { z } from 'zod';
const checkoutSchema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(200).regex(/^[\p{L}\p{M}\s\-'.]+$/u),
address: z.string().min(1).max(500),
city: z.string().min(1).max(100),
postalCode: z.string().min(1).max(20),
country: z.string().length(2), // ISO 3166-1 alpha-2
});
export async function POST(req: NextRequest) {
const body = await req.json();
const result = checkoutSchema.safeParse(body);
if (!result.success) {
return NextResponse.json({ errors: result.error.flatten() }, { status: 400 });
}
// Proceed with validated data only
}Best Practices
- Treat checkout as a separate security zone — apply the most restrictive CSP, disable all non-essential third-party scripts, and treat any CSP violation on a payment page as a potential Magecart incident
- Never inline JavaScript on payment pages — use nonce-based CSP and external scripts; adding
'unsafe-inline'toscript-srcdefeats the entire purpose of CSP - Remove non-essential apps and plugins — every installed Shopify app, WordPress plugin, or BigCommerce script is a potential attack surface; remove anything your store does not actively use
- Add Subresource Integrity (SRI) to CDN scripts — SRI ensures the script content has not been tampered with even if the CDN is compromised; generate with
openssl dgst -sha256 -binary script.js | openssl base64 - Enable WAF protection at the edge — Cloudflare WAF (free plan) or your hosting provider's WAF blocks OWASP Top 10 attacks before they reach your application
- Scan dependencies for vulnerabilities in CI — run
npm auditand use Snyk or Dependabot; a compromised npm package in your checkout bundle is as dangerous as a Magecart injection
Common Pitfalls
| Problem | Solution |
|---|---|
| CSP breaks Stripe Elements iframes | Add https://js.stripe.com and https://hooks.stripe.com to frame-src; check Stripe's CSP documentation for the current complete allowlist |
'unsafe-inline' added to unblock styles | Use nonces for inline styles instead; 'unsafe-inline' invalidates CSP protection for that directive entirely |
| TLS certificate expired | Use Let's Encrypt with auto-renewal (Certbot) or a managed certificate from your CDN; Shopify and BigCommerce auto-renew — only WooCommerce/custom stores require manual renewal |
| Analytics scripts loading on checkout pages | Add a conditional check in your analytics initialization that skips loading on /checkout routes; on Shopify use Customer Events placement settings |
| Third-party chat widget with access to payment fields | Remove chat widgets from checkout pages entirely; no legitimate support use case requires reading payment form values |
Related Skills
- @fraud-detection
- @account-security
- @bot-protection
- @pci-dss-compliance
- @gdpr-ecommerce
{
"context": "Tests whether the agent avoids collecting raw card data by using Stripe Elements, sanitizes HTML rendered from external sources using DOMPurify with an allowlist, validates server-side checkout form submissions using zod, and avoids dangerous patterns like logging card details or storing CVV.",
"type": "weighted_checklist",
"checklist": [
{
"name": "No raw card input fields",
"max_score": 10,
"description": "The checkout form does NOT use <input> elements to collect card numbers, expiry, or CVV directly — delegates to Stripe Elements or equivalent iframe-based approach"
},
{
"name": "Stripe Elements pattern",
"max_score": 10,
"description": "Uses Stripe Elements (loadStripe, elements.create, cardElement.mount) to collect card data, resulting in a paymentMethodId token sent to the server instead of card details"
},
{
"name": "No card data logged",
"max_score": 8,
"description": "Code does NOT log or print card numbers, CVV, or full payment method details anywhere (no console.log, logger calls with card fields)"
},
{
"name": "No CVV storage",
"max_score": 8,
"description": "Code does NOT store CVV/CVC in a database, session, or any persistent store"
},
{
"name": "DOMPurify for HTML content",
"max_score": 10,
"description": "HTML content from the CMS/database is sanitized using DOMPurify (isomorphic-dompurify) before rendering, rather than using dangerouslySetInnerHTML unsanitized"
},
{
"name": "DOMPurify ALLOWED_TAGS",
"max_score": 8,
"description": "DOMPurify.sanitize() is called with an explicit ALLOWED_TAGS array limiting permitted HTML elements (e.g., p, b, i, em, strong, ul, ol, li, br)"
},
{
"name": "DOMPurify ALLOWED_ATTR empty",
"max_score": 8,
"description": "DOMPurify.sanitize() is called with ALLOWED_ATTR: [] (or equivalent) to strip all HTML attributes"
},
{
"name": "Zod server-side validation",
"max_score": 10,
"description": "The checkout API route validates the request body using a zod schema (z.object with field definitions) rather than manual checks or no validation"
},
{
"name": "Zod email field",
"max_score": 6,
"description": "Zod schema includes email field validated with z.string().email() and a max length constraint"
},
{
"name": "Zod name regex",
"max_score": 6,
"description": "Zod schema validates the name field with a regex that restricts to valid name characters (letters, spaces, hyphens, apostrophes)"
},
{
"name": "Zod country ISO code",
"max_score": 6,
"description": "Zod schema validates country as exactly 2 characters (ISO 3166-1 alpha-2)"
},
{
"name": "JSX for dynamic content",
"max_score": 10,
"description": "Dynamic user-supplied content is rendered through JSX (e.g., {variable}) rather than string template literals interpolated into HTML"
}
]
}
Payment Checkout Page with Product Descriptions
Problem/Feature Description
A growing online retailer wants to build a custom checkout experience in Next.js. The checkout page must display rich product descriptions fetched from their headless CMS — these descriptions contain basic HTML formatting (bold, italics, lists) written by the marketing team, but the CMS system doesn't sanitize content before storing it.
The page needs to collect payment from customers. The company has a Stripe account and wants to integrate payments directly on their own domain to provide a seamless branded experience, rather than redirecting customers to an external payment portal. The engineering lead has emphasized that the company does not want to become responsible for storing or handling raw card numbers — this would significantly increase their compliance burden.
Your task is to implement the core checkout page and its supporting API route. The implementation should display the product information safely, handle payment collection in a way that keeps card data off the company's servers, and robustly validate all the billing information submitted with the order.
Output Specification
Produce the following files:
app/checkout/page.tsx— the checkout page component, showing the product and the payment formapp/api/checkout/route.ts— the Next.js API route that receives and validates the billing details and processes the order (useprocess.env.STRIPE_SECRET_KEYfor the server-side Stripe key)lib/sanitize.ts— a utility for safely rendering HTML content from external sources
The Stripe publishable key is available as process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY.
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/product.json =============== { "id": "prod_001", "name": "Artisan Leather Wallet", "price_cents": 7999, "descriptionHtml": "<p>Handcrafted from <strong>full-grain leather</strong> with <em>RFID blocking</em> technology.</p><ul><li>6 card slots</li><li>2 bill compartments</li></ul><script>alert('xss')</script><p>Made in <a href='javascript:void(0)' onclick='stealData()'>Italy</a>.</p>" }
{
"context": "Tests whether the agent correctly configures HTTP security headers and a nonce-based Content Security Policy for a Next.js e-commerce application, including HSTS with the right parameters, checkout-specific headers, and a strict CSP generated in middleware.",
"type": "weighted_checklist",
"checklist": [
{
"name": "HSTS max-age value",
"max_score": 7,
"description": "Strict-Transport-Security header has max-age=63072000 (exactly 2 years, not a shorter value like 31536000)"
},
{
"name": "HSTS includeSubDomains",
"max_score": 4,
"description": "Strict-Transport-Security header includes the includeSubDomains directive"
},
{
"name": "HSTS preload",
"max_score": 5,
"description": "Strict-Transport-Security header includes the preload directive"
},
{
"name": "X-Frame-Options DENY",
"max_score": 4,
"description": "X-Frame-Options header is set to DENY (not SAMEORIGIN)"
},
{
"name": "X-Content-Type-Options",
"max_score": 4,
"description": "X-Content-Type-Options header is set to nosniff"
},
{
"name": "Referrer-Policy value",
"max_score": 4,
"description": "Referrer-Policy header is set to strict-origin-when-cross-origin"
},
{
"name": "Permissions-Policy camera/mic/geo",
"max_score": 4,
"description": "Permissions-Policy header disables camera=(), microphone=(), and geolocation=()"
},
{
"name": "Global headers route pattern",
"max_score": 4,
"description": "Security headers are applied to all routes using source: '/(.*)' in next.config.ts"
},
{
"name": "Checkout Cache-Control",
"max_score": 8,
"description": "Checkout routes have Cache-Control set to no-store, no-cache, must-revalidate"
},
{
"name": "Checkout X-Robots-Tag",
"max_score": 4,
"description": "Checkout routes have X-Robots-Tag set to noindex"
},
{
"name": "Nonce per request",
"max_score": 8,
"description": "CSP nonce is generated uniquely per request in middleware (e.g., using crypto.randomUUID() encoded as base64), not statically"
},
{
"name": "CSP in middleware",
"max_score": 8,
"description": "Content-Security-Policy header is set inside Next.js middleware (not statically in next.config.ts)"
},
{
"name": "CSP nonce in script-src",
"max_score": 8,
"description": "CSP script-src directive includes the nonce value (nonce-${nonce}) rather than 'unsafe-inline'"
},
{
"name": "CSP no unsafe-inline in script-src",
"max_score": 8,
"description": "CSP script-src does NOT contain 'unsafe-inline'"
},
{
"name": "CSP Stripe frame-src",
"max_score": 8,
"description": "CSP frame-src includes both https://js.stripe.com and https://hooks.stripe.com"
},
{
"name": "CSP object-src none",
"max_score": 4,
"description": "CSP includes object-src 'none'"
},
{
"name": "CSP base-uri self",
"max_score": 4,
"description": "CSP includes base-uri 'self'"
},
{
"name": "unsafe-eval dev-only",
"max_score": 4,
"description": "CSP 'unsafe-eval' is only included in development (gated on NODE_ENV check), not hardcoded unconditionally"
}
]
}
Secure Headers and CSP for Next.js Checkout
Problem/Feature Description
Your team has just completed a penetration test of your Next.js e-commerce application. The report flagged that the payment and checkout pages are missing critical HTTP response headers and have no Content Security Policy. The security team is particularly worried about Magecart-style attacks — malicious JavaScript injected into the page that silently exfiltrates card numbers as customers type them. Several competitors in your space have suffered these attacks in the past year.
The application currently has a /checkout route group and a standard next.config.ts, but no security hardening has been done. Your task is to implement the full set of recommended HTTP security headers globally across the app, add extra restrictive headers for the checkout route specifically, and implement a per-request nonce-based Content Security Policy applied through Next.js middleware.
Output Specification
Produce a self-contained implementation with the following files:
next.config.ts— with global security headers defined for all routes and extra headers specifically for checkout pagesmiddleware.ts— Next.js middleware that generates and applies the Content Security Policy header per requestlib/csp.ts— the CSP generation function that accepts a nonce and returns the full policy string
The Stripe payment integration is already handled elsewhere; make sure your CSP is compatible with Stripe Elements (both the script loading and the iframe widgets).
For the nonce, the middleware should also forward it downstream so that layout components can use it on script tags.
Do not produce any other application files — focus only on the security infrastructure files listed above.
{
"context": "Tests whether the agent removes non-essential third-party scripts from the checkout layout, adds Subresource Integrity (SRI) hashes to CDN-loaded scripts, loads Stripe.js from CDN rather than bundling it, and implements a CSP violation reporting API endpoint that detects and alerts on checkout-page violations.",
"type": "weighted_checklist",
"checklist": [
{
"name": "No analytics in checkout layout",
"max_score": 10,
"description": "The checkout layout file does NOT load any analytics scripts (e.g., Google Analytics, Segment, Mixpanel) — either they are absent or explicitly excluded"
},
{
"name": "No advertising/chat scripts",
"max_score": 8,
"description": "The checkout layout does NOT load advertising tags, chat widgets, or other non-payment third-party scripts"
},
{
"name": "Stripe.js from CDN",
"max_score": 10,
"description": "Stripe.js is loaded from https://js.stripe.com/v3/ via a <script> tag (or equivalent), NOT imported/bundled via npm package"
},
{
"name": "SRI integrity attribute",
"max_score": 10,
"description": "The Stripe.js <script> tag (or any other CDN-loaded script in checkout) includes an integrity attribute with a SHA hash value"
},
{
"name": "SRI crossOrigin attribute",
"max_score": 8,
"description": "The CDN script tag with integrity also sets crossOrigin=\"anonymous\""
},
{
"name": "CSP report-uri in policy",
"max_score": 10,
"description": "The Content-Security-Policy header includes a report-uri directive pointing to a local reporting endpoint (e.g., /api/csp-report)"
},
{
"name": "Reporting endpoint exists",
"max_score": 8,
"description": "An API route file exists that handles POST requests to receive CSP violation reports"
},
{
"name": "Violation logging",
"max_score": 8,
"description": "The CSP reporting endpoint logs the violation details (violated-directive, blocked-uri, document-uri, source-file)"
},
{
"name": "Checkout violation alerting",
"max_score": 12,
"description": "The CSP reporting endpoint specifically detects violations from checkout pages (checks document-uri for '/checkout') and triggers a special alert or warning"
},
{
"name": "Reporting endpoint returns 204",
"max_score": 8,
"description": "The CSP reporting endpoint returns an HTTP 204 No Content response (not 200 with a body)"
},
{
"name": "Conditional third-party loading",
"max_score": 8,
"description": "Any third-party scripts that exist on the main site (outside checkout) include a conditional check or are placed in a non-checkout layout so they do not appear on /checkout routes"
}
]
}
Checkout Security Hardening: Script Isolation and Monitoring
Problem/Feature Description
Your company runs a Next.js storefront that recently added Google Analytics, a live chat widget, and a few marketing pixels to drive conversion tracking and customer support. These scripts load on every page, including the new checkout flow. A security review flagged that having third-party JavaScript on payment pages is a significant supply chain risk — if any of those vendors were ever compromised, attackers could harvest customer card data in real time.
The security team wants two things done: first, isolate the checkout pages so that no non-essential third-party scripts run there at all; second, add active monitoring so the team is notified immediately if something suspicious attempts to load on a checkout page. The payment flow already uses Stripe Elements for card collection. The team also wants to ensure that the Stripe.js library itself is loaded in a tamper-evident way.
Your task is to implement the checkout layout that enforces script isolation, configure the CSP to enable violation reporting, and build the reporting endpoint that the browser will call when a violation is detected.
Output Specification
Produce the following files:
app/checkout/layout.tsx— the checkout-specific layout that loads only essential scripts (Stripe.js) and excludes all non-payment third partiesapp/api/csp-report/route.ts— the CSP violation reporting API endpointmiddleware.ts— updated middleware that includes the CSP reporting directive in the policy
A simplified version of the existing root layout that loads analytics is provided below — use it to understand what scripts are currently loading site-wide.
Input Files
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/app/layout.tsx =============== import Script from 'next/script';
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> {/ Google Analytics /} <Script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX" strategy="afterInteractive" /> <Script id="google-analytics" strategy="afterInteractive"> { window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXXX'); } </Script> {/ Live chat widget /} <Script src="https://cdn.livechat.com/widget.js" strategy="lazyOnload" /> {/ Facebook Pixel /} <Script id="facebook-pixel" strategy="afterInteractive"> { !function(f,b,e,v,n,t,s){...}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '123456789'); fbq('track', 'PageView'); } </Script> </head> <body>{children}</body> </html> ); }
{
"name": "finsi/secure-checkout",
"version": "0.1.0",
"summary": "TLS, CSP headers, tokenization, and XSS prevention for payment pages",
"skills": {
"secure-checkout": {
"path": "SKILL.md"
}
}
}