/
/

How to Prove Clickjacking Protection Is Working Across Tenants

by Richelle Arevalo, IT Technical Writer
How to Prove Clickjacking Protection Is Working Across Tenants blog banner image

Key Points

  • Use modern browser controls, such as CSP frame-ancestors, instead of X-Frame-Options to apply stronger and more flexible clickjacking protection across tenants.
  • Align your policy with real application behavior by listing legitimate embeds first, so your allow-lists include only what business workflows require.
  • Validate protections regularly in staging by checking headers and testing framing attempts with browser tools to confirm that enforcement works as intended.
  • Avoid using JavaScript frame-busters or other fragile methods since attackers can easily bypass these defenses.
  • Maintain ongoing proof of compliance with a monthly evidence packet that includes header scan results, blocked framing attempts, and approved exceptions managed under change control.

Clickjacking is a UI redress attack that tricks people into clicking hidden or disguised elements on a page, often through a malicious or unintended iframe. The right way to block it is at the browser level using security headers, mainly CSP frame-ancestors for modern coverage and X-Frame-Options for legacy support.

To keep clickjacking protection consistent across tenants, you need a clear policy, scoped allow-lists, reliable validation tests, and ongoing monitoring with evidence you can share with stakeholders. This guide explains how to build and maintain effective clickjacking protection across tenant environments.

Methods to prove clickjacking protection across tenants

Before you apply or test any protections, ensure the basics are in place.

📌 General prerequisites: 

  • An inventory of applications, known embedding partners, and any client portals that must support framing.
  • The ability to set or adjust response headers at the application layer or through a reverse proxy.
  • Access to a staging domain or environment for safe header testing.
  • Basic tools for traffic capture or automated header scans to verify results.
  • A shared workspace or repository for storing monthly evidence packets and related documentation.

Method 1: Inventory real embed requirements

Before applying any clickjacking protections, identify which applications or pages are legitimately intended to be embedded. This inventory serves as your ground truth. It ensures that valid use cases remain functional and prevents unnecessary blocking during rollout.

Steps:

  1. Review all applications and pages, and list those designed to be embedded. Look for <iframe> usage, widgets, dashboards, or client portals.
  2. Document which external domains are allowed to embed each page.
  3. For every embeddable page, note the business reason for framing it.
  4. Store the information in a shared configuration file, spreadsheet, or internal wiki. Include:
    • Page URLs
    • Allowed domains
    • Notes on framing behavior

Method 2: Select your primary mitigation

Next, decide which technical control will enforce your clickjacking protection. The goal is to apply a consistent, browser-compatible defense across all tenants.

Steps:

  1. Use Content-Security-Policy: frame-ancestors as your main control. It allows you to specify exactly which domains can embed your content and supports granular allow-lists for trusted tenants or partners.
  2. Keep X-Frame-Options in place as a fallback for browsers that don’t fully support Content Security Policy (CSP).
  3. Record your reasoning, noting why CSP is your main control and XFO is used for legacy coverage. Include sample configurations and compatibility notes.
  4. Store this documentation in a shared configuration file or repository, so all app teams follow the same standard.

Method 3: Author a minimal, specific policy

With your inventory complete and mitigation method chosen, it’s time to write a precise CSP that enforces clickjacking protection. Apply the principle of least privilege. Allow only the trusted domains identified in your inventory and block everything else.

Steps:

  1. Start with the most restrictive baseline:

Content-Security-Policy: frame-ancestors ‘self’;

This limits framing to your own domain and blocks all external sources by default.

  1. Gradually extend the policy only as needed to include verified domains:

Content-Security-Policy: frame-ancestors ‘self’https://portal.example.com;

  1. Avoid wildcards. Don’t use * unless absolutely necessary, and if you must, scope it tightly.
  2. If you need to add an exception, document it with:
    • Purpose and expiration date
    • Change record or ticket number
    • Responsible team or approver

Method 4: Validate with simple framing tests

After defining your policies, you must prove that they behave correctly under real browser conditions. This method verifies how your pages respond when framed from both allowed and disallowed origins to ensure only approved domains can display your content.

Steps:

  1. Create a minimal HTML test page on an external domain that embeds your target page using an <iframe>. Host this page on both allowed and disallowed domains.
  2. Open your staging URLs in Chrome, Edge, or Firefox and observe the behavior. Allowed domains should load. Disallowed ones should be blocked.
  3. In the browser console or network tab, look for messages such as:

Refused to display ‘https://app.example.com’ina frame because itset’X-Frame-Options’to’SAMEORIGIN’.

or

Refused to frame ‘https://app.example.com’ because an ancestor violates the following Content Security Policy directive: “frame-ancestors ‘self'”.

  1. Capture evidence for records, including:
    • Screenshots of both successful and blocked loads
    • Response headers
    • Console messages
  1. Record which domains passed or failed and document any unexpected results for follow-up.

Method 5: Handle edge cases without weakening policy

Some tenants or integrations may require exceptions, but relaxing protections globally is risky. Handle these cases carefully to avoid weakening your security posture.

Steps:

  1. Avoid JavaScript frame-busting. Don’t rely on code like:

if (top !== self) top.location = self.location;

It’s easily bypassed and shouldn’t replace header-based controls.

  1. For legitimate third-party embeds, create tightly scoped allow-lists that permit only specific domains and avoid using wildcards.
  2. For legacy browsers, keep your X-Frame-Options setting aligned with your CSP to avoid conflicting behavior.
  3. Each time you add an exception, re-run your framing validation (Method 4) to confirm that the allowance works correctly while other restrictions stay in place.
  4. Log every exception. Record who approved it, when, and why. Assign an expiration or review date and record it in your policy register for audit tracking purposes.

Method 6: Roll out safely and monitor

