If you want to embed Eraser in a site with a sane Content Security Policy, you have a few choices. None of them are perfect. The right one depends on whether you care more about tight isolation, easy maintenance, or preserving a very strict policy posture.

I’ve had to make this tradeoff on production apps, and the pattern is always the same: the embed itself is easy, the CSP around it is where the mess starts.

This guide compares the common CSP approaches for Eraser embeds, with the pros, cons, and policy examples you can actually ship.

The baseline problem

Most Eraser embeds are loaded through an iframe. From a CSP perspective, that usually means you care about:

  • frame-src to allow the Eraser iframe
  • maybe child-src for older compatibility
  • frame-ancestors if you control the embedded app and want to restrict who can embed it
  • sometimes script-src, connect-src, or img-src if you use a script-based integration rather than a plain iframe

If your site already has a strict CSP, adding an embed often means poking a hole in it. The goal is to keep that hole as narrow as possible.

A real-world header from headertest.com shows the kind of policy many teams already run:

content-security-policy:
  default-src 'self' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
  script-src 'self' 'nonce-YzBmNmJiNjctNDEyNC00Yjk5LWFmNjEtOTQzNDA2MWNiMDQz' 'strict-dynamic' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
  style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://*.cookiebot.com https://consent.cookiebot.com;
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://api.headertest.com https://tallycdn.com https://or.headertest.com wss://or.headertest.com https://*.google-analytics.com https://*.googletagmanager.com https://*.cookiebot.com;
  frame-src 'self' https://consentcdn.cookiebot.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  object-src 'none';

That policy is already pretty disciplined. If you add Eraser, the first instinct should be: can I keep this to a frame-src change only?

Option 1: Allow Eraser only in frame-src

This is the cleanest setup if you’re embedding Eraser with a plain iframe and not loading extra Eraser scripts into your page.

Example:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-rAnd0m' 'strict-dynamic';
  style-src 'self';
  img-src 'self' data: https:;
  connect-src 'self';
  frame-src 'self' https://app.eraser.io;
  base-uri 'self';
  form-action 'self';
  object-src 'none';
  frame-ancestors 'none';

Or, adapting the headertest-style policy:

Content-Security-Policy:
  default-src 'self' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
  script-src 'self' 'nonce-YzBmNmJiNjctNDEyNC00Yjk5LWFmNjEtOTQzNDA2MWNiMDQz' 'strict-dynamic' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com;
  style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://*.cookiebot.com https://consent.cookiebot.com;
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://api.headertest.com https://tallycdn.com https://or.headertest.com wss://or.headertest.com https://*.google-analytics.com https://*.googletagmanager.com https://*.cookiebot.com;
  frame-src 'self' https://consentcdn.cookiebot.com https://app.eraser.io;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  object-src 'none';

Pros

  • Smallest CSP change
  • Keeps Eraser isolated inside its iframe
  • Doesn’t weaken script-src
  • Easy to explain in a security review

Cons

  • Only works if the integration is truly iframe-only
  • If Eraser later needs additional origins or a different host, the embed breaks until you update CSP
  • Teams sometimes forget frame-src exists because they rely on default-src, then wonder why the iframe is blocked

My bias: start here. If an embed can be supported with only frame-src, that’s almost always the best answer.

Option 2: Allow Eraser via default-src

This is the lazy version. It works, but I usually regret it later.

Example:

Content-Security-Policy:
  default-src 'self' https://app.eraser.io;
  script-src 'self' 'nonce-rAnd0m' 'strict-dynamic';
  style-src 'self';
  img-src 'self' data: https:;
  connect-src 'self';
  base-uri 'self';
  form-action 'self';
  object-src 'none';

Because frame-src falls back to default-src when not explicitly set, the iframe may load.

Pros

  • Minimal effort
  • Useful if your CSP is still early-stage and not fully broken into per-directive controls

Cons

  • Too broad
  • You’re allowing that origin as a fallback source for more than just frames
  • Harder to reason about later
  • Easy to accidentally permit more than you intended

I don’t like using default-src for embed exceptions unless the policy is already very simple. Once your CSP grows beyond a toy policy, explicit directives are easier to maintain and audit.

For a deeper breakdown of fallback behavior, the directive references on https://csp-guide.com are useful.

Option 3: Add Eraser to script-src, connect-src, and friends

Sometimes the embed is not just an iframe. Maybe you load an SDK, maybe the page communicates with the embedded app, maybe there’s dynamic rendering or API calls from your document context.

That leads to a policy like this:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-rAnd0m' 'strict-dynamic' https://app.eraser.io;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://app.eraser.io;
  frame-src 'self' https://app.eraser.io;
  base-uri 'self';
  form-action 'self';
  object-src 'none';

Pros

  • Supports richer integrations
  • Reduces breakage if Eraser needs scripts, fetches, or assets from its own origin
  • Sometimes the only practical option if the vendor integration is script-heavy

