Font Awesome is one of those libraries that looks harmless until CSP gets involved. Then suddenly half your icons disappear, the browser starts shouting about blocked fonts or styles, and somebody suggests adding https: everywhere until the warnings stop.
That usually “works,” but it also guts your policy.
If you’re using Font Awesome with a Content Security Policy, the failures usually come from a few predictable mistakes:
- allowing the CSS but not the font files
- allowing the kit script but not the injected styles
- self-hosting some assets and loading others from a CDN
- relying on
default-srcand assuming it covers everything you need - fixing breakage with
unsafe-inlinewhen the real problem is somewhere else
Here’s what goes wrong and how I’d fix it.
Mistake #1: Allowing the stylesheet but forgetting font-src
This is the classic one.
You add Font Awesome CSS from a CDN:
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
Then your CSP allows that stylesheet:
Content-Security-Policy:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
And the icons still don’t render.
Why? Because the CSS loads, but the actual font files get blocked. Font Awesome CSS typically references .woff2 files from the same CDN, and those are controlled by font-src, not style-src.
Fix
Allow the CDN in both directives:
Content-Security-Policy:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
font-src 'self' https://cdnjs.cloudflare.com;
If you want to see why this matters, check the browser console. You’ll usually get an error like:
Refused to load the font 'https://cdnjs.cloudflare.com/.../fa-solid-900.woff2'
because it violates the following Content Security Policy directive: "font-src 'self'".
That error is basically the whole story.
Mistake #2: Assuming default-src is enough
A lot of developers read CSP once, see default-src, and assume it acts like a wildcard fallback they can rely on forever.
Technically, yes, it is a fallback. Practically, no, you shouldn’t build policies that way.
Here’s a real-world policy from headertest.com:
content-security-policy: default-src 'self' https://www.googletagmanager.com https://*.cookiebot.com https://*.google-analytics.com; script-src 'self' 'nonce-MDI5OWQzNWUtMGQ5ZS00ZmY2LTg0ZDItZjBlMTNmMjE5NzMw' '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'
Notice font-src 'self';.
If that site added Font Awesome from a CDN, the CSS might load if style-src allowed it, but the fonts would still fail because font-src is explicitly locked to self. Once you define a specific directive, default-src stops being relevant for that resource type.
Fix
Be explicit about the resources Font Awesome needs:
Content-Security-Policy:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
font-src 'self' https://cdnjs.cloudflare.com;
I prefer explicit directives over clever fallbacks every time. They’re easier to debug and harder to misunderstand six months later.
For directive behavior, the CSP reference at https://csp-guide.com is useful.
Mistake #3: Using a Font Awesome kit without allowing the right script and style behavior
Font Awesome kits are convenient, but they’re more CSP-hostile than plain self-hosted files.
A kit often looks like this:
<script
src="https://kit.fontawesome.com/your-kit-id.js"
crossorigin="anonymous"></script>
That script can inject styles and fetch assets dynamically. If your policy is tight, it will break in at least one of these places:
script-srcblocks the kit scriptstyle-srcblocks injected stylesfont-srcblocks the font filesconnect-srcmay matter depending on how the kit behaves
Broken policy example
Content-Security-Policy:
default-src 'self';
script-src 'self';
style-src 'self';
font-src 'self';
Fix
If you must use the kit, you need to permit the kit origin where relevant:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://kit.fontawesome.com;
style-src 'self' 'unsafe-inline';
font-src 'self' https://ka-f.fontawesome.com;
connect-src 'self' https://kit.fontawesome.com;
The exact hosts can vary depending on your setup, which is one reason I’m not a huge fan of kits in high-security deployments. They’re easy to drop into a page and annoying to model cleanly in CSP.
If your team cares about a strict CSP, self-hosting Font Awesome is usually the better call.
Mistake #4: Reaching for unsafe-inline when the issue is really external fonts
This happens constantly.
Icons don’t show up, somebody sees a style-related console error, and the fix becomes:
style-src 'self' 'unsafe-inline';
That may suppress one error while doing absolutely nothing for the actual blocked font request.
unsafe-inline is not a magic “make CSS work” switch. It only affects inline styles and style elements. If your Font Awesome CSS is external and the .woff2 files are blocked, unsafe-inline won’t solve that.
Fix
Match the fix to the blocked resource type.
If the browser says the font is blocked, update font-src:
Content-Security-Policy:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
font-src 'self' https://cdnjs.cloudflare.com;
If the browser says an inline <style> block is blocked, then look at nonces, hashes, or whether the third-party library is injecting inline CSS you actually want to allow.
Don’t weaken style-src unless that’s the real issue.
Mistake #5: Mixing self-hosted CSS with CDN font files
I’ve seen this after “partial migrations.”
A team downloads all.min.css and serves it locally:
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
But the CSS still points to CDN-hosted fonts, or the paths got rewritten in a weird build step.
Now the CSP looks safe:
Content-Security-Policy:
default-src 'self';
style-src 'self';
font-src 'self';
Yet the icons fail because the font URLs inside the CSS are not actually same-origin.
Fix
Open the CSS and check the @font-face declarations:
@font-face {
font-family: "Font Awesome 6 Free";
src: url("../webfonts/fa-solid-900.woff2") format("woff2");
}
Make sure those paths resolve to your own origin, and that the files exist where the CSS expects them.
A solid self-hosted setup looks like this:
Content-Security-Policy:
default-src 'self';
style-src 'self';
font-src 'self';
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<i class="fa-solid fa-user"></i>
And your files should be laid out predictably:
/assets/fontawesome/css/all.min.css
/assets/fontawesome/webfonts/fa-solid-900.woff2
/assets/fontawesome/webfonts/fa-regular-400.woff2
If you self-host, actually self-host all of it.
Mistake #6: Forgetting that SVG+JS mode changes the CSP story
Font Awesome doesn’t always use webfonts. Some setups use SVG with JavaScript. That can change which directives matter.
With the JS-based approach, you may need to care more about:
script-srcstyle-src- possibly
img-srcorconnect-src, depending on usage
Developers often copy a webfont-oriented CSP fix and wonder why nothing changes.
Fix
Figure out which Font Awesome mode you’re using before editing the policy.
If you’re loading a stylesheet and .woff2 files, focus on style-src and font-src.
If you’re loading a JavaScript bundle that replaces <i> tags with SVG, start with script-src and inspect the console for any follow-up violations.
This sounds obvious, but people skip it all the time.
Mistake #7: Debugging CSP from memory instead of from violation messages
CSP debugging gets much easier when you stop guessing.
If Font Awesome breaks, don’t start by editing five directives at once. Reproduce the page, open DevTools, and read the exact violation. The browser usually tells you:
- which resource was blocked
- which directive blocked it
- sometimes which fallback directive applied
That’s enough to make a targeted fix.
Example workflow
- Load the page with icons.
- Open the console.
- Look for CSP violations.
- Update only the directive that blocked the request.
- Reload and repeat until clean.
For production rollouts, I also like using Report-Only first:
Content-Security-Policy-Report-Only:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
font-src 'self' https://cdnjs.cloudflare.com;
report-to csp-endpoint;
That lets you see what would break before you enforce it. Official CSP documentation is here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP.
A good baseline policy for self-hosted Font Awesome
If you want the least painful setup, self-host the CSS and webfonts and keep the policy boring:
Content-Security-Policy:
default-src 'self';
style-src 'self';
font-src 'self';
img-src 'self' data:;
script-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'none';
That’s clean, predictable, and easy to reason about.
A good baseline policy for CDN-hosted Font Awesome
If you’re using a CDN stylesheet and webfonts, allow only that CDN where needed:
Content-Security-Policy:
default-src 'self';
style-src 'self' https://cdnjs.cloudflare.com;
font-src 'self' https://cdnjs.cloudflare.com;
img-src 'self' data:;
script-src 'self';
object-src 'none';
base-uri 'self';
frame-ancestors 'none';
No https: blanket allowlist. No unsafe-inline unless you genuinely need it. No random extra hosts because somebody copied a Stack Overflow answer from 2019.
That’s really the pattern with Font Awesome and CSP: treat fonts, styles, and scripts as separate concerns, and fix the one that’s actually blocked. Once you do that, the policy stays tight and the icons render the way they should.