SECURE MODE — CAPTCHA invalidated after use, rate limiting active
Step 3Deploy the security patch and verify the fix

Secure Version Deployed

The security patch is active. CAPTCHA is invalidated after use and rate limiting is enforced. Go back to the Proxy page and try the replay attack again — it will be blocked.

Now go to the Proxy page and try replaying the same request. It will be blocked with HTTP 403 or 429.
INSECURE — Vulnerable Code
// POST /api/Feedbacks/
async function submitFeedback(req, res) {
  const { captchaId, captcha, comment, rating } = req.body;

  // Validate CAPTCHA answer
  const captchaRecord = await getCaptcha(captchaId);
  if (captchaRecord.answer !== captcha) {
    return res.status(400).json({ error: "Invalid CAPTCHA" });
  }

  // ⚠️ VULNERABILITY: CAPTCHA is validated but NEVER invalidated
  // The same captchaId + answer can be replayed indefinitely
  // No rate limiting applied

  const feedback = await createFeedback({ comment, rating });
  return res.status(201).json({ success: true, id: feedback.id });
}
SECURE — Patched Code
// POST /api/Feedbacks/
async function submitFeedback(req, res) {
const { captchaId, captcha, comment, rating } = req.body;
// Validate CAPTCHA answer
const captchaRecord = await getCaptcha(captchaId);
if (captchaRecord.answer !== captcha) {
return res.status(400).json({ error: "Invalid CAPTCHA" });
}
+ // ✅ FIX 1: Single-use CAPTCHA enforcement
+ if (captchaRecord.used) {
+ return res.status(403).json({
+ error: "CAPTCHA already used. Request a new one."
+ });
+ }
+ await markCaptchaAsUsed(captchaId);
+ // ✅ FIX 2: Rate limiting (max 3 requests per minute)
+ if (!checkRateLimit(req.sessionId)) {
+ return res.status(429).json({
+ error: "Rate limit exceeded. Try again later."
+ });
+ }
const feedback = await createFeedback({ comment, rating });
return res.status(201).json({ success: true, id: feedback.id });
}

Single-Use CAPTCHA

Each CAPTCHA is marked as "used" after first validation. Replay attempts get HTTP 403.

Rate Limiting

Max 3 submissions per minute. Exceeding returns HTTP 429 Too Many Requests.

Step-Up Auth

For high-value banking flows, require OTP or biometric verification before processing.