openvibers/openvibe.mail SECURITY.md
SECURITY.md
| 1 | # Security |
| 2 | |
| 3 | OpenVibe.Mail handles addresses, mail metadata and — for a few seconds, in memory — a verification code. It does |
| 4 | not store message bodies. Treat a report about any of the following as security-sensitive. |
| 5 | |
| 6 | ## Reporting |
| 7 | |
| 8 | Report a vulnerability to **[email protected]**. Do not open a public issue for a suspected vulnerability. |
| 9 | Include the affected route, a minimal reproduction and what an attacker gains. We will acknowledge and keep you |
| 10 | informed; do not test against production mailboxes that are not yours. |
| 11 | |
| 12 | ## What M1 runs |
| 13 | |
| 14 | - Stalwart Community receives SMTP on port 25. There is no submission listener (587/465), no POP3, no Sieve and no |
| 15 | public HTTPS listener; JMAP/management (8080) and IMAP (143) bind loopback only. |
| 16 | - Every domain is created with `allowRelaying = false`; an unauthenticated connection cannot relay. |
| 17 | - The API is behind OpenVibe.Network tokens. A typed token (`typ` or `purpose`) is refused. Another person's mask, |
| 18 | burner or inbox answers 404, not 403. |
| 19 | - A burner made without an account is limited per IP and capped, and its mail is deleted when it expires. |
| 20 | - Stalwart runs in its own systemd slice with `MemoryMax=1G`, `CPUQuota=100%`, `NoNewPrivileges=true` and |
| 21 | `ProtectSystem=strict`; the Node service is read-only too. |
| 22 | - Secrets live in `/etc/openvibe/*.env` (root, 0600). The rendered Stalwart `config.json` names the database |
| 23 | password by environment variable; the S3 keys are read from the environment by `apply.js` and are never written |
| 24 | to a rendered file or a log. |
| 25 | |
| 26 | ## Out of scope for M1 |
| 27 | |
| 28 | Inbox AI is opt-in, uses OpenVibe.AI's private tier with the owner's allowance, and stores generated summaries and |
| 29 | drafts. Replies require an explicit send action and follow the existing outbound relay gate. DKIM signing and paid |
| 30 | custom domains remain later phases. A report that a receive-only domain has no SPF sending path is not a |
| 31 | vulnerability; `v=spf1 -all` is deliberate. |
| 32 | |
| 33 | ## Secrets in the repository |
| 34 | |
| 35 | There are none. `.env.example` names variables without values. CI uses throwaway service containers. If a secret |
| 36 | is ever committed, rotate it first, then remove it from history; deleting the file is not enough. |
| 37 |