YetAnotherFileLayer

Security and threat model

YAFL encrypts every file on your own machine before it leaves. The key that decrypts it travels only in the URL fragment, which browsers never send to a server, and it is separate from the API key your agent uses. This page describes what that protects, names the cryptographic primitives so the claims can be checked, and states what it does not protect against. YAFL has not had a third-party security audit.

What is and is not protected

QuestionAnswer
Can the YAFL app server read my file?No. The app server never receives the file bytes; object storage receives only ciphertext.
Can it read the filename or content type?No. The metadata is encrypted separately, under the same scheme.
Does the app server carry the file bytes?No. Bytes go from your machine straight to object storage over a pre-signed URL.
Can whoever holds the link read the file?For a standard link, yes: the link contains the key. A password-protected link also needs the password. Either way, treat the link as the secret.
If my agent's API key leaks, are my files exposed?No. The API key is not the decryption key. See below.
Does the server know who I am and when I sent something?Yes. It knows your account email, the size, and the timing. This is the metadata YAFL does see.
Has the crypto been independently audited?No. Solo project, unaudited. The design is public here so you can judge it yourself.

The cryptography, precisely

Every claim in this section is implemented in one small shared module (packages/crypto) that runs unmodified in both the Node process (the MCP server and CLI) and the browser, through the same WebCrypto crypto.subtle API. There is no second, divergent implementation to get out of sync.

Where the key lives, and why that is the whole design

A YAFL link looks like https://yafl.dev/t/{id}#{secret}. The part after the # is the URL fragment, and browsers do not transmit the fragment to any server. It is never in an HTTP request, never in a server log, never in the database.

There are two link shapes. A standard link carries the raw AES key in the fragment. A password-protected link carries only a random salt in the fragment, and the AES key is derived on the recipient's machine from that salt plus the password (which the server also never sees), so the link alone cannot decrypt without the password.

That is the trust model: object storage has the ciphertext, and the fragment carries the decrypting secret (the key itself, or a salt that needs the password), and that secret never reaches the server. When a recipient opens the link, the secret is read from the fragment by code running on their own machine, and decryption happens there.

The direct consequence, and the thing to internalise: for a standard link, the link is the key. Anyone who gets the whole link can read the file. So the honest security boundary is not "is it encrypted" (it is) but "who can see the link" (and, for a password link, the password).

The two-key split

There are two different secrets, and conflating them is the most common misunderstanding.

So if the box your agent runs on is compromised and its API key is stolen, the attacker can create new transfers billed to your account and list or delete your transfer records, which is why revocation matters and is immediate. What the attacker cannot do with the API key alone is decrypt any file, because the decryption keys travel only in link fragments and are not stored server-side or derivable from the API key. (If a full standard link was also sitting on that box, in shell history or an agent transcript, that link is readable, per the leak caveat below. That is a link leak, not an API-key leak.)

What YAFL does not protect against

This is the section other products leave out. Read it before you trust the tool with anything sensitive.

Expiry, precisely

Two independent layers, and the distinction matters.

One-time links add a third condition: the first successful download burns the transfer, and any later attempt is refused.

An optional password layer (v2 links) derives an additional key from a password using PBKDF2-SHA256 at 600,000 iterations over a fresh 256-bit salt that is itself carried in the fragment, so the password is a required second factor on top of the link, not the sole source of strength. The server never sees the password.

Headless authentication

An agent on a box with no browser should not need you to paste a long-lived secret into a dotfile. YAFL uses the standard device-authorization flow (RFC 8628): the agent prints a short code and a URL, you approve it from your phone, and the agent receives its own named, individually revocable API key. The long device code is stored server-side only as a SHA-256 hash (the plaintext is never persisted), the short user code is compared with a constant-time comparison (timingSafeEqual), and the grant is single-use.

Abuse controls

Bot protection (Cloudflare Turnstile) guards the account and magic-link surfaces, and the sensitive endpoints are rate limited (for example, magic-link requests and transfer resolution). These protect the service; they are not part of the file confidentiality guarantee, and are listed here only so the picture is complete.

Audit status, and how to check the claims

YAFL is a solo project and has not had a third-party cryptographic audit. Everything above is verifiable rather than asserted: the encryption module is a small, standalone package, the primitives are named exactly, and there is no custom cipher or invented protocol to reason about. If you find a hole in any of this, that is the most useful thing you can send, and it is welcome. Report security issues to the contact on the site rather than in a public thread, and expect an honest answer, including "you're right, here is what we are changing."

Install: npx -y @yafldev/mcp with YAFL_API_KEY set, or the one-liner curl -fsSL https://yafl.dev/install.sh | sh.

Get started Full setup docs →