Legal
Security
Malaf hosts code that strangers upload and serves it to the public, so the interesting part of the design is what keeps those pages away from your account. This page covers what protects you, what is deliberately not promised, and how to report a problem.
Last updated
Malaf hosts whatever people upload, including HTML and scripts. The danger in that is a page acting as the person reading it.
Every site and plan lives on its own subdomain, so a page has no access to anything on the app host: not your session, not your keys, not another site. Where user content does have to be served from the app host, it is sent with a sandboxed content security policy that gives it an opaque origin with no cookies and no same-origin requests. The internal route that serves site files answers 404 unless the request came through the host router, so it is never a public address of its own.
Sign-in is Google or GitHub through Clerk. Malaf never sees or stores a password, and there is no password to reset or leak.
API keys are generated from a uniform alphabet and stored only as a SHA-256 hash with a short visible prefix, so a copy of the database does not hand anyone a working key. Each key carries scopes for upload, read, and delete, can be revoked from the dashboard, and is rate limited on its own. Guessing at keys costs the guesser their IP budget, so invalid keys are not free to try.
The database URL ships in the browser bundle, as it must for the live dashboard to work. Everything privileged behind it is signed: the server sends an HMAC over the timestamp, the operation name, and a canonical form of the arguments, checked in a five minute window with a constant time compare. Without that signature nobody can call a privileged function directly, read a claim token, or see a password hash.
- Uploads are sniffed by magic bytes, and executables are refused. A declared content type is validated before it can become a response header.
- Object size is verified against the quota reservation after the bytes land, so a presigned upload cannot exceed what was reserved.
- Archives are checked before anything is expanded, so a small ZIP cannot claim a large amount of disk.
- Importing a file from a URL resolves the address first and refuses loopback, link local, private, and carrier grade ranges in every IPv4 and IPv6 form, rechecking on each redirect.
A site password is stored as a bcrypt hash. The cookie a visitor gets after entering it holds a signature of that hash rather than the hash itself, so changing the password ends every existing session and a stolen cookie reveals nothing. In production the cookie uses the __Host- prefix so a neighbouring subdomain cannot set or clear it, the form posts rather than putting the password in a URL, and attempts are rate limited per address and per site.
Every quota is reserved before a byte is written and released on every failure path, so a crash mid-upload cannot leave storage claimed forever. Requests are counted per API key and per address. Publishing without an account is keyed to the address it came from. These limits keep one noisy user from spending the budget that keeps Malaf free for everyone else.
A security page that lists only strengths is not much use. These are the real edges.
- Links are unguessable, not secret. Six random characters stop someone finding your address by trying. They do not stop a person you shared it with from passing it on. Use a password when that matters.
- There is no end-to-end encryption. Content is encrypted in transit and at rest by the storage provider, and the operator can technically read what is stored. Do not put secrets, credentials, or regulated personal data on Malaf.
- Private is account level. A private file is readable by your workspace, not by a per-item access list.
- One person runs this. There is no security team on a rota, no SOC 2 report, and no 24-hour response promise. The architecture is built to make mistakes hard rather than to make staffing unnecessary.
Send it to hi@jehaad.com with the word security in the subject. Include what you found, the steps to see it again, and what you think it lets someone do. A first reply comes within three working days, and you will be told when it is fixed.
Report first and give it a reasonable time to be fixed before you publish. Reports handled that way will not be met with legal action.
In scope
malaf.dev, its subdomains that Malaf itself serves, the REST API, and the MCP endpoint.- The published CLI package.
Out of scope
- Content published by other users. Report that under the acceptable use policy instead.
- Reports from automated scanners with no working proof, missing hardening headers with no impact shown, and denial of service by volume.
- Anything that needs access to a victim's device or mailbox.
Do not run tests that degrade the service, and do not touch other people's data. Use your own workspace. There is no money on offer, since the product makes none, but real findings are credited here if you want that.
Automated checks run against the app, the database, the storage, and sign-in. Failures open an incident on the status page without anyone approving the wording, and it stays in the 90 day history afterwards. If an incident ever exposes personal data, affected people are told what happened, what was reached, and what changed as a result.