Api Abuse in Adonisjs
How API Abuse Manifests in AdonisJS
API abuse refers to a class of attacks where an adversary misuses an application's API in ways not intended by the developers, often leading to unauthorized data access, privilege escalation, or resource exhaustion. In AdonisJS, a popular Node.js MVC framework, common API abuse patterns stem from its elegant but potentially misconfigured routing, model binding, and middleware systems. Understanding these patterns is crucial for securing AdonisJS applications.
Three prevalent abuse vectors in AdonisJS are:
- Broken Object Level Authorization (BOLA/IDOR): AdonisJS's route model binding automatically fetches models based on route parameters. If authorization checks are omitted, an attacker can access or manipulate any resource by simply changing the ID in the URL.
- Broken Function Level Authorization (BFLA): AdonisJS routes can be grouped and protected with middleware. If role-based access control is not strictly enforced, low-privilege users may invoke administrative functions.
- Excessive Data Exposure: AdonisJS models, when serialized to JSON, may inadvertently include sensitive fields like password hashes or internal identifiers if not explicitly hidden.
Consider the following BOLA vulnerability in an AdonisJS controller:
// Example: Vulnerable user profile endpoint
Route.get('/users/:id', async ({ params, response }) => {
const user = await User.find(params.id)
return response.json(user)
})
Here, any authenticated user can retrieve any other user's record by providing their ID, assuming the route is behind an authentication middleware but without an ownership check.
Similarly, BFLA can occur when admin routes are not properly segmented:
// Example: Admin route without role check
Route.get('/admin/users', 'AdminController.index')
If the route is only protected by the 'auth' middleware (which ensures the user is logged in) but not by an 'admin' middleware, any logged-in user becomes an admin.
Excessive data exposure often happens when model serialization is not configured:
// Example: User model exposing sensitive fields
class User extends Model {
static get hidden () {
return ['password', 'remember_token']
}
}
If the hidden property is missing or incomplete, the password hash will be included in API responses.
AdonisJS-Specific Detection
Detecting these issues in AdonisJS applications requires a combination of code review and automated scanning. Manual detection involves inspecting route definitions for missing authorization, checking model serialization settings, and verifying middleware application. However, this process is time-consuming and error-prone.
middleBrick provides an automated solution. By submitting your AdonisJS API endpoint URL to middleBrick, you receive a comprehensive security assessment in 5–15 seconds. The scanner performs 12 security checks in parallel, including specific tests for BOLA/IDOR, BFLA, and Property Authorization. For example, middleBrick will:
- Probe endpoints with sequential IDs to detect BOLA vulnerabilities.
- Attempt to access administrative routes without proper privileges to identify BFLA.
- Analyze JSON responses for sensitive fields that should be hidden.
The result is a risk score (0–100, A–F) with prioritized findings, each including severity and remediation guidance. If your AdonisJS application has an OpenAPI/Swagger specification, middleBrick can also analyze it to cross-reference declared endpoints with runtime behavior.
You can scan from the web dashboard, use the CLI tool (middlebrick scan <url>), integrate the GitHub Action into your CI/CD pipeline, or even use the MCP Server to scan directly from your AI coding assistant.
AdonisJS-Specific Remediation
Remediating API abuse in AdonisJS involves leveraging the framework's built-in features for authorization, validation, and serialization. Here are concrete fixes for the patterns discussed.
1. Fixing BOLA/IDOR: Always enforce resource-level authorization. AdonisJS policies provide a clean way to do this. For example:
// app/Models/User.ts
import { Model, column } from '@ioc:Adonis/Lucid/Orm'
export default class User extends Model {
@column({ isPrimary: true })
public id: number
// ... other columns
}
// app/Policies/UserPolicy.ts
export default class UserPolicy {
public async update (user: User, params: { id: number }) {
// Only allow users to update their own record
return user.id === parseInt(params.id)
}
}
// app/Controllers/Http/UsersController.ts
import UserPolicy from 'App/Policies/UserPolicy'
export default class UsersController {
public async update ({ params, auth, response }: HttpContext) {
const user = await User.findOrFail(params.id)
await UserPolicy.update(auth.user!, params)
// ... update logic
}
}
Alternatively, use the authorize method in the controller or the can middleware.
2. Fixing BFLA: Apply role-based middleware to route groups. AdonisJS allows you to create custom middleware for role checks:
// app/Middleware/IsAdmin.ts
export default class IsAdmin {
public async handle ({ auth, response }: HttpContext, next: () => Promise) {
if (!auth.user?.isAdmin) {
return response.status(403).json({ error: 'Forbidden' })
}
await next()
}
}
// start/routes.ts
Route.group(() => {
Route.get('/users', 'AdminController.index')
Route.post('/users', 'AdminController.store')
}).middleware(['auth', 'isadmin'])
Ensure the middleware is registered in start/kernel.ts.
3. Fixing Excessive Data Exposure: Configure model serialization using the $hidden or $visible properties. For more control, use API resources:
// app/Models/User.ts
export default class User extends Model {
static get hidden () {
return ['password', 'remember_token', 'email_verified_at']
}
}
// Or using a resource transformer
// app/Transformers/UserTransformer.ts
export default class UserTransformer {
public includeSensitive (user: User) {
return {
id: user.id,
name: user.name,
// exclude sensitive fields
}
}
}
When using API resources, controllers return the transformed object instead of the raw model.
4. Enforcing Rate Limiting: Use the @adonisjs/rate-limiter package. Install and configure it, then apply the middleware to vulnerable endpoints:
// Install: npm i @adonisjs/rate-limiter
// Then register in start/kernel.ts
import RateLimiter from '@ioc:Adonis/Addons/RateLimiter'
Route.get('/login', 'AuthController.login')
.middleware(() => RateLimiter.ignore)
Actually, to apply rate limiting, you would use the rateLimiter middleware. Example configuration in config/rateLimiter.ts and then:
Route.group(() => {
Route.post('/login', 'AuthController.login')
}).middleware('rateLimiter:loginAttempts')
5. Validating Input: Always validate incoming requests using AdonisJS's validator. For example:
// app/Controllers/Http/AuthController.ts
import { schema, rules } from '@ioc:Adonis/Core/Validator'
export default class AuthController {
public async login ({ request, response }: HttpContext) {
const validationSchema = schema.create({
email: schema.string({ trim: true }, [rules.email()]),
password: schema.string(),
})
await request.validate({ schema: validationSchema })
// ... login logic
}
}
By systematically applying these patterns, you can mitigate common API abuse risks in AdonisJS applications. For an automated assessment, run a scan with middleBrick to identify any overlooked vulnerabilities.