CLI tool
robinmoisson/staticrypt avatar
robinmoisson/staticrypt

StatiCrypt: Password-Protect Static HTML Without a Server

Password protect a static HTML page, decrypted in-browser in JS with no dependency. No server logic needed.

8,052 stars499 forksHTMLMIT

At a glance

What is it?
StatiCrypt encrypts a public static HTML file with AES-256 through WebCrypto and ships a password prompt that decrypts in the browser. It is a good fit for one-off pages on static hosting, and a poor fit for anything that needs real access control.
Who is it for?
Adopt StatiCrypt for a single page or a small folder of static HTML that you want to keep out of casual view on Netlify, GitHub Pages or similar hosting, and only when you can serve it over HTTPS. Do not adopt it as an access-control layer for customer data, paid content or anything where a leaked link is a real loss.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 86 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What StatiCrypt actually protects against

StatiCrypt takes a public static HTML file and turns it into a different HTML file: one that shows a password prompt and carries the original markup in encrypted form. The README frames the target clearly, saying it is for encrypting "the content of your _public_ static HTML file, to be decrypted in-browser without any back-end", so the intended deployment is static hosting such as Netlify or GitHub Pages. There is no server component to configure, no session store, no database.

The audience is therefore narrow and specific. Someone publishing a draft page, a private invitation, a client preview or an internal document on a host that only serves files. If you already run an application server with authentication, StatiCrypt solves a problem you do not have, and it solves it worse: the password check happens in JavaScript the visitor controls.

The important framing is that this is obfuscation with real cryptography behind it, not an access-control system. Anyone who has the encrypted file has the ciphertext, and anyone who has the password has the plaintext. There is no revocation, no per-user credential and no audit trail.

AES-256, WebCrypto and the client-side decryption loop

The mechanism is described in the README as AES-256 through WebCrypto. You supply a long password, StatiCrypt encrypts the HTML with it, and the output page performs decryption in JavaScript on the client. The encryption key is derived from the password and a salt, which is why the project keeps a `.staticrypt.json` file in the working directory.

That salt is the part most people get wrong. The README explains that the file is not secret and does not need protection, and that you can suppress it with `--config false`. But it also states that keeping the file matters: if the salt changes between runs, the derived key changes, and any auto-decrypt link you handed out stops working. The same applies to the remember-me feature across successive deployments. The README points to two ways to pin it, either committing the generated config or passing a fixed salt on the command line.

The consequence is that StatiCrypt is stateful in a way a single-file CLI usually is not. The encrypted output is not a pure function of the input and the password; it also depends on the salt in effect at encryption time. Treat `.staticrypt.json` as part of your build inputs, not as a cache artifact to be cleaned.

Installing StatiCrypt from npm and encrypting your first page

The package is published on npm. The README gives the install command and notes that you can run it through `npx` or install it globally. Node 16 or newer is required according to the `engines` field in `package.json`.

bash
npm install staticrypt

With the package available, encrypt a single file. The README notes that this creates an `encrypted/test.html` output and that omitting `-p` prompts for the password so it does not land in your shell history.

bash
staticrypt test.html

If you would rather not be prompted, the password can come from an argument or from an environment variable. The README documents `STATICRYPT_PASSWORD` for this, and states that `.env` files are supported.

bash
staticrypt test.html -p <long-password>

For a whole directory, the recursive flag encrypts every file it finds, and non-HTML files are copied through unchanged. That copy behaviour is what makes the overwrite pattern below practical.

