toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 22 2024 02:43 PM Hi there is it possible to get rid off all inline scripts to be able to set up an effective content security policy and get the best secure CMS ever made or what I am asking is an impossible mission ? Or maybe could it be possible to automatically set up a random nonce for all of them included at the core of litecart and all plugins in the future ? I meant to say this could be safer for commercial things, both customer and seller sides. Regards
tim Founder From Sweden Member since May 2013 tim Nov 22 2024 03:12 PM Sure, lib_document is already collecting all inline scripting. So instead of outputting it on the page you could store it in the session and fetch it with another php process. Or write it to some temporary storage. https://github.com/litecart/litecart/blob/dev/public_html/includes/library/lib_document.inc.php#L239-L248 I was thinking of adding a nonce to version 3.0. I had a concept ready but wasn't sure if I was raising the bar too much for the users. I appreciate feedback on this conversation.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 22 2024 05:24 PM Throwing out some ideas because technically I'm just good for that. Got an A+ on MDN but not deserving 5 stars for it because my main website is not having js at all, only html5,css, that said.. I'm interested on this part for my spouse's coming soon website as she's selling some stuff. I understood it could be possible to link this lib_document to another included php function. Maybe for user's simplicity one dedicated plugin (on, off) could fetch needed informations and with a starting point looks like default-src 'none' (hardenned for A+) or default-src 'self' (not A+, more likely A) and let them possibilities to write further directives on it to an htaccess file for example.
tim Founder From Sweden Member since May 2013 tim Nov 23 2024 03:19 AM This is the policy I had in mind, but nonce may prevent cache. header('Content-Security-Policy: '. implode(';', [ "frame-ancestors 'self'", "script-src 'nonce-". functions::escape_attr(self::$nonce) ."' 'strict-dynamic'", "style-src 'self'", "img-src 'self'", "base-uri 'self'", "form-action 'self'", ])); To use nonce for all inline and external resources.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 23 2024 10:47 AM interesting, that's concrete. exclude nonce from being in cache is possible ?
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 23 2024 02:25 PM don't like much to share this kind of link , apologize my weakness but as an example it allows not to cache specific content and/or some dynamic content.
tim Founder From Sweden Member since May 2013 tim Nov 23 2024 11:42 PM No I don't think it's possible to serve cached content using nonce. We need cache to do it's part. This leads me to believe SHA256 is better but will increase CPU usage. Which leads me back to square one wondering if there is a way that doesn't have disadvantages?
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 23 2024 11:51 PM There is only one advantage, security. another thought, if nonce lifespan is the same as cache lifespan or logged-in cache lifespan would it lead to some troubles ?
tim Founder From Sweden Member since May 2013 tim Nov 24 2024 04:19 AM There is no lifespan for nonce, hence it's name "number used once". It's a one time used string. I'm gonna need to do some field testing with nonce vs sha256 to see how browsers react to caching the resources.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Nov 24 2024 10:21 AM all right then, it looks simple on the paper ... wish you can do about it
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 22 2025 04:15 PM I'm working on this at the moment for my own site. Is there a best way to implement it? I'm currently writing a VMod and making changes to a clone of the template (that has other changes in). But I could fork the repo and make PRs if that helps. I hit the nonce and caching problem, but have a really simple workaround. You just need to do a str_replace before and after caching. I use mod_csp and Apache-level headers, so I've even been considering how it could work for people who don't have that installed.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 22 2025 06:20 PM Hello there, your reply rings like a good new. I'm following this thread with interest.
tim Founder From Sweden Member since May 2013 tim Mar 23 2025 11:40 PM The easiest way to add some security to this thingy is adding hash checksums. echo '<script defer integrity="sha256-'. base64_encode(hash_file('sha256', $file, true)) .'" src="'. document::href_rlink($file) .'"></script>';
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 25 2025 07:57 PM I've just been using nonces for now on the basis that the scripts may change and I don't want to keep track of the checksum or keep external copies of inline scripts and styles updated. A hash could be generated and cached on the fly, but I'm not sure it adds much over a nonce. Nonce: File changes, nonce says "trust it", visitor runs whatever was served Integrity checksum: File changes, checksum is recalculated, checksum says "trust it", visitor runs whatever was served My current approach puts a nonce into all of the templates and then the "collect the scripts" and "collect the styles" steps look for the nonce as well (rather than just the plain tag). Unless I'm missing something, I think that's about as secure as we can get without hard-coding the checksums and keeping them up-to-date. If someone finds a way to inject a script tag via a variable then it won't have a nonce, it won't get collected, so it'll get served up wherever it is in the code unchanged, and then it'll fail the CSP. If someone finds a way to inject values into variables so that a nonced inline script now has bad code in it then that's bad and we'd be better off with external scripts. But the quick review that I did of inline scripts didn't find any that looked dangerous. It would have to be an admin compromise with a bad product name or something. If someone finds a way to modify the template and get the nonce in there as well... well, it's game over at that point anyway. If they can edit a template file then they can basically put any code that they want in there!
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 25 2025 08:25 PM What is the way for a person with bad intentions not to find this ways ... a strong and full CSP starting with default-src 'none'; ... Most of the time on CMSs the only things I couldn't set up on CSP are inline scripts/styles. Ended up to build manually one template without scripts at all, but then .. this is not friendly coding .. If there is someone like you can build a kind of automatic set up for that with nonces, god will bless you and me too. Saying that many broke their teeth trying to, me ve virst
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 25 2025 08:45 PM It's not perfect, but this VMod is what I've got so far. My CSP is basically style-src: 'self' https://cdnjs.cloudflare.com/ajax/libs/tinymce/ 'nonce-%{CSP_NONCE}e (where %{CSP_NONCE}e is an Apache environment variable from mod_cspnonce) and script-src: 'self' https://cdnjs.cloudflare.com/ajax/libs/tinymce/ 'nonce-%{CSP_NONCE}e' 'strict-dynamic'. I've got some extra domains for Google fonts etc, which is why I think it might be better to do the policy at the server level if possible. Otherwise we need to start adding settings in the admin control panel. As I said, I'm happy to do this in a fork and make a PR if that's the best option. The VMod lets me do it and distribute it without getting too closely coupled to the code, but I think there might be bits that won't work without changes to JavaScript files. If that's necessary then a PR would be best, if Tim will accept it, to avoid me distributing parallel copies of scripts and keeping them up-to-date. ibboard_secure.xml
tim Founder From Sweden Member since May 2013 tim Mar 25 2025 09:22 PM I want the best solution out of every aspect. Simple, minimum maintenance, dependency free. integrity="sha-256-{hash}" lets us sign the content with a checksum. Thoughts on using integrity hash checksum?
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 25 2025 09:38 PM I don't see the benefits of a checksum over using a nonce except for external files. If it's part of LiteCart then changes are under our control and either we trust the script or we shouldn't be serving it. Whether it has a nonce or a checksum, it has the same amount of trust. The only way the checksum stops being valid is if someone replaces the file on the server (or intercepts HTTPS and injects a replacement file), and the moment that happens then they can just replace other content including the checksum. The place where the checksum helps is with CloudFlare and other third-parties to cover the "what if {third-party} ends up serving a different file under the same name?" situation. I'll see what I can put together over the weekend in a branch rather than a VMod, and try to cover server-based CSP and additional third-party content (e.g. Google Fonts)
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 25 2025 10:07 PM Many thanks idboard, you are very kind.
tim Founder From Sweden Member since May 2013 tim Mar 25 2025 10:19 PM If it's part of LiteCart then changes are under our control and either we trust the script or we shouldn't be serving it. Even if we trust our own scripts, an integrity hash would guarantee no middle man attacks or file corruption.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 25 2025 10:57 PM Potentially. But HTTPS should prevent on-path attacks. And if they can intercept and replace the script, what's stopping them replacing the hash as well? While it will prevent browsers executing scripts that corrupted between reading and receiving, I'd expect that a lot of scripts would fail to run anyway if they corrupted. It wouldn't catch on-disk corruption because we'd just hash the corrupt data. Any read corruption could hit both the hash and the main read (or the hash could be wrong and the read could be right - if it's happening then you need to fix the server issues rather than worrying about CSP!). And HTTPS HMAC should reject any packets that corrupt in transit. There's probably a slim situation that it'll protect against, but I think we're getting to tiny probabilities for moderate overhead.
tim Founder From Sweden Member since May 2013 tim Mar 26 2025 03:21 AM Very good points, all of them.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 26 2025 07:23 AM Many litecart users may not have a full access to server side (eg:free hosting). htaccess file suggested ?
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 26 2025 07:28 PM Yeah, some users will be on shared hosting (I wouldn't want to run anything on free hosting these days, especially not professional/commerce stuff!) so they might not be able to add mod_cspnonce. But they can set almost all other config in htaccess files. I'll look at what the options are to make sure people aren't prevented from using it. But I'd also rather have complete control at the server level instead of trusting the PHP script to inject the right headers. It's just another layer of security (like write-protecting files so that PHP can't rewrite them, rather than relying on "PHP shouldn't be rewriting them").
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 26 2025 07:55 PM Agreeing to put conditions of use so there is no misunderstood about it. Should I guess this will be an option to add or not to litecart ? For those who can and those who cannot ? I'm just showing a picture to say litecart is free but not free in that case, not because of litecart but because this mod needs imperatively to have a non-free hosting provider with full server access and control to be effective and efficient. In the meantime there are some for a few bucks per month ...
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 26 2025 08:07 PM CSP is just a header, and PHP can add headers (as per Tim's earlier post). So it can definitely be made compatible with free and shared hosting. It's just that my personal security preference is that CSP is done at the server level to give the additional layer of separation.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Mar 26 2025 08:21 PM I was confused and you made it clear.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 29 2025 09:55 AM Initial changes on a WIP. Not tested yet, but based on my VMod that I was testing. https://github.com/litecart/litecart/compare/dev...IBBoard:litecart:IBBoard/content-security-policy Still lots of style="..." attributes to sort out. And some settings to add (e.g. "let server set header" and "report only mode"), as well as adding the header for sites that don't have mod_cspnonce installed. I want to double-check the scripts as well because I just added nonces to all of them without checking what they do.
tim Founder From Sweden Member since May 2013 tim Mar 31 2025 03:02 AM Hey did you know lib_document extracts style and js on pages, and group them in a new element? https://github.com/litecart/litecart/blob/dev/public_html/includes/library/lib_document.inc.php#L173-L206 In 3.0 there will be a document::load_style($url) and document::load_script($url) to simplify implementation. Your commits are giving me some ideas how to support i.e. Apache modules.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Mar 31 2025 07:47 PM Hey did you know lib_document extracts style and js on pages, and group them in a new element? https://github.com/litecart/litecart/blob/dev/public_html/includes/library/lib_document.inc.php#L173-L206 Yeah, I make use of that as part of the "make sure we're grabbing authorised tags". It's also a big part of working round style="…" attributes. In 3.0 there will be a document::load_style($url) and document::load_script($url) to simplify implementation. One of the things that made CSP annoying in Wordpress was the plugins that didn't use the functions for adding scripts/styles. If LiteCart is going to gain both the functions and CSP at the same time then that would make it a lot easier to enforce "use these functions or else things may break". I'm happy to look at the 3.0 code. If it's in a reasonable state then there's not much point in me migrating a site to 2.x only to have to migrate to 3.x a little while later.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Apr 2 2025 05:19 PM I think litecart v3.0 will have some major changements, not guessing when it will be released but guessing we'll have to wait for ...
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Apr 2 2025 08:23 PM Tim declined a pull request to improve the Unicode handling in LiteCart (including most emoji) with a message saying "This is already implemented in 3.0. Otherwise I would happily like to accept this commit. I'm working hard to finalize many things in 3.0 so it can be released". So I'm assuming that it's not a long way off. At the very least, it sounds like 2.x won't get any more significant updates. But yes, as it's v3 then presumably there will be incompatible API changes.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Apr 7 2025 08:45 PM Given the uncertainty over when Litecart 3.0 is back and whether it's worth doing PRs on the 2.x branch, I'm going to go back to trying to implement this as a VMod. Starting by backporting some of my improved approaches from the branch to the VMod.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Apr 7 2025 08:59 PM Oh well, I'm looking forward and I'll try to try to give it a try.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Apr 16 2025 03:32 PM Here's a work-in-progress VMod. I think I've fixed everything that's user-side. Unlike the earlier version, this one is now very specifically altering each situation, as well as handling style="…" attributes. I'm now working on the admin control panel. Note: There's a custom app.js but it looks like it's only needed because of two setTimeout() calls that pass the function name as a string. I'll put in a PR so that Tim can avoid that and I can drop the custom file. ibboard_secure.zip
ibboard Developer From United Kingdom Member since Jan 2025 ibboard Apr 17 2025 05:02 PM I've got a lot of the admin control panel fixed now. I think the biggest problem is going to be the WYSIWYG editor. It uses inline styles for some things and the dev's response to a previous request was basically "nope, don't care about security - do it yourself" with a wave in the general direction of the documentation. I think it should be possible to make it compatible if I sacrifice the full RGB colour options and just limit it to the built-in palette. If you want more colours and you're adding a CSP vmod then you probably know how to use "source code" mode and add a properly defined class 😁
toulibre LiteCart Fan From France Member since Jan 2021 toulibre Apr 17 2025 08:23 PM I guess many started to create their things with inline styles/scripts everywhere without thinking at all about CSP, just have to test at MDN any website you would like to see the poor security results on the web. Still looking forward, I'm already impressed by your work anyway !
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 3 2025 03:53 PM I'm still working on this. I think I've got pretty much all of the app completed except the WYSIWYG editor. It uses the execCommand API, which makes certain assumptions that are proving really difficult to work around (either the built-in commands use style attributes that fail CSP, or it's hard to rewrite the HTML rather than replacing objects). I've got the editor working with CSP-compliant alignment and I've got simple colouring. But once you start layering and overlapping colours (e.g. [green text on default background][green text on yellow background][default text on yellow background] which you'd do by highlighting parts 1 & 2 and making them green, then parts 2 and 3 and making then yellow background) then it breaks down. And it's even worse once you go across block-level boundaries. I want to try and solve it because it's an interesting challenge. But I'm also considering dropping it and going "You're trying to use a Content Security Policy - you can probably manage a bit of HTML editing".
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 3 2025 04:30 PM Next alternative could be InputEvent work still in progress. Dropping it is best idea till one day better editor popup, or maybe Trumbowyg would perhaps consider now to review his code since execCommand is obsolete
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 8 2025 08:52 PM Okay, I've got what I'm calling v0.90. It should be about complete, but I don't want to call it 1.0 yet because I might have missed something! I might make some changes to the edits as well - I'm being very specific with the <script> and <style> tags, but as the VMod runs before the file is included by PHP then I think I could get away with a simpler "just find and replace the tag" operation and still be secure. Please check it out and give feedback. I'll try to add CDN support over the weekend, but for now it assumes a default Litecart install that's all locally hosted. ibboard_secure.zip
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 9 2025 07:23 AM Just installed a new local test version especially. Thanks for instructions on Readme file I'll install this evening your module to tell you :)
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 9 2025 03:30 PM So I've got v0.99 and activated on fresh litecart install. There is this message appearing all the time on the top Warning: Could not create link for missing resource (/var/www/html/test-litecart/public_html/ext/trumbowyg/plugins/colors/ui/trumbowyg.content.colors.css) in ~/vmods/.cache/includes-library-lib_document.inc.php (Line 329)http://127.0.0.2/public_html/ext/trumbowyg/plugins/colors/ui/trumbowyg.content.colors.css"> trumbowyg at his best I guess ... I'm teasing
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 9 2025 08:04 PM Ah. Sorry. I didn't include the files for the replacement colour plugin for the WYSIWYG editor because I didn't get it to work, but I forgot about the references to it in the VMod. Because I still have the file then it didn't error for me. I also spotted that the CSP plugin was missing as well - I'd managed to zip the folder but not the contents (because I was using the command-line on my server and didn't check what was in there). Those files should be there now. Hopefully v0.91 fixes that. ibboard_secure.zip
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 9 2025 08:59 PM It's ok don't worry, this is the deal to try So everything is activated and I see nothing wrong on admin part but the website part seems not to be right Do I have something to do on settings or should it work as it is ? That's still a fresh install, I touched nothing at all except changed language. Check screenshots below
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 9 2025 09:34 PM I'm using mod_cspnonce to generate the nonce value on my server. It looks you're not and I'm not handling the "if it isn't set then generate our own value" situation correctly. I'll look at it tomorrow, but basically the second replacement in includes/library/lib_document.inc.php needs to do something better than self::$nonce = isset($_SERVER['CSP_NONCE']) ? $_SERVER['CSP_NONCE'] : base64_encode(random_bytes(18)); to check whether the value is set (it has been a while since I did much PHP, and I started with PHP4, so I forget which functions treat "no such index" as falsey and which treat it as an error!) Strange that you're not getting the same error on the admin side, though!
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 10 2025 08:58 AM All right then can you tell me if I forgot something to do so, sudo apt install apache2-dev then download repository at https://github.com/wyday/mod_cspnonce and open terminal into downloaded folder to type sudo apxs -ci mod_cspnonce.c I restarted apache2 but I got same error message on website and now on admin part too .. Is there any other commands ? Is my mod_cspnonce just running like that ? There is perhaps more lines to add on Readme file for general understanding.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 10 2025 12:36 PM I manage my server via Puppet and pre-package the module, so I didn't take those steps. I've got an Open Build Service repo that packages the modules for Ubuntu 22.04 and 24.04, so I can install it with apt. (I used to have a few more things in there, not just a module that hasn't changed in years!) I've then got /etc/apache2/mods-available/cspnonce.load which contains LoadModule cspnonce_module /usr/lib/apache2/modules/mod_cspnonce.so (update as appropriate for wherever the .so file is). After that, it just seems to work.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 10 2025 01:04 PM Seems to have to setup a lot of things before to be able to use your vmod with no errors. I'm using debian bookworm and after install from this repository on github and adding line into httpd file when I call mod_cspnonce throught a2enmod it just tells me this module doesn't exist even if it is present in apache modules folder. I'm going to try your repository later and send you feedback.
ibboard Developer From United Kingdom Member since Jan 2025 ibboard May 10 2025 01:28 PM I'm enabling Debian 12 on the repo. It should mostly be the same as Ubuntu for the Deb build instructions, so hopefully it just works and builds the package.
toulibre LiteCart Fan From France Member since Jan 2021 toulibre May 10 2025 04:13 PM Thanks, very simple like this, no pain in the head or neck. Now I'm having both sides working fine. When inspecting with firefox console there is this message, Content-Security-Policy: Analysis of “report-to” failed, because the directive is unknown.