Skip to main content

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 with OAuth2PasswordBearer).
  • Flask: decorate with @login_required (Flask-Login) or check current_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, or LoginRequiredMixin on 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.