6.0 KiB
Security & Functionality Fixes Applied
Date: February 21, 2026
Summary of Fixes Applied
Critical Fixes (Fixed)
1. Webhook Signature Verification Buffer Length Check
File: server.js:15162-15170
Issue: timingSafeEqual() throws error if buffer lengths differ, potentially bypassing verification.
Fix: Added buffer length comparison before calling timingSafeEqual().
const sigBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expectedSignature);
if (sigBuffer.length !== expectedBuffer.length || !require('crypto').timingSafeEqual(sigBuffer, expectedBuffer)) {
// reject
}
2. Duplicate Variable Declaration in Webhook Handler
File: server.js:15253
Issue: eventId was declared twice in the same function scope, causing SyntaxError.
Fix: Removed the duplicate declaration at line 15253.
3. Session Secret Auto-Generation with Persistence
File: server.js:390-420
Issue: Session secret was regenerated on each restart, invalidating all sessions.
Fix: Session secret is now persisted to generated-secrets.json and reused on restart.
const secretsFile = path.join(STATE_DIR, 'generated-secrets.json');
// Load existing secret or generate and persist new one
4. SQLCipher Key Validation
File: src/database/connection.js:18-29
Issue: SQLCipher key was only escaping quotes, not fully validating format.
Fix: Added comprehensive key validation:
- Minimum 32 characters
- Must be hexadecimal only (0-9, a-f, A-F)
function validateSqlcipherKey(key) {
if (!key || typeof key !== 'string') throw new Error('...');
if (key.length < 32) throw new Error('...');
if (!/^[a-fA-F0-9]+$/.test(key)) throw new Error('...');
return true;
}
5. JSON Body Size Limit in External API
File: src/external-admin-api/handlers.js:108-131
Issue: No size limit on JSON body parsing, potential memory exhaustion.
Fix: Added maxBodySize parameter (default 6MB) with streaming size check.
async function parseJsonBody(req, maxBodySize = 6 * 1024 * 1024) {
// ... size tracking and rejection if exceeded
}
High Priority Fixes (Fixed)
6. CORS Headers
File: server.js:8940-8950
Issue: No explicit CORS configuration.
Fix: Added comprehensive CORS headers to sendJson():
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Allow-Credentials
7. Pending Payment Session Cleanup
File: server.js:1130-1190
Issue: Pending payment sessions accumulate without cleanup.
Fix: Added cleanupStalePendingPayments() function that:
- Removes pending records older than 48 hours
- Runs during periodic memory cleanup
- Persists changes after cleanup
8. Builder State Debouncing
File: public/builder.js:19-46
Issue: Every property change triggered localStorage write (performance impact).
Fix: Implemented debounced save with 500ms delay.
let builderStateSaveTimer = null;
function saveBuilderState(state) {
pendingBuilderState = state;
if (builderStateSaveTimer) clearTimeout(builderStateSaveTimer);
builderStateSaveTimer = setTimeout(() => {
localStorage.setItem(BUILDER_STATE_KEY, JSON.stringify(pendingBuilderState));
}, 500);
}
9. Zip Extraction Symlink Protection
File: server.js:8950-8975
Issue: Extracted archives could contain symlinks pointing outside workspace.
Fix: Added scanForSymlinks() function that removes symlinks after extraction.
10. Enhanced Environment Validation
File: server.js:20672-20720
Issue: Limited production environment checks.
Fix: Enhanced validation with:
- Critical variables check (DATABASE_ENCRYPTION_KEY added)
- Recommended variables warnings
- Better console output formatting
Medium Priority Fixes (Fixed)
11. Dangerous File Type Blocking in Zip Extraction
File: server.js:8922-8927
Fix: Added blocking of potentially dangerous file types:
.exe,.bat,.cmd,.sh,.ps1,.vbs
Files Modified
chat/server.js- Main server file (multiple fixes)chat/src/database/connection.js- Database connection with SQLCipher validationchat/src/external-admin-api/handlers.js- JSON body size limitchat/public/builder.js- State persistence debouncing
Remaining Recommendations (Non-Critical)
These are recommended but not critical for launch:
Post-Launch Items
- OAuth State in Database - Currently stored in memory, will be lost on restart/multi-instance
- Atomic Token Operations - Consider using database transactions for high-concurrency scenarios
- 2FA for Admin - Add two-factor authentication requirement for admin accounts
- IP-Based Admin Restrictions - Consider limiting admin panel access by IP
Testing Performed
- Webhook signature verification with various buffer lengths
- Session persistence across simulated restarts
- SQLCipher key validation with various formats
- JSON body parsing with oversized payloads
- Builder state persistence under rapid changes
- Zip extraction with path traversal attempts
Verification Steps
- Webhook Test:
curl -X POST http://localhost:4000/webhooks/dodo \
-H "dodo-signature: sha256_invalid" \
-d '{"test": true}'
# Should return 401, not crash
- Session Persistence Test:
- Start server
- Login as user
- Restart server
- Verify session still valid
- SQLCipher Test:
# Valid key
DATABASE_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef node server.js
# Invalid key should fail with clear error
DATABASE_ENCRYPTION_KEY="invalid!key" node server.js
Conclusion
All critical and high-priority security and functionality issues have been addressed. The application is now ready for launch with the following improvements:
- Robust webhook handling
- Persistent session secrets
- Validated SQLCipher keys
- Protected JSON parsing
- CORS support
- Automatic cleanup of stale data
- Better error handling and user feedback