Content Security Policy and security headers in Apache Superset

Content Security Policy and security headers in Apache Superset are set through Talisman, and tuning them is what keeps dashboards, map tiles, fonts and embedding working. This page covers the decisions, setup order and tests.

On this page

Why Content Security Policy and security headers in Apache Superset need deliberate tuning

Enabling security headers on a production Superset is a tuning exercise, not a switch to flip. A security team typically wants a Content Security Policy, HSTS, frame restrictions and related headers enforced, and Superset can apply them through Flask-Talisman. The difficulty is that dashboards are not self-contained pages. Charts may load map tiles from external hosts, dashboards may pull web fonts from a CDN, and teams that embed Superset in their own product need the frame rules to allow that specific parent origin. A policy written for a plain web application will block some of these resources, and the failures show up as blank map panels, fallback fonts or an embedded iframe that refuses to render. Before rollout, list every external origin your dashboards and embedding pages actually load, then decide which ones the policy must allow.

The headers protect against different threats, and each one addresses a specific risk. A Content Security Policy limits which scripts, styles, images and frames the browser will execute or load, which reduces the impact of cross-site scripting. HSTS tells browsers to use HTTPS for the site, which reduces downgrade and interception risk on the login path. Frame options and the frame-ancestors directive control which sites may place Superset inside an iframe, which addresses clickjacking. Teams need this work when Superset holds sensitive warehouse data, when users reach it from untrusted networks, or when an audit or internal control requires documented browser hardening. Ask your security team which of these risks they are mitigating, because that answer decides how strict each directive should be.

Exact Talisman settings, option names and default values differ between Superset releases, so confirm them in the configuration documentation for the version you run before you write any policy. Do not copy a policy from a blog post or an older deployment. Plan a staging test that loads every dashboard type, map charts, embedded views and exports, and watch the browser console for policy violations while the policy runs in report-only mode if your version supports it. The Apache Superset configuration documentation is the natural starting point for those settings and for the SECRET_KEY and session settings that interact with the same configuration file.

Which headers Superset sends and which ones your deployment changes

Superset's browser security headers are set by Flask-Talisman and then shaped by your reverse proxy, your TLS setup and any embedding you allow. The cards below cover the headers a reviewer will test first, what each one blocks, and which dashboard features it can break if the policy is tuned too tightly.

Content-Security-Policy directives

The Content-Security-Policy controls which origins the browser may load scripts, styles, fonts, images and frames from. Superset's chart libraries, map tiles and any external font or logo host each need an explicit allowance, so a policy that works for the login page can still blank a map or a custom theme. Check every directive against the dashboards your users actually open, and confirm the current defaults in the configuration documentation before you change anything.

Strict-Transport-Security

HSTS tells browsers to use HTTPS for the Superset host for a set period, which blocks downgrade attempts on hostile networks. It only works if TLS terminates correctly at the proxy for every path users reach, including the embedded or public dashboard hostnames. Enable it after you confirm that all Superset traffic is HTTPS, because a long max-age is hard to undo on user browsers that have already cached it.

X-Frame-Options and frame-ancestors

X-Frame-Options and the frame-ancestors directive decide which sites may place Superset inside an iframe, which is the core of clickjacking protection. The same setting controls embedding, so a strict value blocks your own portal from showing dashboards. List the exact parent origins that need embedding, and test each one, rather than choosing between full blocking and open framing.

Cookie flags and SameSite

Secure and HttpOnly flags keep session cookies off plain HTTP and out of reach of page scripts, and the SameSite attribute limits cross-site sending. SameSite strictness is the setting most likely to break iframe embedding, because the browser may withhold the session cookie inside a third-party frame. Confirm the embedding model and session backend together, since the two choices interact.

Referrer and content type controls

Referrer-Policy limits how much URL detail browsers send to external hosts, which matters when dashboard URLs carry filter values or identifiers. X-Content-Type-Options stops browsers from guessing file types on downloads. Both are usually low-risk to enable, but confirm that any external link or export flow you rely on still works after the change.

Proxy and application ownership

Headers can be set by Superset, by the reverse proxy, or by both, and duplicate or conflicting values are hard to diagnose. Decide which layer owns each header, remove the other copy, and record that decision with the proxy configuration. Verify the final response headers from a browser and from a scanner, and repeat the check after each Superset upgrade, since defaults can change between releases.

Talisman and CSP options and when each fits

