Authentication & permissions
RingZero is built on least privilege: no single credential grants org-wide access. Every API request is authorized three ways — who is calling (the principal), what they’re allowed to do (role or scopes), and which resources they may touch (org, project, or host). A leaked CI key can, at worst, do what that one key was scoped to do — typically upload dependency snapshots to a single project — not read your findings or act as your org.
Principals
Section titled “Principals”Five kinds of principal can authenticate to RingZero:
| Principal | Credential | Issued in | Can do |
|---|---|---|---|
| Human user | Session token (browser sign-in) | — | Whatever their role allows, in the app and API |
| API key | rz_key_… bearer token | Settings → API keys | Only its granted scopes, only on its granted projects |
| Registration token | rz_reg_… bearer token | Settings → Hosts | Register new hosts — nothing else |
| Registered host | Host credential (managed by the sidecar) | Derived automatically during registration | Heartbeat and challenge responses for that one host — nothing else |
| Scan Gateway | Gateway credential (managed by the gateway) | Derived from an rz_gw_… enrollment token in Settings → Gateways | Relay registration and run scoped scan egress for hosts in its network — nothing else |
Session tokens are short-lived and refreshed automatically by the app. A
session’s org membership and role come from GET /v1/me; org, member,
invitation, and API-key management endpoints are session-only — no API-key
scope grants them. The four machine credentials are the ones you handle
yourself — and each is deliberately narrow:
- An API key never carries user-level power. It holds an explicit scope list fixed at creation, optionally restricted to specific projects.
- A registration token can only add hosts to your org’s scan scope. It cannot read scans, findings, hosts, or anything else.
- A host credential is created by the sidecar during registration, stored only on that host, rotated automatically, and dies with the registration. Even a fully compromised host can’t read your org’s data or register other hosts — its credential only heartbeats for itself.
- A gateway credential is derived when a Scan Gateway enrolls, and only lets that gateway relay registration and open scoped, private-range scan egress for its own network. RingZero never routes a scan outside a gateway’s approved private scope (public-internet safety), and the credential is mTLS-pinned to one org (cross-tenant safety) — see the connectivity trust model.
User roles
Section titled “User roles”Each member of an organization has exactly one role:
| Capability | Owner | Admin | Member | Auditor |
|---|---|---|---|---|
| View scans, findings, dependencies | ✅ | ✅ | ✅ | ✅ |
| Trigger scans on registered hosts | ✅ | ✅ | ✅ | — |
| Create projects, manage project settings | ✅ | ✅ | — | — |
| Issue / revoke API keys | ✅ | ✅ | — | — |
| Issue / revoke registration tokens, revoke hosts | ✅ | ✅ | — | — |
| Enroll / approve / revoke Scan Gateways | ✅ | ✅ | — | — |
| Manage members and roles | ✅ | ✅ | — | — |
| View the audit trail | ✅ | ✅ | — | ✅ |
| Billing, org deletion, transfer ownership | ✅ | — | — | — |
Notes:
- Member project visibility can be narrowed with teams (a member sees the projects of the teams they belong to; org-wide visibility is the default).
- Auditor is a read-only role for compliance reviewers: full visibility including the audit trail, no ability to change anything or trigger scans.
- Promoting someone to Admin, and any role change on an Owner, is Owner-only.
Joining and leaving an organization
Section titled “Joining and leaving an organization”Each user belongs to one organization. RingZero has no public signup: a company requests access, we send account- creation details, and we provision the organization with a first Owner. Everyone else joins by redeeming an invitation — an account that hasn’t redeemed one belongs to no organization and can’t see any data.
- Invitations are created by Admins and Owners on the Organization page; inviting someone as Admin is Owner-only, and the Owner role is never invitable.
- An invitation is email-bound, single-use, and expires after 7 days (states: pending → accepted / revoked / expired). Re-inviting a pending email revokes and replaces the earlier invite.
- Any member can leave an org (removing your own membership); Admins and Owners can remove others — but removing (or demoting) an Owner is Owner-only, and the org’s sole Owner can never be demoted or removed.
API key scopes
Section titled “API key scopes”API keys are org-owned service credentials — they don’t ride on a user’s session and keep working if their creator leaves the org (the audit trail records who created what). What a key can do is fixed at creation:
| Scope | Grants | Needed by |
|---|---|---|
| sca:upload | Upload dependency snapshots and their embedded suppressions (POST /v1/scans/dependency-snapshots) | Gradle plugin (ringzeroScan), direct snapshot integrations |
| scans:read | Read scan status and severity counts | ringzeroCheck polling (coming soon), dashboards |
| findings:read | Read finding details — CVE ids, versions, dependency paths | ringzeroCheck console output (coming soon), triage tooling |
| deps:read | Read the dependency inventory | Inventory exports, internal tooling |
| hosts:read | Read registered-host inventory and statuses (GET /v1/hosts) | Fleet dashboards, drift alerts |
| gateways:read | Read Scan Gateway inventory (GET /v1/gateways) | Gateway/connectivity dashboards |
| mcp:upload | Upload MCP scan results and usage audit events (POST /v1/mcp/scans, POST /v1/mcp/usage-events) | ringzero-mcp in CI and dev machines |
| mcp:read | Read the MCP server inventory and pull the MCP Registry catalog (GET /v1/mcp/servers, GET /v1/mcp/registry) | ringzero-mcp registry pull, MCP dashboards |
Alongside scopes, every key has a project restriction: all projects or an explicit list. Both are visible on the key’s row in Settings → API keys and enforced on every request.
Rules:
- Only Admins and Owners create keys, and a key can never be granted a capability its scopes don’t name — there is no “full access” key.
- Keys support an optional expiry (recommended for CI: 1 year, rotate on renewal) and are revocable immediately.
- Keys can never: manage members, issue credentials, revoke hosts, trigger scans, or read the audit trail. Those capabilities are role-gated to humans.
How a request is authorized
Section titled “How a request is authorized”Every API call walks the same three checks, in order:
- Authenticate — is the bearer credential valid, unexpired, unrevoked?
Failure →
401 invalid_token. - Scope — does the principal hold the capability this endpoint needs
(role capability for users, scope for keys)? Failure →
403 insufficient_scope, and the error message names the missing scope. - Resource — is the target resource inside the principal’s reach (the
key’s project list, the member’s team visibility, the host’s own
registration)? Failure →
404 not_found— resources outside your reach are indistinguishable from resources that don’t exist.
// 403 — key is valid but lacks the scope{ "error": { "code": "insufficient_scope", "message": "This endpoint requires 'findings:read'. The key has: sca:upload, scans:read." }}The endpoint index lists every endpoint with its required scope.
Recipes
Section titled “Recipes”Least-privilege setups for common integrations:
| Use | Scopes | Projects | Notes |
|---|---|---|---|
CI build gate (Gradle ringzeroScan today; gating via ringzeroCheck coming soon) | sca:upload, scans:read | the one project | The build fails on severity counts alone; the console CVE table needs findings:read — add it only if you want that detail in CI logs. See the Gradle guide. |
| Upload-only pipeline (scan results reviewed in the app) | sca:upload | the one project | The narrowest useful key — it can’t read anything back. |
| Security dashboard / export tooling | scans:read, findings:read, deps:read | as needed | Read-only; can’t upload or change anything. |
| Fleet monitoring | hosts:read | all projects | Watch for hosts drifting out of the active state via GET /v1/hosts. |
One key per integration, named for it (ci-acme-web, grafana-export) — so
revoking one integration never breaks another, and audit entries read cleanly.
Audit trail
Section titled “Audit trail”Every credential and membership event and every scan authorization is recorded: key/token issued or revoked (and by whom), org created, invitation created/accepted/revoked, member role changed or member removed, host registered/expired/revoked, gateway enrolled/approved/expired/revoked, scan authorized (and which gateway it routed through), scan halted out of scope — plus the acting principal on API requests made with keys. Owners, Admins, and Auditors can review the trail under Settings → Audit.
Best practices
Section titled “Best practices”- Scope keys to the minimum: one integration, one project, fewest scopes.
- Set expiries on CI keys and rotate on a schedule, not just on incidents.
- Store keys and tokens in a secret manager or CI secret store — never in source control.
- Prefer the Auditor role for anyone who only needs to look.
- Review Settings → Audit after any suspected leak — then revoke; both take effect immediately.
Related pages
Section titled “Related pages”- Gradle plugin — provide your API key securely
- REST API reference — authentication and per-endpoint scopes
- Sidecar authentication & configuration — registration tokens and host credentials in depth