sast-missingauth-b3773d — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sast-missingauth-b3773d (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are performing a focused security assessment to find missing authentication and broken function-level authorization vulnerabilities in a codebase. This skill uses a three-phase approach with subagents: recon (map endpoints and the permission system), batched verify (check authentication and authorization in parallel batches of 3 endpoints each), and merge (consolidate batch results into the final report).
Prerequisites: sast/architecture.md must exist. Run the analysis skill first if it doesn't.
An endpoint performs a sensitive action but requires no login at all — any anonymous HTTP request can trigger it.
An endpoint requires authentication (user must be logged in) but does not check whether the authenticated user has the required role or permission to invoke that function. The classic example: a regular user calling an admin-only API.
Do not conflate with:
The endpoint modifies data, returns private information, or performs an administrative action — with no authentication required.
GET /api/admin/users → returns full user list, no token needed
DELETE /api/admin/users/5 → deletes a user, no token needed
POST /api/settings/smtp → updates server config, no token neededThe endpoint requires a valid session/token but performs no role or permission check. Any authenticated user — regardless of role — can invoke admin or privileged functions.
Regular user sends:
DELETE /api/admin/users/5
Authorization: Bearer <regular_user_token>
→ Server deletes the user without checking if the caller is an adminAuthorization logic is present but can be bypassed:
When you see these patterns, the endpoint is likely not vulnerable:
1. Authentication + role-check middleware on a route group
// Express: all /admin routes protected
router.use('/admin', auth, requireRole('admin'));
router.delete('/admin/users/:id', deleteUser); // protected by above
// Flask-Login + custom decorator
@app.route('/admin/users')
@login_required
@admin_required
def list_users(): ...2. Declarative role annotations (Java / Spring)
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/api/admin/users/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id) { ... }3. In-handler role check before sensitive action
# Django
@login_required
def delete_user(request, user_id):
if not request.user.is_staff:
return HttpResponseForbidden()
User.objects.filter(id=user_id).delete()
return HttpResponse(status=204)4. Middleware gate applied to entire prefix
// Chi router — admin group protected
r.Group(func(r chi.Router) {
r.Use(AdminOnly)
r.Delete("/admin/users/{id}", deleteUser)
})5. Policy/Gate objects
// Laravel Gate
Gate::define('admin-action', fn($user) => $user->role === 'admin');
// In controller
$this->authorize('admin-action');# VULNERABLE: No authentication at all
def list_all_users(request):
users = User.objects.values('id', 'email', 'is_staff')
return JsonResponse(list(users), safe=False)
# VULNERABLE: Authenticated but no role check
@login_required
def delete_user(request, user_id):
User.objects.filter(id=user_id).delete()
return HttpResponse(status=204)
# SECURE
@login_required
def delete_user(request, user_id):
if not request.user.is_staff:
return HttpResponseForbidden()
User.objects.filter(id=user_id).delete()
return HttpResponse(status=204)# VULNERABLE: No auth decorator
@app.route('/admin/users')
def list_users():
return jsonify([u.to_dict() for u in User.query.all()])
# VULNERABLE: Login required but no role check
@app.route('/admin/users/<int:user_id>', methods=['DELETE'])
@login_required
def delete_user(user_id):
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return '', 204
# SECURE
@app.route('/admin/users/<int:user_id>', methods=['DELETE'])
@login_required
def delete_user(user_id):
if current_user.role != 'admin':
abort(403)
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return '', 204// VULNERABLE: No auth middleware
router.get('/api/admin/users', async (req, res) => {
const users = await User.find({});
res.json(users);
});
// VULNERABLE: Auth middleware present but no role check
router.delete('/api/admin/users/:id', auth, async (req, res) => {
await User.findByIdAndDelete(req.params.id);
res.sendStatus(204);
});
// SECURE
const requireAdmin = (req, res, next) => {
if (req.user.role !== 'admin') return res.sendStatus(403);
next();
};
router.delete('/api/admin/users/:id', auth, requireAdmin, async (req, res) => {
await User.findByIdAndDelete(req.params.id);
res.sendStatus(204);
});# VULNERABLE: No before_action
def destroy
User.find(params[:id]).destroy
head :no_content
end
# VULNERABLE: Authenticated but no admin check
before_action :authenticate_user!
def destroy
User.find(params[:id]).destroy
head :no_content
end
# SECURE
before_action :authenticate_user!
before_action :require_admin
def destroy
User.find(params[:id]).destroy
head :no_content
end
private
def require_admin
head :forbidden unless current_user.admin?
end// VULNERABLE: No security annotation
@DeleteMapping("/api/admin/users/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
userRepo.deleteById(id);
return ResponseEntity.noContent().build();
}
// VULNERABLE: Authenticated but wrong role
@DeleteMapping("/api/admin/users/{id}")
@Secured("ROLE_USER") // any user can call this
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
userRepo.deleteById(id);
return ResponseEntity.noContent().build();
}
// SECURE
@DeleteMapping("/api/admin/users/{id}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
userRepo.deleteById(id);
return ResponseEntity.noContent().build();
}// VULNERABLE: No auth middleware on route
r.Delete("/admin/users/{id}", deleteUser)
// VULNERABLE: Auth middleware but no role check in handler
r.With(AuthMiddleware).Delete("/admin/users/{id}", deleteUser)
func deleteUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
db.DeleteUser(id) // no role check
w.WriteHeader(http.StatusNoContent)
}
// SECURE
r.Group(func(r chi.Router) {
r.Use(AuthMiddleware)
r.Use(AdminOnlyMiddleware)
r.Delete("/admin/users/{id}", deleteUser)
})// VULNERABLE: No auth middleware
Route::delete('/admin/users/{id}', [AdminController::class, 'destroy']);
// VULNERABLE: Auth but no role gate
Route::middleware('auth')->delete('/admin/users/{id}', [AdminController::class, 'destroy']);
// SECURE
Route::middleware(['auth', 'role:admin'])->delete('/admin/users/{id}', [AdminController::class, 'destroy']);
// SECURE (using Gate in controller)
public function destroy($id) {
Gate::authorize('admin-action');
User::findOrFail($id)->delete();
return response()->noContent();
}// VULNERABLE: No authorization attribute
[HttpDelete("api/admin/users/{id}")]
public async Task<IActionResult> DeleteUser(int id) {
await _userService.DeleteAsync(id);
return NoContent();
}
// VULNERABLE: [Authorize] but no role
[Authorize]
[HttpDelete("api/admin/users/{id}")]
public async Task<IActionResult> DeleteUser(int id) {
await _userService.DeleteAsync(id);
return NoContent();
}
// SECURE
[Authorize(Roles = "Admin")]
[HttpDelete("api/admin/users/{id}")]
public async Task<IActionResult> DeleteUser(int id) {
await _userService.DeleteAsync(id);
return NoContent();
}This skill runs in three phases using subagents. Pass the contents of sast/architecture.md to all subagents as context.
Launch a subagent with the following instructions:
Goal: Build a complete map of (1) all application endpoints/routes and their current authentication/authorization posture, and (2) the role/permission system. Write results to sast/missingauth-recon.md.>
Context: You will be given the project's architecture summary. Use it to understand the tech stack, frameworks, route definitions, and the auth/authz strategy.
>
What to search for:
>
1. All route/endpoint definitions — collect every HTTP handler, REST endpoint, GraphQL mutation/query, RPC method, or WebSocket handler: - Express/Koa:router.get/post/put/delete/patch/use- Django:urlpatterns,path(),re_path()- Flask:@app.route,@blueprint.route- Rails:routes.rb—get,post,resources,namespace- Spring:@GetMapping,@PostMapping,@RequestMapping,@DeleteMapping,@PutMapping- Go/Chi:r.Get,r.Post,r.Delete,r.Handle- Laravel:Route::get/post/put/delete- FastAPI:@router.get/post/put/delete- ASP.NET:[HttpGet],[HttpPost],[HttpDelete],[HttpPut]
>
2. Authentication middleware and decorators currently applied: - Identify the pattern used:@login_required,authmiddleware,[Authorize],authenticate_user!, JWT verification middleware, session checks - Note which routes or route groups they are applied to - Note any routes explicitly excluded from auth (e.g.,except: [:index, :show])
>
3. Role/permission system — identify how roles are defined and checked: - Role constants/enums:ROLE_ADMIN,'admin',UserRole.ADMIN,is_staff,is_superuser- Permission decorators:@admin_required,@roles_required,@PreAuthorize,requireRole()- Middleware:AdminOnly,requireAdmin,role:admin- Policy/Gate/Ability objects:Gate::define,Policy,CanCanCan,Pundit- In-handler checks:if user.role != 'admin',if not current_user.is_admin
>
4. Sensitive/privileged endpoints to flag — any endpoint that: - Has an/admin,/management,/internal,/api/admin,/superadmin,/system,/opspath prefix - Performs user management: create/update/delete users, change roles, reset passwords for others - Manages application configuration: settings, feature flags, SMTP, secrets, environment variables - Accesses financial/billing data: invoices, payments, subscriptions for all users - Triggers system actions: sending emails to all users, running background jobs, clearing caches - Returns aggregate or sensitive data: all users, all orders, audit logs, error logs
>
5. For each endpoint, note: - Whether an auth middleware/decorator is present - Whether a role/permission check is present - The HTTP method(s) it handles - Whether it reads, writes, or deletes data
>
What to ignore: - Publicly intended endpoints: login, register, password reset request, public content (blog posts, product listings) - Static asset serving, health-check endpoints (/health,/ping,/status)
>
Output format — write to sast/missingauth-recon.md:>
```markdown # Missing Auth Recon: [Project Name]
>
## Permission System Summary - Roles identified: [list roles, e.g. admin, moderator, user] - Auth mechanism: [JWT / session / API key / OAuth] - Auth decorators/middleware: [list names, e.g. @login_required, auth, requireAdmin]
>
## Endpoint Inventory
>
### 1. [Endpoint name / description] - File:path/to/file.ext(lines X-Y) - Endpoint:METHOD /path- Operation: [read / write / delete / admin-action] - Auth present: [yes / no] - Role check present: [yes / no / partial] - Code snippet: ``[route registration + handler signature]``
>
[Repeat for each endpoint] ```
After Phase 1 completes, read sast/missingauth-recon.md and split the endpoint inventory into batches of up to 3 endpoints each (each numbered ### N. under Endpoint Inventory). Launch one subagent per batch in parallel. Each subagent verifies only its assigned endpoints and writes results to its own batch file.
Batching procedure (you, the orchestrator, do this — not a subagent):
sast/missingauth-recon.md and count the numbered endpoint sections under Endpoint Inventory (### 1., ### 2., etc.).sast/missingauth-batch-N.md where N is the 1-based batch number.sast/architecture.md and select only the matching examples from the "Vulnerable vs. Secure Examples" section above. For example, if the project uses Python/Django, include only the "Python — Django" (and if relevant, Flask) examples. Include these selected examples in each subagent's instructions where indicated by [TECH-STACK EXAMPLES] below.Give each batch subagent the following instructions (substitute the batch-specific values):
Goal: Verify the following endpoints for missing authentication and broken function-level authorization vulnerabilities. Write results to sast/missingauth-batch-[N].md.>
Your assigned endpoints (from the recon phase):
>
[Paste the full text of the assigned endpoint sections here, preserving the original numbering]
>
Context: You will be given the project's architecture summary. Use it to understand the middleware ordering, role definitions, and auth patterns.
>
Missing auth / broken function-level auth — what to look for:
>
- Missing authentication: Sensitive action with no login/session/token required. - Broken function-level authorization: Authentication is required but no role/permission check on a privileged endpoint (vertical escalation).
>
What this skill is NOT — do not flag these here: - IDOR / horizontal escalation: User A accessing user B's resource by changing an ID → covered by the IDOR skill. - JWT crypto/verification bugs → covered by sast-jwt.
>
Authorization patterns that PREVENT issues — if you see these, the endpoint is likely safe: 1. Authentication + role-check middleware on a route group (e.g.,router.use('/admin', auth, requireRole('admin'))) 2. Declarative role annotations (e.g.,@PreAuthorize("hasRole('ADMIN')")) 3. In-handler role check before sensitive action 4. Middleware gate on entire prefix (e.g., Chir.GroupwithAdminOnly) 5. Policy/Gate objects enforcing privileged actions
>
Vulnerable vs. Secure examples for this project's tech stack:
>
[TECH-STACK EXAMPLES]
>
For each assigned endpoint, evaluate:
>
1. Authentication check — is a valid login/session/token required? - Is there an auth middleware, decorator, or guard on this route or its parent group? - Trace the middleware chain — confirm the auth middleware runs BEFORE the handler, not after - Check if the route is accidentally mounted outside an auth-protected group
>
2. Role/permission check — if the endpoint is privileged, is a role or permission verified? - Look for:is_admin,is_staff,role == 'admin',hasRole('ADMIN'),@PreAuthorize,requireRole,can?(:manage, ...),Gate::allows,authorize('admin-action')- Verify the check runs on every HTTP method — a DELETE may be unguarded even if GET is protected - Check that the role comparison is not inverted or trivially bypassable
>
3. Edge cases: - Is the check conditional on a user-controlled header, parameter, or query string? - Does the auth gate apply to the route group but the specific route is excluded via an except list? - Is there a secondary unauthenticated path to the same function (e.g., an internal API alias)? - Does the middleware apply only to some environments (e.g., skipped in test mode)?>
4. Privilege identification: - Does the endpoint path suggest it is admin/privileged (/admin/,/manage/,/internal/)? - Does the operation affect other users' data, system configuration, or aggregate records? - If yes to either, a role/permission check should be present
>
Classification: - Vulnerable: No authentication required, or authenticated but role check is entirely absent on a privileged endpoint. - Likely Vulnerable: Auth and/or role check exists but appears incomplete, bypassable, or misapplied (e.g., wrong role, wrong HTTP method, conditional skip). - Not Vulnerable: Proper authentication and role/permission checks are in place. - Needs Manual Review: Cannot determine with confidence (e.g., complex middleware chain, dynamic role loading, authorization delegated to a service layer).
>
Output format — write to sast/missingauth-batch-[N].md:>
```markdown # Missing Auth Batch [N] Results
>
## Findings
>
### [VULNERABLE] Endpoint name - File:path/to/file.ext(lines X-Y) - Endpoint:METHOD /path- Issue: [Missing authentication / Missing role check for privileged action] - Impact: [What an unauthenticated or low-privilege attacker can do] - Proof: [Show the route definition and handler — highlight the missing check] - Remediation: [Specific fix — add auth middleware, add role decorator, etc.] - Dynamic Test: ``[curl command or step-by-step to confirm on the live app. For missing auth: show the request with NO token succeeding. For missing role: show the request with a regular user token succeeding on an admin endpoint. Use placeholders like <REGULAR_USER_TOKEN>, <ADMIN_ENDPOINT>.]``
>
### [LIKELY VULNERABLE] Endpoint name - File:path/to/file.ext(lines X-Y) - Endpoint:METHOD /path- Issue: [What's incomplete about the check] - Concern: [Why this might still be exploitable] - Proof: [Show the code path with the weak/partial check] - Remediation: [Specific fix] - Dynamic Test: ``[curl command or step-by-step instructions to confirm this finding on the live app.]``
>
### [NOT VULNERABLE] Endpoint name - File:path/to/file.ext(lines X-Y) - Endpoint:METHOD /path- Protection: [How it's protected — auth middleware + role decorator / @PreAuthorize / Gate, etc.]
>
### [NEEDS MANUAL REVIEW] Endpoint name - File:path/to/file.ext(lines X-Y) - Endpoint:METHOD /path- Uncertainty: [Why automated analysis couldn't determine the status] - Suggestion: [What to look at manually] ```
After all Phase 2 batch subagents complete, read every sast/missingauth-batch-*.md file and merge them into a single sast/missingauth-results.md. You (the orchestrator) do this directly — no subagent needed.
Merge procedure:
sast/missingauth-batch-1.md, sast/missingauth-batch-2.md, ... files.sast/missingauth-results.md using this format:# Missing Auth/Authz Analysis Results: [Project Name]
## Executive Summary
- Endpoints analyzed: [total across all batches]
- Vulnerable: [N]
- Likely Vulnerable: [N]
- Not Vulnerable: [N]
- Needs Manual Review: [N]
## Findings
[All findings from all batches, grouped by classification:
VULNERABLE first, then LIKELY VULNERABLE, then NEEDS MANUAL REVIEW, then NOT VULNERABLE.
Preserve every field from the batch results exactly as written.]sast/missingauth-results.md, delete all intermediate files: sast/missingauth-recon.md and sast/missingauth-batch-*.md.sast/architecture.md and pass its content to all subagents as context.use('/admin', adminRouter) pattern protects all routes in adminRouter, but routes mounted outside that group are not protected.sast/missingauth-recon.md and all sast/missingauth-batch-*.md files after the final sast/missingauth-results.md is written.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.