This table compares the main header choices for a Superset deployment: keeping Talisman defaults, adding map tile and font sources, allowing one embedding origin, enabling HSTS and running report-only policies. Read each row as a trade-off between dashboard compatibility and tighter browser protection, and confirm every setting name and default against the configuration reference for your Superset version before you change production.

OptionTrade-offWhen it fitsConfirm before changing
Keep Talisman defaultsLowest breakage risk, but default policies may block external map tiles, fonts or embedded content your dashboards useSmall internal deployments with no external map or font sources and no embeddingDefault policy values for your version in the configuration reference
Add allowed sources for map tilesEach added host widens what the browser will load, and tile providers can change domainsDashboards with map charts that load tiles from a named providerExact tile host names used by your map chart configuration and the CSP directive that governs images and connections
Add allowed sources for fontsFont hosts are a small but real script and style surface; self-hosting fonts removes the need for external hostsCustom branding that loads web fonts from a CDNWhether your theme loads fonts externally, and the font-src directive that applies
Allow one embedding origin in frame-ancestorsOnly the named site can frame Superset, but framing weakens clickjacking protection and can conflict with cookie SameSite settingsEmbedded analytics in one known product or portalThe frame-ancestors setting name, its format for your version, and the matching session cookie behavior
Enable HSTS only behind TLSBrowsers remember the HTTPS-only rule, so a misconfigured or plain HTTP path can lock users out until the setting expiresProduction deployments where TLS terminates at a proxy that always serves HTTPSThat the proxy forwards the protocol header Superset reads, and the HSTS setting and its max age in your version
Report-only mode for testingViolations are logged instead of blocked, so breakage is found without user impact, but attacks are not stopped during the testStaging validation and the first weeks after a header changeWhether your version exposes a report-only option, where reports are sent, and who reviews them
Strict policy with no exceptionsStrongest browser restriction, but most likely to break chart rendering, embedded content and extensionsOnly after dashboards and embedding are tested page by pageWhich chart types and plugins need inline scripts or styles in your version

How to tune the CSP for maps, fonts and embedding without weakening it

Tune the Content Security Policy by finding each external origin your dashboards actually load, then allowing exactly those origins and nothing broader. Start by opening a representative dashboard in a staging instance with the browser developer tools open, and watch the Network and Console panels while every chart, map and filter renders. Each blocked request appears as a CSP violation report in the console, naming the directive and the origin. Map tile providers, font hosts, analytics scripts and the parent page that embeds Superset each show up this way. Record every origin in a short register with the directive it belongs under, the business reason it is needed and the dashboard that triggers it. Confirm each entry with the team that owns the dashboard, because a tile provider or font host that appears once may be a leftover from a retired chart.

Resist the shortcuts that quietly remove the protection the policy exists to provide. A wildcard such as * or a broad scheme-wide allowance in script-src, and adding 'unsafe-inline' or 'unsafe-eval' to make an error disappear, let injected script run from anywhere. Where a chart or plugin needs inline behavior, confirm with the Superset release you run whether the relevant setting can be scoped or whether a nonce or hash approach is practical, and treat any blanket relaxation as a documented exception with an owner and a review date. Keep script-src as narrow as your register allows, and keep frame-ancestors separate from the resource directives, since it governs who may frame Superset rather than what Superset may load.

Embedding usually needs a deliberate frame-ancestors decision, not a default. If Superset pages appear inside your own product, list only the parent origins that host them, and tie each one to a named embedding design, such as the embedded SDK with guest tokens or a specific portal. Be aware that browser cookie settings for iframes interact with this decision, so review it alongside the session design in the sibling topic on server-side sessions. If no embedding exists, set frame-ancestors to 'none' and confirm that no internal tool depends on framing before you enforce it. Ask your security team to sign off the parent list in writing, and re-run the browser test after each Superset upgrade, because new front-end assets can introduce origins that the previous register never contained.

Enabling Talisman and rolling out headers in order

