Open tabacitu opened 4 months ago
This would also be a good opportunity for us to bump the dependency versions. It's been a while since we last did that.
@tabacitu thank you for opening the issue based on my email.
In addition to singing the includes I still woud appreciate if the old behavior could still be used via some kind of switch.
It is harder to review and ship such CDN contents than locally build packages.
@tabacitu What's the status on this? This blocks us from upgrading
Thanks for the reminder @amenk !
In addition to singing the includes I still woud appreciate if the old behavior could still be used via some kind of switch.
We do not plan on adding back the old behaviour - that would consider a HUGE breaking change, and a step back for us.
It is harder to review and ship such CDN contents than locally build packages.
I agree - we did plan a v2 for Basset that included importmaps
and integrity checks, but we never got around to it.
Regarding actually implementing SRI in Basset, here are the possible solutions we are considering:
SOLUTION 1. Add the integrity hashes to all our assets, manually. For example instead of:
@basset('https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css')
we can do:
@basset('https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css', true, [
'integrity' => 'GADhaOJCr6lsUqdHJnYcH/QaARzVT92beGzAYxLTSoxUorHjQZci1FW+X9BqbnE3%',
'crossorigin' => 'anonymous',
])
This will output:
<link href="/storage/basset/cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css?187e21de716e"
rel="stylesheet"
type="text/css"
integrity="GADhaOJCr6lsUqdHJnYcH/QaARzVT92beGzAYxLTSoxUorHjQZci1FW+X9BqbnE3%"
crossorigin="anonymous" />
THE PROBLEM with this solution is that it's manual. It requires us to MANUALLY add the hash for each asset we use. And to update it, every time we update the asset. This isn't sustainable. And it would 100% break, when loading local assets from userland, that the developer can change (eg. /storage/basset/vendor/backpack/theme-tabler/resources/assets/css/colors.css
) - but one could argue we shouldn't be using integrity tags on those anyway, they're local 🤔
Then again... we can speed this up by using a service like https://www.srihash.org/ that generates the hash... so it wouldn't be THAT much of a trouble the first time we do it. It would still be unsustainable long-term... but not a HUGE deal.
SOLUTION 2. NOT AN ACTUAL OPTION. We could generate a hash on-the-fly, when basset()
is run and the asset internalized. We could use PHP to get a hash of that asset and use that as the integrity tag. BUT. That defeats the purpose of SRI. SRI is supposed to cover file integrity at the source. We would be "fetching anything from the CDN". Then adding "fake" integrity tags. No bueno.
SOLUTION 3. We could modify the php artisan basset:cache
command to also get the hash and store it in the basset cache file (easily done with something like curl -s https://cdn.datatables.net/1.13.1/css/dataTables.bootstrap5.min.css | openssl dgst -sha384 -binary | openssl base64 -A
). Then when basset()
is called on an asset... basset would check if the hash is present in the cache file... and if so, use that hash as an integrity tag. The idea here is to basically not only store the URL in the basset cache file... but also the hash attribute, and use it whenever someone does basset()
for that asset. This would be better than SOLUTION 2 because it doesn't happen on runtime. It happens on deployment. So yes, if an asset has been compromised at the source, between deployment and pageload... the SRI tag will be useful. But... what if the asset has been compromised before deployment? 🤷♂️
I would say:
That being said, SOLUTION 3 doesn't render SOLUTION 1 worthless. In fact, for the assets where the vendor has published a has in the docs page, it's preferrable to have that hash written along with the URL. Then Basset won't have to generate a hash for it, we just test against it.
What do you think @amenk ? Do you see SOLUTION 1 or SOLUTION 3 as being rock-solid? If not, any other solution you have in mind?
I actually see SOLUTION 1 as being quite okay. That's what I had in mind.
Yes it's manual - but that's the whole point: We have to consciously choose a version, eventually do a short review for known issues and then calculate the hash.
And such updates don't seem to happen so often in backpack - so this should be fine. (see https://github.com/Laravel-Backpack/CRUD/blame/db386bffdb55584ea2ed6dc738bb7aa771420828/src/resources/views/crud/list.blade.php#L152)
We can always add a artisan scaffolding tool
php artisan basset:generate-tag https://example.com/foo.js
which generates the proper @basset()
tag including SRI, later to simplify the process when adding new resources.
but one could argue we shouldn't be using integrity tags on those anyway, they're local 🤔
yes, I would say so - this is a much narrower attack vector. I think SRI is mostly meant to 3rd party stuff.
A user just suggested on email that we should add integrity tags to our assets.
I think it's a small change that would go a long way towards preventing some attacks. A bang-for-buck change.
Especially now that supply chain attacks are more common (see polyfill incident in July 2024), we can do a little more to prevent this kind of attacks.
I suggest we go through all our repos, one by one, and add integrity tags. Afaik Basset already supports it, it's just a matter of actually copy-pasting them to our code as well.
What do you guys think, isn't this an easy and impactful thing we can finish by the end of the month?