Security Tip: Use the Alpine.js CSP Build!

[Tip#68] If you use Alpine and a CSP on your app, you'll want to use the new CSP-friendly build to avoid needing `unsafe-eval` in your policies.

Security Tip: Use the Alpine.js CSP Build!

We’ve talked about using Content Security Policies (CSP) before, but if you’re not familiar with them, then check out my Getting Started with CSPs tip and CSP In Depth articles to learn what they are and how they work. We haven’t talked about Alpine.js before though, so if you’ve never heard of it, go check out the website: alpinejs.dev. It’s a lightweight javascript framework with a inline-to-HTML syntax designed to avoid having to write complex external scripts.

Alpine is a great way to write minimal javascript, however it’s inline syntax uses Function declarations, which violate the unsafe-eval CSP directive. This meant you always had to choose between using Alpine or running a CSP without unsafe-eval, which was frustrating when you wanted to lock down your CSP but still use the cool features Alpine has to offer.

As a result of many folks raising the issue, Caleb Porzio (the creator of Alpine and Livewire), recently announced a new CSP-friendly build of Alpine is available:

You can find all the details on the Alpine docs page: https://alpinejs.dev/advanced/csp.

The key difference with the CSP-friendly version is you can’t use inline scripts, but need to extract them into data components.

For example, you can’t do this with the CSP build:

<div x-data="{ count: 1 }">
    <button @click="count++">Increment</button>
 
    <span x-text="count"></span>
</div>

You need to do this instead:

<div x-data="counter">
    <button @click="increment">Increment</button>
 
    <span x-text="count"></span>
</div>
Alpine.data('counter', () => ({
    count: 1,
 
    increment() {
        this.count++
    },
}))

If you’re putting the work into running a strict CSP without `unsafe-eval`, then extracting components like this and being more intentional and structed around your javascript is a good trade-off, in my opinion.

Note that Livewire 3 doesn’t yet support the CSP build. Caleb is aware of the issue, and I’ll keep bugging him about it so we can make it happen.


If you found this security tip useful, subscribe to get weekly Security Tips straight to your inbox. Upgrade to a premium subscription for exclusive monthly In Depth articles, or drop a coin in the tip jar to show your support.

When was the last time you had a penetration test? Book a Laravel Security Audit and Penetration Test, or a budget-friendly Security Review!

You can also connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.