Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ CLI as well as the browser.
Everything else — protocol, file format, web UI, configuration knobs — is
unchanged and remains compatible with downstream tooling.

[sndr]: https://github.com/tarnover/snder
[sndr]: https://github.com/tarnover/sndr
[ffsend]: https://github.com/timvisee/ffsend
[mozilla-send]: https://github.com/mozilla/send
[timvisee-send]: https://github.com/timvisee/send
Expand Down
8 changes: 6 additions & 2 deletions app/ui/statusBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ const html = require('choo/html');

module.exports = function() {
return html`
<footer class="snd-statusbar" role="contentinfo" aria-label="security status">
<span class="snd-tick snd-text-dim">aes-128-gcm · pbkdf2 · zero-knowledge</span>
<footer
class="snd-statusbar"
role="contentinfo"
aria-label="security status"
>
<span class="snd-tick snd-text-dim">aes-128-gcm · pbkdf2</span>
<span class="snd-tick snd-text-dim">files encrypted in your browser</span>
</footer>
`;
Expand Down
33 changes: 32 additions & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,40 @@ SND uses JavaScript to:

Since SND is an open-source project, you can read the source at <https://github.com/tarnover/snd>.

## Is the web UI "zero-knowledge"?

Not in the strong sense the term usually implies, and we deliberately don't
market it that way. The web UI is **end-to-end encrypted in your browser**:
your file is encrypted before it leaves your device, the decryption key lives
in the link fragment (after the `#`) and never reaches the server, and the
server only ever stores ciphertext plus minimal metadata.

The honest limitation is that the same server also ships the JavaScript that
does the encryption. A passive breach of the server or storage can't read your
files — but an *actively malicious or compromised* server could serve modified
JavaScript that steals the key from the link. This is a structural property of
**every** browser-delivered E2EE app, not specific to SND; tools that brand
their web client "zero-knowledge" share this exact limitation whether they say
so or not.

What each client actually protects against:

| Threat | Web UI | [`sndr`](https://github.com/tarnover/sndr) CLI |
|---|---|---|
| Reading file contents after a passive server/storage breach | ✅ | ✅ |
| Reading filenames / sizes / types after a passive breach | ✅ | ✅ |
| Network / TLS eavesdropper reading contents | ✅ | ✅ |
| An actively malicious server serving targeted JS to steal the key | ❌ | ✅ |
| The operator seeing IPs, file sizes, timing, or denying service | ❌ | ❌ |

For workflows where the operator-shipped-JS risk is unacceptable, use the
`sndr` command-line client: it ships its own copy of the protocol, so a
malicious server can't swap out the crypto layer. See
[`docs/security.md`](./security.md) for the full threat model.

## Is there a command-line client?

Yes — [`ffsend`](https://github.com/tarnover/ffsend), built by Tim Visee, is a fully-featured CLI that speaks the SND protocol. It can upload, download, set/clear passwords, change params, and delete shares. It is the recommended client for any sensitive workflow because, unlike the web UI, it doesn't trust the operator to ship correct JavaScript.
Yes — [`sndr`](https://github.com/tarnover/sndr) is a fully-featured CLI that speaks the SND protocol. It can upload, download, set/clear passwords, change params, and delete shares. It is the recommended client for any sensitive workflow because, unlike the web UI, it doesn't trust the operator to ship correct JavaScript.

## How long are files available for?

Expand Down
10 changes: 7 additions & 3 deletions server/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ module.exports = function(app) {
"'self'",
function(req) {
const baseUrl = config.deriveBaseUrl(req);
const r = baseUrl.replace(/^http(s?):\/\//, 'ws$1://');
console.log([baseUrl, r]);
return r;
return baseUrl.replace(/^http(s?):\/\//, 'ws$1://');
}
],
imgSrc: ["'self'", 'data:'],
Expand All @@ -56,6 +54,12 @@ module.exports = function(app) {
return `'nonce-${req.cspNonce}'`;
}
],
// the service worker decrypts downloads; keep it same-origin
workerSrc: ["'self'"],
// the app sets its own same-origin <base>; block cross-origin
// base rewriting, nested browsing contexts, and plugins
baseUri: ["'self'"],
frameSrc: ["'none'"],
formAction: ["'none'"],
frameAncestors: ["'none'"],
objectSrc: ["'none'"],
Expand Down
Loading