Webpages Can Be Embedded by Other Sites (Clickjacking Risk)
Your website is missing a security setting that tells browsers whether your pages are allowed to be embedded inside other websites. Without it, a malicious site could invisibly overlay your pages to trick your visitors into clicking buttons or links they didn't intend to — a technique called clickjacking. This is a missing protection layer, not an active attack in progress.
Business Impact And Actions
medium urgencyBusiness Impact
The practical risk depends on what your site does. Pages with sensitive actions — like account settings, payment confirmations, or data-deletion buttons — are the most meaningful targets. For most small SaaS products, this is a compliance and security-posture concern: it will be flagged in security audits and penetration tests, and some enterprise customers or regulators may require it to be addressed. It does not expose your database or user passwords directly.
What To Do
- Ask your developer to add a framing protection header to your web server — it's a 15–30 minute configuration change on most platforms (Nginx, Apache, or your hosting provider's settings panel).
- If your site intentionally embeds its own pages in iframes (e.g., a widget or embedded dashboard), let your developer know so they use the right setting ('same origin only') rather than blocking all framing.
- Once the fix is deployed, ask your developer to confirm it's working using a free tool like securityheaders.com.
Missing Anti-Clickjacking Header (X-Frame-Options / CSP frame-ancestors)
medium severity CVSS 4.3–6.1Vulnerability Explanation
The server does not send an X-Frame-Options header or a Content-Security-Policy header containing a frame-ancestors directive. Without either control, browsers apply their default permissive behaviour and allow any third-party site to embed the application's pages inside an <iframe>. An attacker can exploit this by hosting a page that loads the target application in a transparent or invisible iframe, positioned over a decoy UI element. When the victim interacts with the decoy, their click is actually delivered to the underlying application — potentially triggering authenticated actions such as account changes, purchases, or data deletion without the user's awareness.
Root Cause
No server-level configuration was added to emit framing-control response headers. Browsers do not restrict iframe embedding by default; the restriction must be explicitly opted into via HTTP response headers. HTML meta-tag equivalents (e.g., <meta http-equiv="X-Frame-Options">) have no effect and must not be used as a substitute.
Technical Impact
An attacker can trick an authenticated user into performing unintended actions on the application — such as changing account settings, confirming transactions, or deleting data — by overlaying the application in a hidden iframe on a malicious page. The severity is bounded by what authenticated actions are available and whether the application also sets SameSite cookie attributes (which would block session cookies in cross-origin frames).
Severity Justification
Clickjacking requires social engineering (the victim must visit an attacker-controlled page while authenticated) and is most impactful on applications with sensitive one-click actions. The absence of SameSite cookie attributes would elevate risk; their presence significantly reduces it. No CVE is assigned to this class of misconfiguration — it is a missing defence-in-depth control.
Affected Components
All HTML responses served by the application (all versions)
Remediation Steps
- Determine whether any legitimate use case requires your pages to be embedded in iframes on other origins. If not, use DENY. If your own domain needs to embed pages (e.g., an internal dashboard), use SAMEORIGIN.
- Add the header at the web server or reverse-proxy layer so it applies globally. See config examples below for Nginx, Apache, and Express/Node.
- Prefer CSP frame-ancestors over X-Frame-Options — it is the modern standard, offers more flexibility (multiple allowed origins, wildcard subdomains), and supports report-only mode for safe rollout. Set both headers for maximum browser compatibility.
- If you already have a Content-Security-Policy header, append the frame-ancestors directive to it rather than adding a separate header.
- Deploy and verify using the steps in the Verification section.
Verification Steps
- Run: curl -I https://yourdomain.com and check the response includes X-Frame-Options: DENY (or SAMEORIGIN) and/or Content-Security-Policy: frame-ancestors 'none' (or 'self').
- Visit https://securityheaders.com and scan your domain — it will flag missing or misconfigured framing headers.
- Create a local test HTML file containing <iframe src="https://yourdomain.com"></iframe>, open it in a browser, and confirm the browser blocks the embed (you should see a console error, not your page).
Code Examples (nginx / apache / express)
# No framing header present — browser default allows all embedding
# Nginx — add to http {}, server {}, or location {} block
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none';" always;
# Apache — add to httpd.conf, .htaccess, or VirtualHost
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none';"
</IfModule>
# Express / Node.js (using helmet)
const helmet = require('helmet');
app.use(helmet.frameguard({ action: 'deny' }));
// helmet also sets CSP frame-ancestors when you configure helmet.contentSecurityPolicy
# If pages must be embeddable within your own domain, use SAMEORIGIN / 'self':
# X-Frame-Options: SAMEORIGIN
# Content-Security-Policy: frame-ancestors 'self';
Best Practices
- Set both X-Frame-Options and CSP frame-ancestors for broadest browser coverage — CSP takes precedence in modern browsers, while X-Frame-Options serves as a fallback.
- Apply framing headers globally at the server/proxy layer rather than page-by-page to avoid gaps.
- Mark session cookies with SameSite=Lax or SameSite=Strict as a complementary defence — this prevents session cookies from being sent in cross-origin iframe requests, neutralising authenticated clickjacking even if framing headers are absent.
- Never use the ALLOW-FROM directive in X-Frame-Options — it is obsolete and ignored by all modern browsers; use CSP frame-ancestors with explicit origins instead.
References
- cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options
- developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
- cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
Found this in your infrastructure?
VulWall scans for this and dozens of other issues automatically.
Scan Your Domain Free