This document details the technical solution to the payment fingerprint harvesting vulnerability outlined in PROBLEM.md. The architecture is a multi-layered, defense-in-depth strategy designed to protect the payment flow without requiring user authentication.
The solution centers on a server-side nonce-gating system enhanced with advanced debug integration and honeypot bot detection. Access to a payment fingerprint is a privilege granted only after passing multiple security layers, including bot detection, CSRF protection, rate limiting, and honeypot traps.
Core Features:
- Nonce-Gating System: Short-lived (60-second) nonces act as single-use permission slips
- Debug Integration: Comprehensive debug mode with 9+ numbered security checks and correlation IDs
- Honeypot Detection: Advanced bot detection using emoji injection pattern (🍯)
- Session Context: Transient, secure session context via SESSION and XSRF-TOKEN cookies
- Callback Authentication: ValidationCode verification for authentic server-to-server callbacks
The architecture is designed around a user browsing the site, selecting a tour, and proceeding to pay with comprehensive security validation.
graph TD A[User visits site & browses tours] --> B[Selects a specific tour] B --> C[Views Tour Details Page] C --> D{Server sets SESSION & XSRF-TOKEN cookies} D --> E[User clicks "Pay Now"] E --> F{9+ Security Checks Execute} F --> G[Check1: CORS Origin Check] G --> H[Check2: CORS Validation Passed] H --> I[Check3: User Agent Security Scan] I --> J[Check4: Referer Validation] J --> K[Check5: Origin Validation] K --> L[Check6: Header Content Security Scan] L --> M[Check7: Request Size Validation] M --> N[Check8: Rate Limit Validation] N --> O[Check9: Honeypot Bot Detection] O --> P{All Checks Passed?} P -- Yes --> Q[Server issues 60-second nonce] P -- No --> R[Request Rejected] Q --> S[Client exchanges nonce for fingerprint] S --> T[Client initiates Zenpay payment plugin] T --> U{Payment Succeeded?} U -- Yes --> V[Server verifies callback via ValidationCode] U -- No --> W[User reloads page for retry] V --> X[Booking marked as paid] W --> C
NEW: Advanced debug integration provides comprehensive visibility into security validation process:
graph TD A[Request Arrives] --> B[Initialize Debug Session] B --> C[Generate Correlation ID] C --> D[Pass Through Middleware Chain] D --> E[Log Each Security Check] E --> F[Collect Results] F --> G[Finalize Debug Session] G --> H[Print Summary] H --> I[Cleanup Memory]
Debug Output Example:
🔍 DEBUG SESSION STARTED
Correlation ID: 550e8400-e29b-41d4-a716-446655440000
POST /api/v1/create-nonce
IP: 192.168.1.1
───────────────────────────────────────
Check1: ✅ CORS Origin Check
Check2: ✅ CORS Validation Passed
Check3: ✅ User Agent Security Scan
Check4: ✅ Referer Validation
Check5: ✅ Origin Validation
Check6: ✅ Header Content Security Scan
Check7: ✅ Request Size Validation
Check8: ✅ Rate Limit Validation
Check9: ✅ Honeypot Bot Detection
───────────────────────────────────────
🔒 SECURITY CHECKS SUMMARY
Total checks: 9
Passed: 9 | Failed: 0
Response: 200
Duration: 45ms
🔍 DEBUG SESSION ENDED
The solution uses a single table to manage nonce lifecycle with debug session tracking:
/* tpdemo_app_payment_nonces: Single-use tokens for gating fingerprint access */
CREATE TABLE tpdemo_app_payment_nonces (
nonce TEXT PRIMARY KEY, -- Cryptographically random nonce (32 hex chars)
booking_id TEXT NOT NULL, -- Associated booking/tour ID
ip_address TEXT NOT NULL, -- Requester IP for validation
issued_at TEXT NOT NULL, -- Creation timestamp
expires_at TEXT NOT NULL, -- 60 seconds after issued_at
used INTEGER DEFAULT 0 NOT NULL -- Single-use flag (0 or 1)
);
-- Indexes for efficient operations
CREATE INDEX idx_nonces_ip ON tpdemo_app_payment_nonces(ip_address);
CREATE INDEX idx_nonces_expires ON tpdemo_app_payment_nonces(expires_at);
Critical: Enable PRAGMA journal_mode = WAL; for concurrent database operations under load.
Purpose: Display tour details and establish secure session context.
Security Controls:
- Sets HSTS and CSP headers for transport security
- Creates SESSION cookie (httpOnly, secure, 30-min TTL)
- Creates XSRF-TOKEN cookie (secure, SameSite=Strict, 30-min TTL)
- Debug session initialization for subsequent requests
Purpose: Generate single-use, 60-second nonce after comprehensive security validation.
Required Headers: X-XSRF-TOKEN (must match SESSION cookie)
Request Body:
{ "tourId": "tour_123", "cfToken": "cloudflare_turnstile_token", "email_verify": "🍯" }
Security Validation Process:
- Check1-2: CORS origin and validation checks
- Check3: User agent security scanning for suspicious patterns
- Check4: Referer validation for sensitive endpoints
- Check5: Origin validation for sensitive endpoints
- Check6: Header content security scanning for malicious patterns
- Check7: Request size validation (1MB limit)
- Check8: Rate limiting validation (IP-based throttling)
- Check9: Honeypot bot detection (🍯 emoji validation)
- CSRF Protection: X-XSRF-TOKEN header verification
- Turnstile Verification: Cloudflare bot detection with 90s caching
Success Response (200 OK):
{ "nonce": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "expiresAt": "2025-07-06T13:28:40Z" }
Bot Detection Response (200 OK - Fake Nonce):
{ "nonce": "fake_1b2c3d4e5f6a1b2c3d4e5f6a1b2c", "expiresAt": "2025-07-06T13:28:40Z" }
Purpose: Exchange valid nonce for payment gateway fingerprint.
Required Headers: X-Payment-Nonce (obtained from create-nonce)
Security Controls:
- Atomic Consumption:
UPDATE ... SET used=1 WHERE nonce=? AND used=0 - IP Validation: Ensures nonce used by same IP that requested it
- Expiry Check: Validates nonce hasn't expired (60-second window)
- Server-Side Secrets: Adds ZENPAY credentials securely
Success Response (200 OK):
{ "fingerprint": "sha3_512_hash_of_complete_payload", "merchantCode": "DEMO-MERCHANT", "apiKey": "provided_api_key", "paymentAmount": "15000", "merchantUniquePaymentId": "uuid-goes-here", "timestamp": "2025-07-06T13:27:40Z" }
Purpose: Securely receive transaction outcome from Zenpay gateway.
Security Controls:
- ValidationCode Verification: Re-computes SHA3-512 hash
- Payload Integrity: Validates all callback parameters
- Authentication: Rejects tampered or fraudulent callbacks
Advanced bot detection using emoji injection pattern:
Frontend Responsibility:
// Frontend automatically injects honeypot field
const payload = {
tourId: selectedTour,
cfToken: turnstileResponse,
email_verify: "🍯" // Required for human verification
};
Backend Detection Logic:
const { tourId, cfToken, email_verify } = body;
const honeypotPresent = 'email_verify' in body;
const honeypotValid = email_verify === "🍯";
if (!honeypotPresent) {
// Suspicious - sophisticated bot possible
logSecurityCheck(correlationId, "Honeypot Bot Detection",
"Field missing - suspicious", false, { field_missing: true, ip });
} else if (!honeypotValid) {
// Definite bot - return fake nonce
return createFakeNonceResponse();
} else {
// Human verified - proceed normally
logSecurityCheck(correlationId, "Honeypot Bot Detection",
"Human user verified", true, { ip });
}
Comprehensive correlation tracking across request lifecycle:
Session Initialization:
export function initializeDebugSession(request: Request): string {
const correlationId = crypto.randomUUID();
const sessionData = {
correlationId,
startTime: Date.now(),
request: {
method: request.method,
url: new URL(request.url).pathname,
ip: request.headers.get('x-forwarded-for') || 'unknown',
userAgent: request.headers.get('user-agent')?.substring(0, 50) || 'unknown'
}
};
debugSessions.set(correlationId, sessionData);
return correlationId;
}
Session Finalization:
export function finalizeDebugSession(correlationId: string, request: Request, response: Response): void {
if (!DEBUG_MODE || !correlationId) return;
const session = debugSessions.get(correlationId);
if (!session) return;
const duration = Date.now() - session.startTime;
const checks = sessionChecks.get(correlationId) || [];
// Print comprehensive debug summary
console.log('🔒 SECURITY CHECKS SUMMARY');
console.log(`Total checks: ${checks.length}`);
console.log(`Passed: ${checks.filter(c => c.success).length} | Failed: ${checks.filter(c => !c.success).length}`);
console.log(`Response: ${response.status}`);
console.log(`Duration: ${duration}ms`);
console.log('🔍 DEBUG SESSION ENDED');
// Cleanup memory
debugSessions.delete(correlationId);
sessionChecks.delete(correlationId);
}
- User visits
/api/v1/tour/{id} - Server sets SESSION (httpOnly) and XSRF-TOKEN cookies
- User clicks "Pay Now"
- Client reads XSRF-TOKEN and includes in X-XSRF-TOKEN header
- Server validates header matches SESSION cookie value
- Debug system logs CSRF validation as part of security checks
Race-condition-safe nonce validation and consumption:
function consumeNonce(nonce: string, ip: string): boolean {
const query = `
UPDATE tpdemo_app_payment_nonces
SET used = 1
WHERE nonce = ?
AND ip_address = ?
AND used = 0
AND expires_at > datetime('now')
`;
const result = db.prepare(query).run(nonce, ip);
return result.changes === 1; // Success only if exactly one row updated
}
Critical authentication step for payment callbacks:
function verifyCallback(body: ZenpayCallbackPayload): boolean {
const { apiKey, mode, paymentAmount, merchantUniquePaymentId, CustomerReference, ValidationCode } = body;
const username = Deno.env.get("ZENPAY_USERNAME");
const password = Deno.env.get("ZENPAY_PASSWORD");
const payload = [
apiKey, username, password, mode, paymentAmount,
merchantUniquePaymentId, CustomerReference
].join("|");
const expectedCode = sha3_512(payload);
return expectedCode === ValidationCode;
}
# Enable comprehensive debug output export DEBUG_MODE=true # Disable debug output for production export DEBUG_MODE=false
- Generation: Unique UUID per request in API Gateway
- Distribution: Passed to all middleware and handlers
- Tracking: Links all security checks for single request
- Cleanup: Automatic memory management prevents leaks
- Check1-2: CORS validation and origin checks
- Check3: User agent security scanning
- Check4-5: Referer and origin validation for sensitive endpoints
- Check6: Header content security scanning
- Check7: Request size validation
- Check8: Rate limiting validation
- Check9: Honeypot bot detection
- Request Duration: Total processing time tracked
- Check Timing: Individual security check performance
- Success/Failure Ratios: Security validation metrics
- Memory Usage: Debug session cleanup monitoring
Enhanced UX with debug visibility for troubleshooting:
- Failure: Payment fails (card issues, insufficient funds)
- Debug Info: In debug mode, detailed failure analysis available
- Notification: Clear error message with retry instructions
- Action: "Try Again" button triggers page reload
- Mechanism:
location.reload()creates fresh session context - Fresh Start: New correlation ID, clean debug session, new nonce
# Required environment variables ZENPAY_USERNAME="your_username" ZENPAY_PASSWORD="your_password" TURNSTILE_SECRET_KEY="your_turnstile_key" ADMIN_API_KEY="your_admin_key" # Debug configuration DEBUG_MODE=false # Disable debug output in production LOG_LEVEL=INFO # Production logging level
- Log Cleanup: Automatic log file cleanup on server restart
- Memory Management: Debug session cleanup prevents memory leaks
- Database WAL Mode: Concurrent access optimization
- Correlation ID Efficiency: UUID generation optimized for performance
Built with security-first design principles, comprehensive debug visibility, and advanced bot detection for enterprise payment processing.