Skip to main content

vulkro rbac

Emit a role-based-access-control matrix from your discovered endpoints

  • METHOD PATH rows x AuthTier columns, where the endpoint requires that tier. Markdown for audit handoff, JSON for tooling.

Usage

vulkro rbac . # markdown matrix to stdout
vulkro rbac . --format json # structured JSON
vulkro rbac . --output rbac.md # write to a file

Arguments

ArgumentDescriptionDefault
PATHProject root..

Flags

FlagDescriptionDefault
--format <FMT>md (Markdown table) or json.md
--output <FILE>, -oWrite to file instead of stdout.stdout

What the matrix shows

Vulkro's auth model has been extended beyond the original Protected/Unprotected/Unknown flag: each endpoint now carries an AuthRequirement with three fields the matrix surfaces.

  • AuthTier - one of Anonymous, User, Admin, Service, Machine, Unknown. Inferred from decorators and middleware (@UseGuards(AdminGuard), IsAdminUser, is_staff, [Authorize(Roles="Admin")], @PreAuthorize("hasRole('ADMIN')"), auth:sanctum, etc.).
  • Scopes - list of OAuth-style scope checks. Populated from @Security(scopes=["users:read"]), @Scopes('foo'), RequiresScope(...), etc.
  • TenantScoping - ScopedByTenant | GlobalNoTenant | Unknown. Flagged when the handler body references current_user.tenant_id, request.tenant, req.user.organisation_id, or similar.

The matrix presents the first dimension (tier) as columns and the endpoints as rows; scopes and tenant scoping appear as extra columns.

Markdown example

| Method | Path | Anonymous | User | Admin | Service | Machine | Scopes | Tenant |
|---|---|:--:|:--:|:--:|:--:|:--:|---|---|
| GET | /api/health | | | | | | | global |
| GET | /api/me | | | | | | | by tenant |
| POST | /api/users/:id/promote | | | | | | users:admin | by tenant |
| POST | /api/internal/sync | | | | | | | global |

JSON example

{
"endpoints": [
{
"method": "POST",
"path": "/api/users/:id/promote",
"tier": "Admin",
"scopes": ["users:admin"],
"tenant_scoping": "ScopedByTenant",
"file": "src/api/users.rs",
"line": 142
}
]
}

Why this is useful

  • Audit handoff. Auditors asking "which endpoints can role X reach?" get a one-page answer instead of "let me grep the middleware."
  • Sanity check on a release. A diff of the RBAC matrix before and after a release surfaces accidentally-exposed admin endpoints.
  • Tenant-boundary review. The TenantScoping column reveals endpoints in a multi-tenant codebase that don't visibly scope by tenant - a common IDOR shape.

How tier inference works (per language)

The inference is best-effort and never invents a tier - it falls back to Unknown when no clear evidence is visible. Examples:

LanguageAdmin signalService signal
PythonIsAdminUser, is_staff, permission_classes=[IsAdmin*], @staff_member_requiredX-Service-Token, verify_service_token, mTLS hints
Node/TS@UseGuards(AdminGuard), requireAdmin, IsInRole("Admin")@UseGuards(ServiceTokenGuard), X-Service-Token
Java@PreAuthorize("hasRole('ADMIN')"), @RolesAllowed("ADMIN")@RolesAllowed("SERVICE")
C#[Authorize(Roles="Admin")][Authorize(Policy="ServiceToken")]
Goroute registered behind a RequireAdmin middlewareroute behind a ServiceAuth middleware
Railsbefore_action :require_admin, current_user.admin?(less common in Rails)
Laravelmiddleware('role:admin'), Gate::allows('admin')middleware('auth:sanctum-service')
  • vulkro discover - produces the endpoint list the matrix is computed from.
  • vulkro openapi - emits an OpenAPI 3.1 spec with the same auth-tier info as x-vulkro-tier extensions.