openvibers/openvibe.services SECURITY.md
SECURITY.md
| 1 | # Security policy |
| 2 | |
| 3 | OpenVibe is run in the open, and we want to hear about security problems before anyone else does. |
| 4 | |
| 5 | ## Reporting a vulnerability |
| 6 | |
| 7 | Email **[email protected]** with "security" in the subject. Please include what you found, where (URL, |
| 8 | repository, file), how to reproduce it, and what an attacker could do with it. Do not open a public GitHub issue for |
| 9 | a vulnerability, and do not test against other people's accounts, projects, resources or data. |
| 10 | |
| 11 | We reply within 7 days, keep you updated while we fix it, and credit you when the fix ships if you would like. |
| 12 | |
| 13 | ## Scope |
| 14 | |
| 15 | Every OpenVibe service and site (openvibe.services, openvibe.network, openvibe.live, openvibe.media, openvibe.run, |
| 16 | openvibe.bot and the other openvibe.* domains) and every repository under github.com/OpenVibers. Machine-readable |
| 17 | contact details are at `/.well-known/security.txt` on each site. |
| 18 | |
| 19 | ## This service |
| 20 | |
| 21 | OpenVibe.Services aggregates every authority's resource index and (from plan T13 step 10) routes control operations |
| 22 | to them, so a defect here can expose another project's resources or act on them. What Services guarantees, and what |
| 23 | a report should assume: |
| 24 | |
| 25 | - **no other service's data is written.** Services never opens, writes or migrates another service's database. Its |
| 26 | own rows are migrations/0001_initial.sql — the authority registry, a rebuildable read model, recipes and the |
| 27 | control log. |
| 28 | - **a person reads only their own projects.** A Network user token is accepted only for a project the person owns or |
| 29 | belongs to, verified with the caller's own token against Network's developer projects API |
| 30 | (`GET /api/v1/projects/:project`); a project they are not a member of is `404`, never a `403` that confirms it |
| 31 | exists. A person is never accepted unscoped, and the fan-out passes only that one project to the authorities. |
| 32 | - **a scoped read stays scoped.** Services filters `project` (and `kind`, `service`) on the merged rows itself, so an |
| 33 | authority that ignores a query parameter cannot leak another project's resource into a person's page. |
| 34 | - **a service token is judged on its own claims.** Audience `openvibe.services`, `svc:` principal, capability |
| 35 | `services.resource.read` (registered in the pinned openvibe-contracts, active and first-party — enforced with |
| 36 | contracts' own manifest and grant rules). |
| 37 | A bad token is refused, never downgraded to anonymous, and an app, mod or agent token is refused even with the |
| 38 | grant: a person reads with their own user token, never through a developer app's credential. |
| 39 | - **no secret is stored, logged or served.** The per-authority client-credentials tokens are minted at call time, |
| 40 | cached in memory with a 60 s refresh skew and never written to disk, a log line or a response body. The only route |
| 41 | that shows operational detail, `GET /api/v1/authorities`, is first-party (a service token) and carries no secret. |
| 42 | - **a failure degrades, it never stops.** An authority or Network being down yields a partial page whose body's |
| 43 | `partial: [{ service, code }]` names the authorities that did not answer; the rest of the index keeps serving |
| 44 | (ADR-046 section 6). |
| 45 | - nothing starts at module load (the key refresher and the outbox relay start in `server/index.js` `main()`), and |
| 46 | `/metrics` answers only a direct loopback caller that no proxy relayed. |
| 47 | |
| 48 | ## Supported versions |
| 49 | |
| 50 | Only the current `main` branch, which is what runs in production, receives fixes. |
| 51 |