Skip to content

Tokens

Tokens are for machines: MCP agents, CI/CD pipelines, Prometheus, administration scripts. People use a user account, which alone opens the web interface, with the rights of its groups (Roles, groups and permissions). There is no read-only or triage token: to give a person read or triage access, add their account to a group.

Roles of a token

Every token has a fixed role, which decides the endpoints it reaches. A token created without a role is mcp.

Role Usage (Tokens screen) /mcp REST API Status change
mcp (default) MCP ✅ — (pipeline routes for a personal token) —
admin CLI only ✅ ✅ open, fixed ¹
api REST API — Swagger and scripts (API tokens) — ✅ with the permissions of its role or of its user open, fixed ¹ with findings.triage
ci CI/CD pipeline — gate, SARIF, trend and scans — pipeline routes only (/api/v1/ci/), including the scans that store reports —
metrics CLI only — /metrics only (Prometheus) —

¹ accepted and false_positive need a person logged in to the interface with the findings.triage permission (triage of findings). On /mcp, no role changes a status: the agents only propose one.

An mcp token can be restricted to projects with --project (repeatable); a ci token always is (see ci token and tokens restricted to a project). Creation, expiry, rotation and revocation from the CLI: Bearer tokens.

admin token

An admin token calls the whole REST API, for example from an administration script, but does not open the interface (the login page only offers the accounts):

security-review-controller token create --label ops-script --role admin
# {"id": "…", "label": "ops-script", "role": "admin", "project": null, "created_at": "…", "token": "UJB7…"}
curl -H "Authorization: Bearer $TOKEN" https://secreview.example.com/api/v1/projects

The REST API lists the findings of a project across all its reports, open by default, worst first (status, severity and review_type filter, limit is capped by SECREVIEW_MAX_LIST_LIMIT, total gives the number of matching findings for paging). Without project, it lists the findings of every project the caller reads ("project": null):

curl -H "Authorization: Bearer $TOKEN" \
  "https://secreview.example.com/api/v1/findings?project=shop-api&status=open&limit=50"
# {"project": "shop-api", "total": 12, "findings": [{"id": 42, "severity": "critical", "report_id": 7, "project": "shop-api", "branch": "main", "commit_sha": "abc123", "review_type": "codebase-review", "report_created_at": "…", …}, …]}

GET /api/v1/reports lists the reports (project, risk_level, review_type and author filter), each with its author and submitted_by. The author is returned, filtered, searched and sorted only for a caller holding users.manage or tokens.manage: for the others it is null (in the report and its Markdown export too) and the author filter is ignored:

curl -H "Authorization: Bearer $TOKEN" \
  "https://secreview.example.com/api/v1/reports?project=shop-api&author=alice@example.com"

Revoke it with security-review-controller token revoke ops-script. Every status change is logged with the label of the token or of the account:

INFO security_review_mcp.web: Finding 42 set to fixed by ops-script

and written to the audit log (GET /api/v1/audit, audit.read permission), with the actor token:ops-script or user:<name>.

API tokens

An api token calls the REST API, from a script or from the Swagger documentation (/api/docs, Authorize button), with the rights of the access control, read at each request. It never reaches /mcp and never opens the interface. There are two kinds:

  • Personal token: created by a user for themselves, with Usage REST API — Swagger and scripts (see personal tokens). It holds the current rights of the account, which come from its groups: it reaches nothing once the account loses them.
  • Role token: created by an administrator (tokens.manage) on the Tokens screen, with Usage REST API and a Role. It holds the permissions of that role on its projects (every project, or a list when the role only holds permissions per project). A role used by a token cannot be deleted.
curl -X POST -H "Authorization: Bearer $SESSION" -H "Content-Type: application/json" \
  https://secreview.example.com/api/v1/me/tokens -d '{"label": "swagger", "expires_in_days": 30}'
# {"id": "…", "label": "alice:swagger", "role": "api", "personal": true, "access_role_id": null, …, "token": "Zq3…"}
curl -H "Authorization: Bearer $TOKEN" https://secreview.example.com/api/v1/me
# {"client": "alice:swagger", "role": "api", "permissions": {"reports.read": ["shop-api"]}, …}

Tokens created from the interface

A token never grants more than its creator holds: creating a token, changing its projects, rotating its secret or revoking it needs reports.read on every project of the token, before and after a change of its projects, and, for a role api token, each permission of its role on these projects. The Tokens screen only lists the tokens of the projects the user reads.

Personal tokens

A user creates their own tokens in My account > Personal tokens, with one of three usages:

Usage Role Reaches Needs
REST API — Swagger and scripts api the REST API, with the rights of the account —
MCP mcp /mcp and the pipeline routes, on the projects the account may read mcp_tokens.create
CI/CD pipeline ci the pipeline routes only, on the projects the account may read mcp_tokens.create

Every personal token follows the same rules:

  • one at most per usage by default (SECREVIEW_PERSONAL_TOKENS_PER_USER): revoke it to create another;
  • label <user>:<label>, with a : that no other token label may hold, and validity bounded by SECREVIEW_TOKEN_MAX_DAYS;
  • its rights are those of the account, read at each request; it stops while the account must change a password set by an administrator, and is deleted with the account;
  • nobody can rotate it nor change its projects; an administrator can revoke it from the Tokens screen.

Personal MCP and CI tokens

A personal mcp token connects the MCP agent of the user. It is offered only when the groups of the account hold mcp_tokens.create (role mcp-user, see Roles; 403 without it); a token already created keeps working when the account loses it, and an administrator revokes it if needed. It reaches the projects the account may read (reports.read of its groups): every project when one of its groups reads every project, none when it has none. The Projects column shows them, and so does the Tokens screen for the administrators.

For a project it does not reach, an administrator gives the account access to the project (a group that reads it), or the user creates it from Projects if it is new and they hold projects.create (see Creating a project); a project requested by an enrollment waits for an approval. When the server refuses the token (unknown, revoked or expired), the agent receives a 401 that tells the user to sign in again and create a new one.

A personal mcp token also works as a personal ci token on the pipeline routes: one SECREVIEW_TOKEN on the workstation serves both the MCP agent and security-review-ci. A personal ci token is only needed to keep the two uses apart; it never reaches /mcp. A report stored by either is submitted by the token (alice:laptop), and its user is the author (see scan from a workstation). An mcp token created by an administrator on the Tokens screen stays an MCP agent token only.

curl -X POST -H "Authorization: Bearer $SESSION" -H "Content-Type: application/json" \
  https://secreview.example.com/api/v1/me/tokens -d '{"label": "laptop", "role": "mcp"}'
# {"id": "…", "label": "alice:laptop", "role": "mcp", "personal": true, …, "token": "Zq3…"}
curl -X POST -H "Authorization: Bearer $SESSION" -H "Content-Type: application/json" \
  https://secreview.example.com/api/v1/me/tokens -d '{"label": "laptop", "role": "ci"}'
# {"id": "…", "label": "alice:laptop", "role": "ci", "personal": true, …, "token": "Zq3…"}