This sequence moves Talisman and the Content Security Policy from configuration to enforcement without breaking dashboards, so each header change is tested against real content before users see it. It ends with HSTS, which is enabled last because it is hard to undo once browsers have cached it.

  1. Confirm TLS terminates at the proxy

    The platform team confirms that every user request reaches Superset over HTTPS at the reverse proxy or load balancer, and that the proxy forwards the original scheme to Superset. Talisman decides on secure cookies and HSTS partly from what the application sees, so a plain HTTP hop behind the proxy will produce misleading results. The step is done when a request to the public hostname shows a valid certificate and the forwarded protocol header matches what the proxy receives. Confirm the exact proxy settings with your own network team and your Superset version's configuration documentation.

  2. Back up the configuration and record the current headers

    The Superset administrator copies the current superset_config.py, the deployment manifests or environment files, and any custom templates, then records the response headers the staging instance returns today. Keep this baseline so that any later difference can be traced to a specific change. The check is a stored copy of the configuration with a note of the baseline headers from the browser's network panel or a command-line request. Store the backup with the same access controls as the secret key material it may contain.

  3. Enable Talisman in staging with a report-only policy

    In staging only, the administrator enables Talisman and sets the Content Security Policy to report-only mode, so the browser reports violations without blocking any resource. The policy starts with the sources Superset is known to need, and the reporting endpoint is set to a location your team monitors. The check is that Superset starts cleanly, the login page loads, and the headers include the report-only policy header rather than the enforcing one. Confirm the configuration keys and their current names in the Superset configuration documentation for the version you run.

  4. Exercise every dashboard type, chart and export

    A tester opens each dashboard in staging and walks through every chart type in use, including maps with their tile sources, charts that load web fonts, embedded dashboards, SQL Lab results, and CSV, Excel and image exports. The tester also runs any scheduled report or thumbnail path that the instance uses. The check is a written list of each dashboard and chart, with the outcome and any violation seen in the browser console or the report endpoint. Include a user from each role population so that role-specific pages are covered.

  5. Review violation reports and classify each one

    The security engineer reviews the collected violation reports and groups them into three categories: sources Superset legitimately needs, sources that come from a customization or a third-party embed, and unexpected sources that should be investigated. Each legitimate source is added to the policy with the narrowest directive that works, and each unexpected source is traced to its origin before any change is made. The check is a reviewed list where every reported source has an owner and a decision. Expect the map tile and font sources to need explicit review because they are the most common additions.

  6. Tighten the policy and repeat the test pass

    The administrator removes broad allowances that were added only to stop noise, replaces them with specific origins, and runs the full dashboard and chart pass again in report-only mode. The policy should contain no source that was not justified in the previous review. The check is a clean second pass where the same dashboards and exports produce no unexpected reports. Keep the final policy in version control next to the configuration so that later upgrades can be tested against it.

  7. Switch the policy to enforcement in staging, then production

    The administrator changes the policy from report-only to enforcing in staging and repeats a short smoke test of login, a sample dashboard, a map chart and an export. If the staging check passes, the same change is made in production during a window agreed with the business owners, with the previous configuration ready to restore. The check is that the enforcing header is present, the smoke test passes in both environments, and no violation reports appear for the tested paths. Keep the report endpoint active for a period so that new violations are still visible.

  8. Enable HSTS last with a planned max-age

    HSTS is enabled only after the policy is stable in production, because browsers cache the instruction and will refuse plain HTTP to the hostname for the lifetime set. The team chooses a max-age value, decides whether subdomains are included, and confirms that every subdomain is served over HTTPS before the change. The check is that the Strict-Transport-Security header appears on production responses with the planned value, and that the owner has a documented way to reverse the change if a problem appears. Confirm the value and directives with your security policy owner before the header is sent.

Security and operational risks of header changes

Header changes look small in a configuration file but can break dashboards, lock users out or weaken the frame protections you meant to add. The four risks below share one pattern: a setting that is correct on the day it is made and wrong after an upgrade, a certificate change or a new embedding requirement. Each card names the control to apply and the check to run after every upgrade.

Policy blocks a chart library after upgrade

A Content Security Policy tuned for one release can stop a chart, map tile or font from loading once Superset updates its front-end bundles or a plugin adds a new external resource. The dashboard then renders blank panels without an obvious server error. Keep the policy in version control next to your Superset configuration, and diff it against the new release's UPDATING.md notes. After each upgrade, open a dashboard that uses every chart type and map your users rely on, and check the browser console for blocked resource messages.

HSTS locks users out

HTTP Strict Transport Security tells browsers to refuse plain HTTP for the host and, if enabled, its subdomains for a set period. If the certificate expires, a subdomain has no HTTPS, or a hostname is misconfigured, users cannot reach Superset until the max-age passes or the browser cache is cleared. Enable HSTS only after TLS works on every hostname it covers, start with a short max-age, and add includeSubDomains only when every subdomain serves valid HTTPS. Check certificate expiry and subdomain TLS before each change window.

