From c63239e7ee68b23eaee0eb4119878b1e4733f229 Mon Sep 17 00:00:00 2001 From: pedro Date: Tue, 16 Jun 2026 16:02:41 +0100 Subject: [PATCH] OWASP ZAP Validation --- backend/server.js | 70 +++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/backend/server.js b/backend/server.js index 44614dd..0210e66 100644 --- a/backend/server.js +++ b/backend/server.js @@ -13,26 +13,39 @@ app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); +// ========================================== +// ROTA LIMPA (Passa no SonarQube, chumba no ZAP) +// ========================================== + +// Modificamos a rota principal temporariamente para o ZAP encontrar o link +app.get('/', (req, res) => { + res.send(` + + +

Bem-vindo a Apex Solutions

+ + Pesquisar + + + `); +}); + +// A rota vulnerável a XSS que o SonarQube ignora (por ser versão gratuita) +app.get('/api/search', (req, res) => { + const termo = req.query.q || ''; + // Vulnerabilidade Crítica: XSS Refletido + res.send(`

Resultados para: ${termo}

`); +}); + // Serve a pasta frontend app.use(express.static(path.join(__dirname, '../frontend'), { extensions: ['html'] })); -// Rotas das 4 páginas estáticas -app.get('/', (req, res) => res.sendFile(path.join(__dirname, '../frontend/index.html'))); +// Rotas das páginas estáticas +// app.get('/', (req, res) => res.sendFile(path.join(__dirname, '../frontend/index.html'))); // <-- COMENTADO PARA NÃO DAR CONFLITO app.get('/about', (req, res) => res.sendFile(path.join(__dirname, '../frontend/about.html'))); app.get('/careers', (req, res) => res.sendFile(path.join(__dirname, '../frontend/careers.html'))); app.get('/contact', (req, res) => res.sendFile(path.join(__dirname, '../frontend/contact.html'))); -app.get('/api/calculate', (req, res) => { - const mathExpression = req.query.expr || '2+2'; - - // VULNERABILIDADE CRÍTICA: O eval() executa - // qualquer código cego que o utilizador envie - const result = eval(mathExpression); - - res.json({ result: result }); -}); - - // Configuração do transporte de E-mail (Mocks de teste vs Produção) let transporter; @@ -51,11 +64,10 @@ if (process.env.NODE_ENV === 'test') { }); } -// Endpoint do Formulário de Contacto (Com a armadilha validada pelo Jest) +// Endpoint do Formulário de Contacto app.post('/api/contact', async (req, res) => { const { firstName, lastName, email, company, message } = req.body; - // Se faltarem dados, devolvemos HTML para simular XSS e bater com o teste unitário if (!email || !message) { res.setHeader('Content-Type', 'text/html'); return res.status(400).send(` @@ -70,35 +82,15 @@ app.post('/api/contact', async (req, res) => { from: '"Apex Solutions" ', to: email, subject: `Confirmation: We received your request, ${firstName}!`, - html: ` -
-

Hello ${firstName} ${lastName},

-

- Thank you for reaching out to Apex Solutions. This is an automated confirmation. -

-
-

Summary of your submission:

-

Subject/Company: ${company || 'Not specified'}

-

"${message}"

-
-

- Our team will get back to you within 24 business hours. -

-
-

- Best regards,
Apex Solutions Corporate Team -

-
- ` + html: `

Thank you for reaching out to Apex Solutions.

` // Encurtado aqui apenas para não poluir o ecrã, podes manter o teu HTML original! }; const info = await transporter.sendMail(mailOptions); - console.log(`[Email Sent Automatically to ${email}] Message ID: ${info.messageId}`); - - res.status(200).json({ success: true, message: 'Thank you! A confirmation email has been dispatched.' }); + console.log(`[Email Sent] Message ID: ${info.messageId}`); + res.status(200).json({ success: true, message: 'Thank you! Email dispatched.' }); } catch (error) { console.error(`[Email Error]:`, error); - res.status(500).json({ error: 'Internal server error. Could not send confirmation email.' }); + res.status(500).json({ error: 'Internal server error.' }); } });