bash
staticrypt dir_to_encrypt/* -r -d dir_to_encrypt

What you should see afterwards is an `encrypted/` directory containing your page with a password prompt in place of the original content. Open it locally over `localhost` and the prompt should accept the password you set.

Share links, remember-me and the salt trap

StatiCrypt can produce a URL that decrypts the page automatically. The README shows the `--share` flag with an optional URL, and the resulting fragment looks like `#staticrypt_pwd=` followed by a long hex string. A companion flag, `--share-remember`, appends `&remember_me` so the visitor is not prompted again on other pages.

The README is explicit about the risk here: the link contains the hashed password. Anyone who receives that URL can open the page. Sending it over a channel you do not control is equivalent to sending the password itself. The project's own warning is that you should keep your `.staticrypt.json` so the salt stays the same, otherwise re-encrypting invalidates the link.

There is a second-order problem the README does not resolve. Once a share link is out, there is no documented way to revoke it short of re-encrypting with a different password and salt, which breaks every other link and every remember-me cookie in circulation. For a one-time handoff that is fine. For a link posted in a team chat six months ago, it is not.

Where StatiCrypt is the wrong tool

The clearest limitation is stated by the project itself: v3 uses WebCrypto, which the README says is only available in HTTPS or localhost contexts, and anyone who needs plain HTTP must stay on v2. If your hosting or your internal network serves pages over HTTP, the modern version of this tool will not decrypt at all. That is not a bug to work around; it is a hard boundary of the browser API it depends on.

Beyond that, the security model deserves a plain statement. The password verification and the decryption both run in JavaScript delivered to the visitor. Someone who wants in can read the prompt template, modify the page in their own browser, or brute-force the password offline against the ciphertext they already downloaded. A long password raises the cost of that attack, which is why the README repeatedly says "long password". A short one does not.

If the content is regulated, personally identifying, or commercially valuable enough that a leak matters, StatiCrypt is the wrong layer. It cannot distinguish users, cannot log access, cannot expire a credential, and cannot be turned off for one person without turning it off for everyone.

StatiCrypt compared with a server-side gate

The obvious alternative is not another static encryption tool but an actual authentication layer in front of the file: HTTP basic auth at the reverse proxy, a platform's password protection feature, or a small serverless function that checks a session before returning the HTML. The difference in approach is where the secret lives. StatiCrypt ships the ciphertext to everyone and relies on the visitor's browser to hold the key. A server-side gate never sends the file to an unauthenticated request at all.

That difference decides most cases. A server-side gate gives you revocation, per-user credentials and logs, and it costs you a place to run code. StatiCrypt gives you a file you can drop on any static host with no runtime, and it costs you every one of those controls.

The README also points to a community project, `a-nau/password-protected-website-template`, as an example of using StatiCrypt in a CI build step. That is the shape StatiCrypt fits best: a build-time transform in a pipeline that already produces static output, not a runtime gate.

Maintenance, upgrades and the MIT licence

The repository is not archived, and the last push was on 2026-07-06. The most recent release listed is v3.5.0 from 2024-04-17, while `package.json` reports version 3.5.4, so published releases and the working tree are not perfectly in step. The runtime dependency list is short: `dotenv` and `yargs`. Node 16 or newer is required.

Upgrade cost is concentrated in the v2 to v3 transition, which the repository documents in `MIGRATING.md`. The README describes v3 as bringing a clearer CLI and a simpler `password_template` over v2, and warns that the WebCrypto dependency removes plain HTTP support. If you are on v2 because of an HTTP deployment, that is the upgrade you cannot make without changing your hosting.

StatiCrypt is MIT licensed, which permits commercial use and modification with the licence and copyright notice retained. That is a permissive arrangement, but it says nothing about whether the encryption approach suits your threat model, and it is not legal advice for your particular deployment.

Editorial conclusion

Adopt StatiCrypt for a single page or a small folder of static HTML that you want to keep out of casual view on Netlify, GitHub Pages or similar hosting, and only when you can serve it over HTTPS. Do not adopt it as an access-control layer for customer data, paid content or anything where a leaked link is a real loss. Before shipping, check three things: that your hosting serves the page over HTTPS or localhost, since v3 depends on WebCrypto and the README says v2 is the fallback for plain HTTP; that you commit or pin the salt so share links and remember-me keep working across deploys; and that you have a plan for rotating a password, because re-encrypting with a new password invalidates every previously issued auto-decrypt link.

Frequently asked questions

How do I encrypt my HTML code with StatiCrypt?

Install the npm package and run the CLI against your file, for example `staticrypt test.html`, which prompts for the password and writes an encrypted copy into an `encrypted` directory. You can also pass the password with `-p` or set it in the `STATICRYPT_PASSWORD` environment variable.

Does StatiCrypt need a server or backend?

No. The README states that decryption happens in JavaScript client side and that no back-end is needed, which is what makes it suitable for static hosting such as Netlify or GitHub Pages.

Why does StatiCrypt create a .staticrypt.json file?

It stores the salt used to derive the encryption key. The README says the file is not secret, that you can disable it with `--config false`, and that keeping the same salt matters because re-encrypting with a different one invalidates share links and remember-me behaviour.

Can StatiCrypt work over plain HTTP?

Not in v3. The README states that v3 uses WebCrypto, which is only available in HTTPS or localhost contexts, and that anyone who needs HTTP must use v2 instead.

What does the StatiCrypt share link contain?

It contains the hashed password in the URL fragment, in the form `#staticrypt_pwd=...`. The README warns that this auto-decrypts the file, so the link should be treated as sensitive.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. robinmoisson/staticrypt on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/robinmoisson-staticrypt.svg)](https://hysenlabs.com/projects/robinmoisson-staticrypt)