Over-broad frame-ancestors

The frame-ancestors directive controls which sites may embed Superset in a frame. Setting it to a wildcard or to a broad list of domains lets any listed site place Superset behind a transparent overlay, which enables clickjacking against logged-in users. Limit the list to the exact embedding applications your team owns, and remember that embedded dashboards need those origins to be allowed. Review the list whenever an embedding partner or internal portal is added or retired.

Report-only policy left in production

A report-only Content Security Policy logs violations without blocking them, which is useful while tuning but gives no protection when left on. Teams often switch to report-only during troubleshooting and forget to switch back, so the enforcing policy never applies. Use report-only in staging with a reporting endpoint, record which header name is active in production, and make enforcement a required item in your go-live checklist. After each upgrade, confirm the response carries the enforcing header name and that violation reports from production are being received and reviewed.

How to test headers without breaking dashboards

What is the first step to test security headers before turning on enforcement?

Start with a staging copy of your production Superset, served through the same reverse proxy and TLS setup, and record the headers it returns on each key URL before you change anything. Run the new policy in report-only mode first, so the browser logs violations without blocking content, and review those reports against the dashboards your users actually open. Only move to enforcement once a full pass over the test cases below produces no unexpected violations. Keep the baseline so you can compare later changes against it.

Which URLs should automated header checks cover in Superset?

Script a request to each URL class that your proxy and Superset serve differently, and assert the presence, value and absence of each header. Include the login page, the home page, a dashboard list, a published dashboard, a draft or unpublished dashboard, SQL Lab, an explore view, the static asset paths, and any embedded or guest-token route you expose. Check that HSTS, frame options and the CSP match what your configuration declares for each path, and fail the run when a header disappears or changes. Ask your team to confirm which Superset routes are reachable from outside the network, because those need the same checks.

How do you check every dashboard and chart type for CSP breakage?

Build a register of the chart types and dashboard features in use, then open a representative dashboard for each one in a browser with the developer console open and the CSP report collector active. Cover at least the chart types your analysts rely on, filter bars, cross-filters, native filters, markdown text blocks with images or links, and any custom visualization plugins. Record console errors and CSP violations per chart, and treat any blocked script, style, image or connection as a finding to resolve in the policy or the content. Repeat the pass with each role you have defined, because permissions change what loads.

How do you verify maps, fonts and exports still render?

Test map charts against the exact tile and style hosts your configuration allows, because a blocked tile host typically shows as a blank map with console errors rather than a clear message. Load each font family used by your branding and confirm it renders without fallback, and check that image and PDF exports, thumbnails and downloaded charts still complete. Export checks matter because some export and screenshot paths run server-side or depend on the same assets, so verify both the file produced and the on-screen result. Note which tile providers your team has approved, and confirm each one with the owner of the map configuration before you add it to the policy.

How should embedding be tested with the real parent origin?

Test embedding from the actual parent application on its real domain, not from a local page, because frame-ancestors and the iframe origin rules only behave correctly against the true origin. Confirm that the parent loads the embedded dashboard, that the guest token flow completes, and that the frame options and cookie settings allow the frame without loosening protection for pages that must not be framed. Include a negative test from an unapproved origin, which should be refused. Ask the team that owns the parent application to confirm the origins that must appear in the policy, and retest whenever that application changes its domain or its embedding path.

What should a regression test cover after each Superset upgrade?

Rerun the full header suite, the browser pass across dashboards and chart types, the export and map checks, and the embedding tests, because upgrades can change bundled asset paths, inline scripts and the frontend code that a policy depends on. Read the release notes and UPDATING.md for the target version before you start, and compare the new build's requests against the baseline you recorded. Run the upgrade in staging first, as the upgrade documentation advises, and keep the policy under version control so a failed upgrade can be rolled back to the last working set of headers.

Can our own team run this test plan, or do we need a partner?

Your team can run this plan if it has staff who can operate the reverse proxy, read browser developer tools, and script HTTP checks, and if it has a staging environment that matches production. The work that usually needs the most time is the dashboard and embedding inventory, because it requires input from the analysts and the application owners who depend on those dashboards. A partner can take on scoping, the automated checks, the report-only rollout and the upgrade regression suite under a written scope. Ask any provider to state which of these tasks it covers, what evidence it returns, and which tasks remain with your staff.

What does a header test engagement cost, and what drives it up?