After final testing, deploy your clickjacking protections to production, but do it carefully. A gradual rollout with active monitoring helps prevent breaking legitimate integrations.

Steps:

  1. Deploy CSP and XFO headers behind a feature flag or configuration toggle so they can be disabled quickly if needed.
  2. Start in staging, then expand to a small group of tenants or internal users before a full rollout.
  3. Monitor application behavior:
    • Check logs for related errors.
    • Look for blocked iframes or empty embeds.
    • Track client feedback through support channels.
    • Use browser console data and analytics to confirm impact and respond quickly to any breakage reports.
  1. Keep a short rollback plan that lists:
    • The config toggle or setting location
    • Deployment steps
    • Escalation contacts
  1. Once the rollout runs smoothly for several days without any issues, mark it as complete and update your documentation.

Method 7: Scan for drift and regressions

Even well-deployed protections can weaken over time due to updates or configuration drift. This method helps ensure your policies stay consistent and effective.

Steps:

  1. Document the expected CSP and XFO headers for each domain or tenant.
  2. Set up weekly scans of public endpoints using tools like curl, a security scanner, or a simple script.
  3. Verify that frame-ancestors or X-Frame-Options headers are present and match the expected values, with no new wildcards or unapproved domains.
  4. If headers are missing or incorrect, open a ticket that includes the affected domain, owner, discovery date, and expected policy.
  5. Keep exceptions limited, documented, and time-bound. Review them regularly and close any that are outdated.

Method 8: Publish a monthly evidence packet

Finally, close the loop with documentation and reporting. A monthly evidence packet turns your ongoing validation work into formal proof of compliance and governance.

Steps:

  1. Compile header scan summaries from the past month, listing:
    • Tenant domain
    • Header values
    • Scan status (pass/fail)
    • Timestamp
  1. Include examples of blocked framing attempts or CSP violation reports from your report-to endpoint, showing:
    • Test domain and URL
    • Browser console message
    • Screenshot of the blocked iframe
  1. Document all approved exceptions with:
    • Domain
    • Reason and expiry date
    • Linked change record or approval ticket
  1. Add screenshots of working embeds to confirm that legitimate framing continues to function as expected.
  2. Record any policy changes or redeployments made that month. Reference related tickets or commits.
  3. Tie the evidence packet to a standing change-control record or Jira epic so auditors and clients can see governance in action.
  4. Store the packet in a central location (e.g., SharePoint, Confluence, or your ticketing system), tagged with tenant ID and reporting period.

Best practices summary table

Use this table to reinforce the key practices that support reliable, secure, and auditable clickjacking protection across tenants.

PracticePurposeValue delivered
frame-ancestors as defaultAdopt modern, granular anti-framing control.Strong protection with fewer false blocks
Minimal allow-listsReduce attack surface.Safer embeds without breakage
Staging-based testsValidate behavior before rollout.Confidence that protections work as intended before production
Weekly header scansDetect drift or misconfigurations.Early fixes and cleaner audits
Monthly evidence packetProve the control is working.Clear QBR story and audit readiness.

Automation touchpoint example

Automation reduces manual effort, catches issues early, and keeps protections consistent across tenants. Use scheduled jobs to enforce and verify clickjacking controls without relying on manual checks.

A typical setup looks like this:

  • Nightly header check
    • A scheduled job fetches response headers from all tenant URLs, confirming that Content-Security-Policy: frame-ancestors or X-Frame-Options is present and correct.
    • Any mismatch or missing header is flagged automatically and logged for review.
  • Weekly iframe test run
    • Once a week, a test page attempts to embed tenant pages from both allowed and disallowed origins.
    • The process captures pass or fail results, console messages, and screenshots to confirm that blocking and allowed behavior align with policy.
  • Monthly evidence packet generation
    • At the end of each month, a scheduled script compiles header scan logs, test results, and exception lists.
    • The output is saved as a PDF or structured report and stored with the corresponding change record for audit reference.

NinjaOne integration

For teams managing multiple tenants and applications, automation fits naturally into existing NinjaOne workflows. Here’s how NinjaOne can support clickjacking protection and governance:

FeatureAction
Scheduled automationsUse NinjaOne’s scheduled automations to run custom scripts that perform header checks across tenant URLs. Log results centrally with custom fields and the platform’s built-in activity logging.
Ticket/Alert generationAutomatically generate tickets or alerts in integrated PSA systems when scheduled checks detect issues, with the option to attach evidence directly to the related change or compliance tracking.
Tagging and custom fieldsApply flexible tagging and custom fields to categorize monitored endpoints and services by tenant and application, enabling easy tracking of exceptions, expirations, and compliance status.
Reporting and dashboardsAggregate scan results and exception data in NinjaOne’s reporting and dashboard features, creating visual representations of governance activities ideal for quarterly business reviews and compliance tracking.

Sustaining strong clickjacking protection with testing and evidence

Clickjacking protection doesn’t have to be complicated. When you use modern controls, test them in staging, and keep an eye out for drift, the process becomes simple and repeatable. Pairing CSP frame-ancestors with clear, minimal allow-lists and consistent evidence makes it easy to show that your safeguards work, and that they stay that way across every client environment.

Related topics:

FAQs

Yes. It still helps with legacy coverage, but CSP frame-ancestors is the modern, more flexible standard for controlling framing behavior across browsers.

Add only that partner’s exact origin to your frame-ancestors directive, test it in staging, and assign an expiration date and owner for the exception.

No. Script-based frame-busting can be bypassed and should never replace header-based protections like CSP or XFO.

Generate a short evidence packet that includes header scan results, examples of blocked framing attempts, approved exceptions, and screenshots of working embeds. Link these to tickets or change logs for transparency.

You might also like

Ready to simplify the hardest parts of IT?