API2:2023 Broken Authentication
An endpoint that should require an authenticated caller accepts anonymous traffic, or accepts tokens the server cannot verify (JWT alg: none, HS256 signed with the public key, unsigned cookies). Anyone can then act as any user.
What Vulkro detects
- Routes whose handler is reachable without any auth middleware, dependency or guard in the auth pipeline.
- JWT misconfigurations, flagged on their own line:
alg: 'none', a hardcoded HS256 secret,verify=False.
Non-compliant code
# FastAPI: no dependency, anonymous traffic accepted
@app.get('/admin/users')
def list_users():
return db.fetch_all(User) # no auth check anywhere on the path
// Express: handler mounted without middleware
app.get('/admin/users', (req, res) => {
res.json(db.query('SELECT * FROM users')); // reachable anonymously
});
Compliant code
# FastAPI: OAuth2 dependency on the route
@app.get('/admin/users')
def list_users(user: User = Depends(get_current_user)):
return db.fetch_all(User)
// Express: auth middleware before the handler
app.use('/admin', requireAuth);
app.get('/admin/users', (req, res) => {
res.json(db.query('SELECT * FROM users'));
});
How to fix
- FastAPI: add
Depends(get_current_user)(for example withOAuth2PasswordBearer). - Flask: decorate with
@login_required(Flask-Login) or checkcurrent_user.is_authenticated. - Express:
app.use('/api', authMiddleware)before the route is mounted. - NestJS:
@UseGuards(JwtAuthGuard)on the controller method or class. - Django:
@login_required, orLoginRequiredMixinon a class-based view.
References
See also: Confidence model.
This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.