Skip to content

MPA Security — Protecting Multi-Page Applications from Vulnerabilities

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about MPA Security. We cover key concepts, practical examples, and best practices to help you master this topic.

MPA security covers server-side input validation, SQL Injection prevention, XSS protection, CSRF token implementation, secure session management, HTTPS enforcement, and security headers for multi-page applications.

What You'll Learn

By the end of this tutorial, you will understand the main security threats facing MPAs, how to prevent SQL injection with parameterized queries, protect against XSS with output encoding, implement CSRF tokens, secure sessions, enforce HTTPS, configure security headers, and follow OWASP guidelines for web applications.

Why It Matters

MPAs handle sensitive data on the server — user credentials, payment information, personal data. A single vulnerability can expose millions of records. Security is not optional; it is a fundamental requirement. Understanding and implementing security measures protects your users and your business from data breaches, legal liability, and reputational damage.

Real-World Use

A healthcare MPA suffered a SQL injection attack that exposed 500,000 patient records including medical histories and social security numbers. The vulnerability was in a search feature that concatenated user input directly into SQL queries. After switching to parameterized queries and implementing input validation, no further SQL injection attacks succeeded.

OWASP Top 10 for MPAs
    ┌──────────────────────────────────────────────────────────┐
    │              OWASP Top 10 — MPA Focus                    │
    ├──────────────────────────────────────────────────────────┤
    │                                                          │
    │  1. Broken Access Control     → Server-side auth checks │
    │  2. Cryptographic Failures     → HTTPS, secure cookies  │
    │  3. Injection (SQL, NoSQL)     → Parameterized queries  │
    │  4. Insecure Design            → Security by design     │
    │  5. Security Misconfiguration  → Headers, CORS, CSP    │
    │  6. Vulnerable Components      → Dependency updates     │
    │  7. Auth Failures              → Strong password policy │
    │  8. Data Integrity Failures    → CSRF tokens            │
    │  9. Logging Failures           → Audit logging          │
    │ 10. SSRF                        → URL validation        │
    │                                                          │
    └──────────────────────────────────────────────────────────┘

Think of MPA security like securing a building. Input validation is the receptionist checking IDs at the entrance. Parameterized queries are the secure internal mail system that prevents packages from being opened mid-delivery. Security headers are the security cameras. HTTPS is the encrypted tunnel connecting the building to the outside world.

SQL Injection Prevention

// BAD — vulnerable to SQL injection
app.get('/products', (req, res) => {
    const category = req.query.category;
    // Never do this — concatenating user input into SQL
    const query = `SELECT * FROM products WHERE category = '${category}'`;
    // If category = "'; DROP TABLE products; --"
    // The query becomes: SELECT * FROM products WHERE category = ''; DROP TABLE products; --'
    db.query(query, (err, results) => {
        res.render('products', { products: results });
    });
});

// GOOD — parameterized query
app.get('/products', (req, res) => {
    const category = req.query.category;

    // Parameterized query — user input is separated from SQL
    db.query(
        'SELECT * FROM products WHERE category = $1',
        [category],  // Parameters are escaped automatically
        (err, results) => {
            if (err) {
                console.error('Database error:', err);
                return res.status(500).render('error', {
                    message: 'An error occurred. Please try again.'
                });
            }
            res.render('products', { products: results });
        }
    );
});

// Additional input validation
function validateCategory(category) {
    const validCategories = ['electronics', 'clothing', 'food', 'books'];
    if (!validCategories.includes(category)) {
        return null;
    }
    return category;
}

Security Headers Configuration

// Security headers middleware
const helmet = require('helmet');

app.use(helmet({
    // Content Security Policy
    contentSecurityPolicy: {
        directives: {
            defaultSrc: ["'self'"],
            scriptSrc: ["'self'", "'unsafe-inline'"],
            styleSrc: ["'self'", "'unsafe-inline'"],
            imgSrc: ["'self'", 'https:', 'data:'],
            connectSrc: ["'self'", 'https://api.example.com'],
            fontSrc: ["'self'", 'https://fonts.gstatic.com'],
            objectSrc: ["'none'"],
            frameAncestors: ["'none'"],
            formAction: ["'self'"]
        }
    },
    // HTTP Strict Transport Security
    hsts: {
        maxAge: 31536000,  // 1 year
        includeSubDomains: true,
        preload: true
    },
    // Referrer Policy
    referrerPolicy: { policy: 'strict-origin-when-cross-origin' }
}));

