robinmoisson / staticrypt

Password protect a static HTML page, decrypted in-browser in JS with no dependency. No server logic needed.
https://robinmoisson.github.io/staticrypt/
MIT License
7.1k stars 431 forks source link

Page not protected until reload #179

Closed techbridgedev closed 1 year ago

techbridgedev commented 1 year ago

EDIT: This seems to be because the default behavior of Staticrypt is not to encrypt the page if document.referrer() != null. If any page is navigated to by a link in the same domain, it doesn't encrypt.

I successfully protected my entire Docusaurus site using this plugin; however, if I attempt to only protect 2 directories build/docs/web-docs/ & build/docs/categories/website-docs, the login prompt does not appear for the encrypted pages.

What's happening

After running the command, Staticrypt successfully encrypts the specified pages. I can see that they are inspected by viewing them in my IDE. But when I navigate to them I'm not prevented from viewing them — unless I reload the restricted page; then I get the password prompt.

I've checked to see if there is something cached in the browser but can't locate anything that might be responsible.

I'm not checking the "remember me" checkbox, so local storage is empty.

I am using .env to store the password.

I'm only testing on the local site; I don't want to push this to live (which is currently protected on all pages) until I've fixed this bug.

What should be happening

I expect to be prevented from viewing the pages.

My setup

StatiCrypt version: 3.3.0 Node version: 18.7.0 Any additional relevant context, if any:

package.json scripts:

    "encrypt-web-docs": "staticrypt ./build/docs/web-docs/* -r -d ./build/docs/web-docs/ --template-title 'Restricted Access' --template-instructions 'This portion of this site is restricted. Please enter your password to view this site. If you forgot your password, please contact <a href=\"mailto:webmaster@acme.com\">the site administrator</a>.' --template-button 'Unlock' --template-color-primary '#1b365d' --template-color-secondary '#142645' -t ./src/auth/login.html --remember 30",
    "encrypt-web-docs-cat": "staticrypt ./build/docs/category/website-docs/* -d ./build/docs/category/website-docs/ --template-title 'Restricted Access' --template-instructions 'This portion of this site is restricted. Please enter your password to view this site. If you forgot your password, please contact <a href=\"mailto:webmaster@acme.com\">the site administrator</a>.' --template-button 'Unlock' --template-color-primary '#1b365d' --template-color-secondary '#142645' -t ./src/auth/login.html --remember 30",
    "encrypt": "npm run encrypt-web-docs && npm run encrypt-web-docs-cat",

The only substantial differences in my template from the default are styles + I changed the submit input to a button (it works). I did this to improve accessibility and to be able to add a padlock icon (SVG) to the submit field.

robinmoisson commented 1 year ago

Hi @techbridgedev, thanks for reporting!

That's pretty weird. Once encrypted by staticrypt the files do not have the cleartext content (nor the password) and it's impossible for staticrypt to decrypt the page without the password. The only option for you to see the unencrypted page is if the page has been opened or cached already, since you are replacing the files you are encrypting.

I'm not sure I understand your exact steps - how do you navigate to the pages ? If you open the page before encryption it'll be shown in the clear, then if you encrypt them you need to refresh the page to show the encrypted version, but I'm assume that's already what you're doing?

Also thanks for the trick to replace the files with the encrypted ones with staticrypt /folder/* -r -d /folder that's pretty neat, I'm going to add that to the README.

techbridgedev commented 1 year ago

Hi, @robinmoisson,

To test whether it was a caching issue, I opened the site in an incognito window. Did a hard reload & flushed the cache. Kept dev tools opened on the network tab with "disable cache" selected.

Then I navigated to a protected page via the links in my site's menu. The page loads with no encryption.

But if I reload the page or navigate to it directly by pasting the URL in the web browser address bar, it loads the login screen.

As a workaround, I'm forcing the page to reload on the first visit, then storing the state via session storage so it doesn't reload when you navigate to any of the other protected pages. This forces the login screen to appear on the first visit. But it's trivial to get around since you can just navigate to another protected page from the homepage; it's more like security by obscurity than a real solution.

The only option for you to see the unencrypted page is if the page has been opened or cached already, since you are replacing the files you are encrypting.

Does this mean that once a page has been visited by anyone, it has been unencrypted for everybody? I was under the impression that decryption takes place in the browser and that the encrypted files themselves are untouched.

It's still possible this is a caching issue. It's a static site built with Docusaurus, but the host (Vercel) does employ edge and data caching.

EDIT: I get the same behavior for local setup, so it's probably not Vercel's caching either.

techbridgedev commented 1 year ago

More info: if I open the unencrypted page source in a new tab after performing the steps above (visit the page by link without reload), I see the encrypted page source.

robinmoisson commented 1 year ago

Hey @techbridgedev, thanks for updating and sorry for the late reply. Did you resolve the issue?

Does this mean that once a page has been visited by anyone, it has been unencrypted for everybody? I was under the impression that decryption takes place in the browser and that the encrypted files themselves are untouched.

You're correct, the decryption happens locally in the browser and the original encrypted files are untouched (everything happens in JS and the browser has no way of writing back anything to the server). So no, when you decrypt the file it's decrypted only for you, and if you didn't check the "Remember me" checkbox it's decrypted only until your refresh/navigate away.

Regarding navigating to a page through your menu and seeing the page unencrypted: I guess that could happen if you're website is an SPA that includes the unencrypted code, and navigating through the menu means the SPA is showing the unencrypted page without triggering a fresh request to the server that would show the encrypted page? It's hard to say without knowing more about your setup, what techno are you using and what does your menu code look like? What requests are made in the Network tab of your browser when you navigate to the page and it shows unencrypted?

In either case, the problem would be that the SPA is still including the unencrypted version of the page somewhere. If you encrypt pages with staticrypt (and confirm that yeah, the html you get and are uploading is indeed the one created by staticrypt and doesn't contain the cleartext version), then the unencrypted information is just not there in that html page. There is no way for staticrypt to show it by mistake, the password is needed to decrypt the ciphertext and it's impossible to recover the data without that key.

So that's where I would look.

techbridgedev commented 1 year ago

I'm using Docusaurus (static website builder, not SPA) served by Vercel & encrypting pages in a subdirectory of my build docs folder.

In theory, when Vercel builds the site it is running the encrypt command as the final step. The build logs seem to confirm this. You can see my build command in a previous comment; I'm replacing the original index.html files with the encrypted ones as the final build step.

I can share a link if you have a private way for me to contact you (e.g., DM or email). I'd prefer not to post the URL here since it's public.

robinmoisson commented 1 year ago

Sure, you can send it to my protonmail address which is public in SECURITY.md - it's robin.moisson, at protonmail.com.

robinmoisson commented 1 year ago

I haven't received any email - I'm closing this issue since it doesn't seem to me like it's related to staticrypt, which from what I understand does its job encrypting the files (and something weird happens afterwards).

Feel free to re-open if you think that's incorrect, and if you want to reach out privately on your setup my inbox is still open. Thanks!