Hardcoded service identifiers are scoped to config files
Why it matters
A Stripe price ID (price_1AbC...) hardcoded in an API route handler means the same literal string is duplicated across every checkout flow the AI generated. When the price changes — plan restructuring, annual pricing, regional variants — every scattered reference must be found and updated manually, with no guarantee they all match. CWE-798 applies because the same pattern that scatters price IDs also scatters webhook secrets (whsec_*), which must never appear as literals. OWASP A05 (Security Misconfiguration) covers the broader class: configuration that belongs in a single source of truth spread across the codebase is a maintenance and security misconfiguration by definition.
Severity rationale
Medium because scattered price IDs create update-coherence failures and mask webhook secret leaks — the business impact is pricing drift and potential secret exposure rather than immediate data breach.
Remediation
Centralize all Stripe identifiers in a single config file and import from there. Webhook secrets must always come from environment variables, never literals.
// lib/stripe.ts — single source of truth for all Stripe IDs
export const STRIPE_PRICE_IDS = {
pro_monthly: 'price_1AbCdEfGhIjKlMnOp',
pro_yearly: 'price_1XyZaBcDeFgHiJkLm',
} as const
export const STRIPE_PRODUCT_IDS = {
pro: 'prod_AbCdEfGhIjKlMn',
} as const
// src/app/api/checkout/route.ts
import { STRIPE_PRICE_IDS } from '@/lib/stripe'
const session = await stripe.checkout.sessions.create({
line_items: [{ price: STRIPE_PRICE_IDS.pro_monthly, quantity: 1 }],
})
For whsec_* values: remove the literal immediately and replace with process.env.STRIPE_WEBHOOK_SECRET. Webhook secrets in source code are a secret leak regardless of file location.
Detection
-
ID:
hardcoded-service-ids-scoped -
Severity:
medium -
What to look for: Walk source files for literal string matches against these service-identifier regex patterns:
arn:aws:[a-z0-9-]+:[a-z0-9-]*:[0-9]{12}:[\\w/-]+(AWS ARN),price_[A-Za-z0-9]{20,}(Stripe price ID),prod_[A-Za-z0-9]{14,}(Stripe product ID),whsec_[A-Za-z0-9]{20,}(Stripe webhook secret PREFIX — flag presence even if not literal secret),re_[A-Za-z0-9]{20,}(Resend API key prefix),ACa[a-f0-9]{32}(Twilio Account SID). For each occurrence, record the file path. Then check whether the file matches one of these allowlisted "config-style" filename patterns:(stripe|billing|plans|pricing|products|payments|subscriptions|tiers)\\.(ts|tsx|js|jsx|mjs|cjs)$,**/config/**,**/constants/**,**/lib/(stripe|billing|payments|aws)/**,*.example,*.test.*,*.spec.*,**/__tests__/**,**/__fixtures__/**. Count all hardcoded service IDs found, total in allowlisted config files, total scattered in non-config files. -
Pass criteria: 0 hardcoded service identifiers exist outside of allowlisted config-style files. Report: "X service IDs found, Y in config files, 0 scattered."
-
Fail criteria: At least 1 hardcoded service identifier appears in a non-config file (e.g., scattered across API route handlers, components, hooks).
-
Do NOT pass when: A
whsec_*(webhook secret) literal appears anywhere in source (even in config files) — webhook secrets must come from env vars, not literals. Flag separately with detail. -
Skip (N/A) when: Project has 0 hardcoded service identifiers at all.
-
Cross-reference: For comprehensive secret detection including AWS keys and API tokens, the Environment Security audit (
environment-security) covers credential hygiene. -
Detail on fail:
"2 scattered hardcoded service IDs: 'price_1AbC...' in src/app/api/checkout/route.ts (move to lib/stripe.ts), 'arn:aws:s3:::user-uploads' in src/components/Uploader.tsx (move to config/aws.ts)" -
Remediation: Hardcoded service identifiers scattered across handlers indicate the AI didn't centralize configuration — the same ID appears in 5 different files, and updating it requires hunting all of them down. Centralize them:
// lib/stripe.ts — single source of truth export const STRIPE_PRICE_IDS = { pro: 'price_1AbC...', team: 'price_1XyZ...', } as const // src/app/api/checkout/route.ts import { STRIPE_PRICE_IDS } from '@/lib/stripe' // use STRIPE_PRICE_IDS.pro instead of the literalFor webhook secrets (
whsec_*), never store them as literals — they must always be in environment variables.
External references
- cwe · CWE-798 — Use of Hard-coded Credentials: hardcoded service identifiers (especially webhook secrets) outside config files
- owasp:2021 · A05 — Security Misconfiguration: scattered service IDs make rotation and environment separation error-prone
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ai-slop-hallucinations·automated