// Resulting response headers:
// Content-Security-Policy: default-src 'self'; ...
// Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
// X-Content-Type-Options: nosniff
// X-Frame-Options: DENY
// X-XSS-Protection: 0 (modern browsers disable this)
// Referrer-Policy: strict-origin-when-cross-origin

Output Encoding for XSS Prevention

<!-- EJS template with proper output encoding -->

<!-- Escaped output (recommended) — prevents XSS -->
<h1><%= product.name %></h1>
<!-- If product.name = "<script>alert('xss')</script>"
     Output: &lt;script&gt;alert('xss')&lt;/script&gt;
     Safe! -->

<!-- Unescaped output — use only with trusted content -->
<div><%- product.sanitizedDescription %></div>
<!-- Use DOMPurify on the server before passing to template -->

<!-- URL encoding -->
<a href="/products/<%= encodeURIComponent(product.slug) %>">
    <%= product.name %>
</a>

<!-- JavaScript context — JSON encode -->
<script>
    var product = <%- JSON.stringify(product) %>;
    // JSON.stringify escapes special characters
    // Never use user input directly in <script> tags
</script>

<!-- HTML attribute encoding -->
<input type="text"
       value="<%= product.name.replace(/"/g, '&quot;') %>">

Common Mistakes

  1. SQL injection through unprotected inputs. Every user input that reaches a database query must use parameterized queries or prepared statements. Never concatenate input into SQL strings.
  2. Missing security headers. Without CSP, HSTS, X-Frame-Options, and other headers, your application is vulnerable to clickjacking, MIME-type sniffing, and content injection.
  3. Server-side validation gaps. Client-side validation is for UX; server-side validation is for security. Always validate and sanitize input on the server.
  4. Insecure session configuration. Sessions without HttpOnly, Secure, and SameSite flags are vulnerable to theft. Use a secure session store (Redis) with proper configuration.
  5. Exposing stack traces in production. Error messages should be user-friendly, not technical. Never reveal database schemas, file paths, or dependency versions in production error pages.

Practice Questions

  1. How does SQL injection work and how do you prevent it?
  2. What security headers should every MPA include?
  3. What is the difference between escaped (<%= %>) and unescaped (<%- %>) output in templates?
  4. Why is server-side validation necessary even with client-side validation?
  5. What session configuration settings improve security?

Challenge: Perform a security audit on an MPA using OWASP ZAP scanner. Check for: SQL injection vulnerabilities, missing security headers, XSS vulnerabilities, CSRF protection, insecure session configuration, exposed error pages, and outdated dependencies. Fix all high and medium severity issues.

FAQ

What is the most common MPA vulnerability?

SQL injection remains the most common and dangerous MPA vulnerability. It occurs when user input is concatenated into SQL queries without proper sanitization or parameterization.

Is HTTPS enough for security?

No. HTTPS encrypts data in transit but does not protect against server-side vulnerabilities. You need HTTPS plus input validation, output encoding, CSRF protection, and secure sessions.

How often should I update dependencies?

Update security-critical dependencies immediately. Run npm audit or similar tools weekly. Use Dependabot or Renovate for automated dependency updates.

What is the difference between authentication and authorization?

Authentication verifies who you are (login). Authorization determines what you can access (permissions). Both must be enforced on the server.

Should I roll my own authentication?

No. Use established libraries like Passport.js, bcrypt for password hashing, and standard session management. Custom authentication is error-prone.

Mini Project

Secure an MPA with: SQL injection prevention using parameterized queries for all database operations, Helmet.js security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options), CSRF tokens on all forms, secure session configuration (HttpOnly, Secure, SameSite), output encoding in all templates, input validation and sanitization, Rate Limiting on login endpoints, and HTTPS enforcement.

What's Next

You understand MPA security. Now build a complete MPA mini project that combines everything you have learned.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro