RBAC getRequiredRoles bypasses wildcard when exact match lacks method roles #685
Labels
No labels
1week
2weeks
Failed compliance check
IP cameras
NATS
Possible security concern
Review effort 1/5
Review effort 2/5
Review effort 3/5
Review effort 4/5
Review effort 5/5
UI
aardvark
accessibility
amd64
api
arm64
auth
back-end
bgp
blog
bug
build
checkers
ci-cd
cleanup
cnpg
codex
core
dependencies
device-management
documentation
duplicate
dusk
ebpf
enhancement
eta 1d
eta 1hr
eta 3d
eta 3hr
feature
fieldsurvey
github_actions
go
good first issue
help wanted
invalid
javascript
k8s
log-collector
mapper
mtr
needs-triage
netflow
network-sweep
observability
oracle
otel
plug-in
proton
python
question
reddit
redhat
research
rperf
rperf-checker
rust
sdk
security
serviceradar-agent
serviceradar-agent-gateway
serviceradar-web
serviceradar-web-ng
siem
snmp
sysmon
topology
ubiquiti
wasm
wontfix
zen-engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
carverauto/serviceradar#685
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Imported from GitHub.
Original GitHub issue: #2147
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/issues/2147
Original created: 2025-12-16T05:17:02Z
Summary
getRequiredRolesfunction inpkg/core/auth/rbac.godetermines which roles are required to access HTTP routes based on the RBAC configuration, supporting both exact path matches and wildcard patterns./api/admin/*requires["admin"]role and/api/admin/usershas method-specific rules{"POST": ["superadmin"]}, a GET request to/api/admin/usersreturns no required roles (allowing unrestricted access) instead of falling back to the wildcard's["admin"]requirement.Code with bug
Evidence
Example
Consider this RBAC configuration (from the actual config files in this codebase):
Step-by-step execution for
GET /api/admin/users:getRequiredRoles("/api/admin/users", "GET", routeProtection)is called/api/admin/usersparseProtection({"POST": ["superadmin"]}, "GET")is calledparseProtectionchecks the map for"GET"key at line 109"GET"key doesn't exist in the map[]string{}getRequiredRolesreturns[]string{}Expected behavior:
/api/admin/*["admin"]as required rolesadminroleFailing test
Test script
Test output
Full context
The
RouteProtectionMiddlewareis applied to all protected API routes in the HTTP server. When a request comes in, it:getRequiredRolesto determine which roles are needed for the requested path and HTTP methodgetRequiredRolesreturns an empty array, the middleware interprets this as "no protection required" and allows the request to proceed without any role checksThe bug occurs in step 2-3: when an exact path match exists but doesn't define roles for the specific HTTP method being used,
getRequiredRolesreturns an empty array instead of falling back to wildcard pattern matches.This is particularly dangerous because:
packaging/core/config/core.json,helm/serviceradar/files/serviceradar-config.yaml) use wildcard patterns like/api/admin/*to protect entire sections of the APIsuperadminfor POST operations) without realizing this creates a security hole for other HTTP methods on that same endpointThe bug is in
pkg/core/auth/rbac.go:72-90, specifically the early return at line 79 that doesn't check if the returned roles array is empty before bypassing the wildcard pattern checks.Why has this bug gone undetected?
This bug has gone undetected for several reasons:
No existing tests for the RBAC route protection logic: The only test file in
pkg/core/auth/isauth_test.go, which tests JWT authentication but not the route protection middleware orgetRequiredRolesfunction.Limited production usage of method-specific rules: Based on the configuration files in the codebase, most route protection uses simple role arrays rather than method-specific maps. The bug only manifests when you have BOTH a wildcard pattern AND an exact match with method-specific rules.
Authentication middleware still active: Even though the route protection is bypassed, the authentication middleware (
authenticationMiddleware) still runs before the RBAC middleware (seepkg/core/api/server.go:822-827). This means completely unauthenticated requests are still blocked - only authenticated users without the required roles can exploit this bug.Common configurations don't trigger the bug: Looking at the example configs, most routes either:
The bug requires specific configuration pattern: You need someone to:
/api/admin/*:["admin"])/api/admin/users:{"POST": ["superadmin"]})This specific sequence is uncommon but not unrealistic - a developer might want to add stricter requirements for certain operations (POST/DELETE) while assuming the wildcard still protects read operations (GET).
Recommended fix
The function should only return early from the exact match if it actually found roles for the requested method. If the exact match doesn't specify roles for the method, it should fall through to check wildcard patterns:
This ensures that method-specific rules can override wildcard patterns when they specify roles for a method, but wildcard patterns still provide protection when the method-specific rule doesn't define roles for the requested HTTP method.
Imported GitHub comment.
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/issues/2147#issuecomment-3663510876
Original created: 2025-12-17T03:45:03Z
closing as completed