Cons

  • Much larger trust boundary
  • Easy to over-allow without realizing it
  • If you use 'strict-dynamic', host allowlists in script-src may not behave the way some developers expect
  • More moving parts during troubleshooting

That last point matters. With a nonce-based policy plus 'strict-dynamic', the browser gives trust to scripts loaded by already-trusted nonce-bearing scripts. Developers often keep adding hostnames to script-src even when those hosts are no longer the deciding factor. If your policy uses 'strict-dynamic', understand it before pasting more domains into it. The official CSP docs are worth reading here.

My rule: don’t put Eraser in script-src unless you know the page itself must execute Eraser-hosted JavaScript.

Option 4: Sandbox the iframe

This is less about CSP allowlisting and more about reducing risk from the embed itself.

Example HTML:

<iframe
  src="https://app.eraser.io/..."
  sandbox="allow-scripts allow-same-origin"
  referrerpolicy="strict-origin-when-cross-origin"
  loading="lazy"
  width="100%"
  height="600">
</iframe>

Paired with CSP:

Content-Security-Policy:
  default-src 'self';
  frame-src 'self' https://app.eraser.io;
  object-src 'none';
  base-uri 'self';
  form-action 'self';

Pros

  • Adds defense in depth
  • Limits what the embed can do in the browser
  • Good fit when product teams want the embed, but security wants tighter guardrails

Cons

  • Easy to break functionality
  • sandbox permissions are finicky
  • If the embed needs forms, popups, downloads, or top-level navigation, you may end up adding back a bunch of capabilities anyway

I like sandboxing when I don’t fully trust the embedded surface or when the feature is non-critical. For a core workflow app, sandbox restrictions often become a support treadmill.

Option 5: Put the embed on a separate route with a separate CSP

This is the most practical pattern for teams with strict CSPs on the main app.

Instead of loosening policy globally, serve the Eraser embed page from a dedicated route with a route-specific CSP:

  • /app keeps the strict app CSP
  • /embed/eraser gets a narrower, purpose-built CSP

Example Express middleware:

app.get("/embed/eraser", (req, res) => {
  res.setHeader(
    "Content-Security-Policy",
    [
      "default-src 'self'",
      "script-src 'self'",
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' data: https:",
      "connect-src 'self'",
      "frame-src https://app.eraser.io",
      "object-src 'none'",
      "base-uri 'self'",
      "form-action 'self'"
    ].join("; ")
  );

  res.send(`
    <!doctype html>
    <html>
      <body>
        <iframe
          src="https://app.eraser.io/..."
          width="100%"
          height="700"
          loading="lazy"></iframe>
      </body>
    </html>
  `);
});

Pros

  • Keeps your main application policy clean
  • Easier to review and test
  • Limits the blast radius of future CSP exceptions

Cons

  • More routing and deployment complexity
  • Sometimes awkward for SPA architectures
  • Teams need discipline to avoid turning the embed route into a junk drawer

This is my favorite option when the main app has a carefully tuned CSP and the embed is just one feature page.

For most developer teams, I’d rank the options like this:

  1. frame-src only
  2. Dedicated route with its own CSP
  3. Iframe + sandbox
  4. Broader per-directive allowlisting
  5. Rely on default-src fallback

That order reflects a simple principle: permit the minimum required by the integration.

If you’re starting from the headertest.com policy, the first thing I’d try is this small diff:

frame-src 'self' https://consentcdn.cookiebot.com https://app.eraser.io;

And nothing else.

If the embed works, stop there. Don’t preemptively add Eraser to script-src, connect-src, or img-src just because it feels safer to “cover all the bases.” That habit quietly destroys CSP quality.

Common mistakes

Forgetting that frame-ancestors is unrelated

frame-ancestors controls who can embed your page. It does not allow you to embed Eraser.

I still see this mixed up all the time.

Allowing a whole wildcard domain

This:

frame-src https://*.eraser.io;

might be convenient, but it’s sloppier than:

frame-src https://app.eraser.io;

Use the narrowest origin you can verify.

Debugging only in production

Use Content-Security-Policy-Report-Only first if you’re not sure what the embed needs.

Example:

Content-Security-Policy-Report-Only:
  default-src 'self';
  frame-src 'self' https://app.eraser.io;
  report-to default-endpoint;

Roll it out, inspect violations, then enforce.

Final take

For Eraser embeds, the boring answer is usually the right one: allow the Eraser origin in frame-src and leave the rest of your CSP alone.

If that’s not enough, isolate the feature on a dedicated route before you start widening script-src and connect-src. Once you loosen those directives, you’re no longer just allowing an embed. You’re extending trust into your page context, and that’s a much bigger deal.

If you need a refresher on directive behavior and fallbacks, the references at https://csp-guide.com and the official CSP documentation are the places I’d check first.