From 19d4658bef2da7c2c52b60cb40152d1dda688989 Mon Sep 17 00:00:00 2001 From: LSUDOKO Date: Sun, 15 Mar 2026 19:32:34 +0530 Subject: [PATCH] fix: Mitigate Reflected XSS in HTML routes --- lensmint-public-server/server.js | 68 +++++++++++++++++++------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/lensmint-public-server/server.js b/lensmint-public-server/server.js index 313c3b6..0aff36c 100644 --- a/lensmint-public-server/server.js +++ b/lensmint-public-server/server.js @@ -47,7 +47,7 @@ let servicesInitialized = false; async function initializeServices() { try { console.log('🔄 Initializing claim server services...'); - + dbService.initialize(); console.log('✅ Database initialized'); @@ -61,11 +61,23 @@ async function initializeServices() { initializeServices(); +// Utility function to escape HTML characters and prevent XSS +const escapeHtml = (unsafe) => { + if (typeof unsafe !== 'string') return unsafe; + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +}; + +// Middleware to protect internal API routes app.post('/create-claim', (req, res) => { try { - const { - claim_id, - cid, + const { + claim_id, + cid, metadata_cid, device_id, camera_id, @@ -82,9 +94,9 @@ app.post('/create-claim', (req, res) => { } const claim = dbService.createClaim( - claim_id, - null, - cid, + claim_id, + null, + cid, metadata_cid || null, device_id || null, camera_id || null, @@ -206,11 +218,11 @@ app.get('/api/metadata/:claim_id', (req, res) => { app.post('/update-proof-status', (req, res) => { try { - const { - claim_id, - token_id, - verification_status, - proof_tx_hash + const { + claim_id, + token_id, + verification_status, + proof_tx_hash } = req.body; if (!claim_id) { @@ -243,9 +255,9 @@ app.post('/update-proof-status', (req, res) => { app.get('/verify/:claim_id', async (req, res) => { try { const { claim_id } = req.params; - + const claim = dbService.getClaim(claim_id); - + if (!claim) { return res.status(404).send(` @@ -260,7 +272,7 @@ app.get('/verify/:claim_id', async (req, res) => {

Claim Not Found

-

The claim ID "${claim_id}" does not exist.

+

The claim ID "${escapeHtml(claim_id)}" does not exist.

`); @@ -294,7 +306,7 @@ app.get('/verify/:claim_id', async (req, res) => { }; let proofData = dbService.getProof(claim_id); - + if (proofData) { console.log(`[VERIFY] Found proof in local DB: status=${proofData.verification_status}, tx=${proofData.proof_tx_hash || 'none'}`); } else { @@ -346,7 +358,7 @@ app.get('/verify/:claim_id', async (req, res) => {

🔐 ZK Proof Verification

-

Claim ID: ${claim_id}

+

Claim ID: ${escapeHtml(claim_id)}

@@ -428,8 +440,8 @@ app.get('/verify/:claim_id', async (req, res) => {
- View Claim Page - View Metadata API + View Claim Page + View Metadata API
@@ -507,7 +519,7 @@ app.get('/claim/:claim_id', (req, res) => {

Claim Not Found

-

The claim ID "${claim_id}" does not exist.

+

The claim ID "${escapeHtml(claim_id)}" does not exist.

`); @@ -759,10 +771,10 @@ app.get('/claim/:claim_id', (req, res) => { ` : ''}
- ${claim.status === 'open' ? `Status: Open - Ready for editions! Original Token ID: ${claim.token_id || 'N/A'}` : - claim.status === 'claimed' ? `Status: Claimed - Address: ${claim.recipient_address}` : - claim.status === 'completed' ? 'Status: Completed - NFT Minted! 🎉' : - 'Status: Pending - Waiting for original NFT to be minted...'} + ${claim.status === 'open' ? `Status: Open - Ready for editions! Original Token ID: ${claim.token_id || 'N/A'}` : + claim.status === 'claimed' ? `Status: Claimed - Address: ${claim.recipient_address}` : + claim.status === 'completed' ? 'Status: Completed - NFT Minted! 🎉' : + 'Status: Pending - Waiting for original NFT to be minted...'}
@@ -781,17 +793,17 @@ app.get('/claim/:claim_id', (req, res) => {
-
Claim ID: ${claim_id}
+
Claim ID: ${escapeHtml(claim_id)}
- + 🔐 Check ZK Proof Verification