The cost depends on the number of dashboards, chart types, roles, embedding integrations and tile or font sources in scope, along with the number of environments and the frequency of upgrades. Costs are usually one-time for the initial baseline and policy design, and recurring for regression runs after each upgrade or change to embedding. DeployOpen does not publish prices, and a quote follows from a written scope that lists these inventory items, the environments involved and the deliverables you expect, such as a test script, a results report or a retainer for regression runs.

Limits to confirm in your environment

Talisman and the Content Security Policy depend on the Superset version, the reverse proxy in front of it and the way your team deploys configuration. Each card below is a point where a header that works in a test lab can break dashboards, embedding or login in production. Confirm each one against the vendor documentation and your own test results before you change anything in production.

Talisman and CSP settings by version

Talisman options, the default Content Security Policy and the header keys Superset reads can change between releases. Check the configuration reference for the exact version you run, not a newer branch, and list every header key your deployment sets. Compare the effective policy in a staging browser session after each upgrade, because a release note may not call out a policy change. Record the version next to the policy so an auditor can match the two.

Reverse proxy header behavior

Your load balancer or ingress may add, strip or override headers such as HSTS, frame options and the Content Security Policy. If Superset and the proxy both set the same header, browsers may receive conflicting values or none at all. Confirm which layer owns each header, and test through the exact public hostname and TLS terminator users will use. Also confirm that the proxy forwards the protocol and host headers Superset needs to build correct redirect URLs.

Relaxed frame policy for embedding

Embedded dashboards need the page to load inside another site's frame, which conflicts with a strict frame policy. Decide which parent origins are allowed before you loosen frame options, and avoid a wildcard if your embedding partners are known. Confirm whether your embedding design also depends on cookie settings for iframes, since a stricter SameSite value can block the session inside the frame. Test an embedded dashboard from each allowed parent origin.

Deployment method and configuration source

The way you deploy sets where headers are configured. A container image, a PyPI install and a Kubernetes deployment each read configuration from different files, environment variables or custom resources. The Kubernetes operator is in alpha with a v1alpha1 API whose schemas may change between releases, so header settings written there may need rework after an upgrade. Confirm the configuration path for your method and keep it in version control.

External resources the policy must allow

Maps, web fonts, analytics scripts and custom branding assets each need an allowed source in the Content Security Policy. Inventory every external origin your dashboards and themes load, including tile servers for map charts. Confirm whether your environment can reach those origins at all, since an air-gapped network needs self-hosted assets instead. Each added origin widens what a compromised page can load, so keep the list short and reviewed.

Where to read the configuration reference before you change headers

Before you change any header setting, confirm in the Superset configuration documentation where Talisman and its Content Security Policy options are defined and how your installed version reads them. Header behavior is controlled through the Superset configuration file that your deployment loads, so the first check is which file your team edits, whether it is mounted into the container or baked into an image, and whether environment variables override it. Read the reference for the exact version you run, not the development branch, because option names and defaults can move between releases. The Apache Superset configuration documentation is the place to start, and record the version and the file path in your change ticket so a later reviewer can reproduce the setting.

Next, read the architecture documentation to establish which component actually serves the pages you are protecting. The Superset architecture documentation describes the Flask and React application, the metadata database, and the optional caching and worker components. Headers are set by the web application, so a reverse proxy or ingress that also adds headers can create duplicates or conflicts. Confirm with your platform team which layer owns HSTS, frame options and the policy, and whether the proxy strips or overwrites what Superset sends. Ask the same question about any separate static asset host, since a policy written for one origin will block resources served from another.

How DeployOpen scopes and delivers header hardening

Most engagements start with a written scope that names the Superset version, the deployment model, the browser surfaces in use and the headers to be changed. The scope fixes what is in and out before any configuration changes, so security and platform leads know what they are approving. It also sets the acceptance criteria that testing will be measured against.

  • Environments in scope: which Superset instances, proxies and staging copies are covered, and who owns each one.
  • Header set: whether Talisman, the Content Security Policy, HSTS and frame options are all in scope or a subset.
  • Embedding decision: whether any dashboard is embedded in another product, since that changes frame options.
  • Acceptance criteria: the pages, dashboards and export paths that must load and behave correctly after enforcement.
  • Change process: who approves each stage and where the written record is kept.

Before signing, confirm that the scope names your Superset version and that out-of-scope items such as the reverse proxy configuration are owned by someone else.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.