Ardis Lu [Mon, 25 May 2026 00:30:25 +0000 (17:30 -0700)]
Use standard ES types
`BufferSource` is from web IDL (`lib.dom.d.ts`), which is not always imported. `ArrayBuffer` and `ArrayBufferView` are from the ES spec (`lib.es*.d.ts`) so they should always be available.
Ardis Lu [Mon, 25 May 2026 00:21:14 +0000 (17:21 -0700)]
Pass PRF as raw bytes instead of string
Avoiding string serialization is more performant and simpler, and more importantly reduces the places where this sensitive value is written to memory. By keeping the value in buffer we can immediately zero it out manually instead of waiting for garbage collection.
The value is still "leaked" via DevTools inspection and other points in the network stack, but that is out of the control of JS.
Ardis Lu [Sun, 24 May 2026 06:16:34 +0000 (23:16 -0700)]
Use custom `Envpass-Challenge` header
Separating `challenge` from `prf` allows more flexibility to change the format that `prf` is bridged (e.g., to `application/octet-stream`) and it is more consistent with how similar material is usually passed in other APIs.
Ardis Lu [Fri, 22 May 2026 06:21:00 +0000 (23:21 -0700)]
Set client-side security headers
The CSP `img-src 'none';` will block the empty data URL used for the favicon, so just remove it. The original purpose of the empty data URL was to prevent `favicon.ico` requests, but that is also accomplished by this CSP.
Ardis Lu [Fri, 22 May 2026 05:33:15 +0000 (22:33 -0700)]
Verify `Content-Type` header on POST
Setting this header to `application/json` forces the request to be CORS preflighted (i.e. not a "simple request"). This is further security hardening against cross-origin requests from a web browser.
Ardis Lu [Fri, 22 May 2026 05:20:18 +0000 (22:20 -0700)]
Verify `Origin` header on POST
This is security hardening against cross-origin requests. Although the server already does not send CORS headers (so web browsers should already block a cross-origin POST), there should still be a server-side `Origin` check as defense-in-depth.
Ardis Lu [Thu, 21 May 2026 05:59:14 +0000 (22:59 -0700)]
Only get passkey if actually required
Getting passkey is not required when `encrypt` is run on a file where all variables are already encrypted, or `decrypt` is run on a file where all variables are already decrypted.
Previously, the passkey flow would always initiate. Now, it will only initiate the first time it is required.
This change improves the UX in situations where `encrypt` or `decrypt` are called on a continuous basis. For example, when calling `envpass encrypt` in a `prestart` npm script hook.