Adonisjs API Security

Adonisjs Security Posture

Adonisjs provides a solid security foundation with built-in CSRF protection, input sanitization, and secure session management. The framework automatically escapes output in templates and includes rate limiting middleware. However, its default configuration assumes a trusted environment and developer responsibility for critical security decisions.

The framework's flexible middleware system and powerful Lucid ORM can introduce vulnerabilities if not properly configured. Adonisjs prioritizes developer experience over security defaults, meaning you get a functional API quickly but must actively harden it for production. The ORM's automatic query building, while convenient, can lead to BOLA (Broken Object Level Authorization) if developers rely on user-provided IDs without proper authorization checks.

Top 5 Security Pitfalls in Adonisjs

1. Missing Authorization Middleware
Adonisjs doesn't enforce authorization by default. Developers often create routes that fetch resources by ID without verifying the requesting user's permissions. This BOLA vulnerability is particularly dangerous because Lucid's simple query syntax makes it easy to write code that looks correct but exposes all records.

// Vulnerable code - no authorization check
async show({ params, auth }) {
  const user = await User.find(params.id)
  return user
}

// Secure version
async show({ params, auth }) {
  const user = await User.find(params.id)
  if (user.id !== auth.user.id) {
    throw new Error('Unauthorized')
  }
  return user
}

2. Insecure Default CORS Configuration
The default CORS settings in Adonisjs allow all origins, which is acceptable for development but dangerous in production. Many developers forget to update these settings before deployment, exposing APIs to cross-origin attacks.

// Default (insecure)
const cors = {
  origin: ['*'],
  methods: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'],
  credentials: true,
}

// Production-ready
const cors = {
  origin: ['https://yourdomain.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true,
  maxAge: 86400,
}

3. Unvalidated Route Parameters
Adonisjs route parameters are strings by default. Developers often use them directly in database queries without type validation, leading to type confusion attacks or unintended data exposure.

// Vulnerable - string comparison issues
async show({ params }) {
  return await User.find(params.id) // params.id is a string
}

// Secure - explicit type conversion
async show({ params }) {
  const userId = parseInt(params.id, 10)
  if (isNaN(userId)) throw new Error('Invalid ID')
  return await User.find(userId)
}

4. Missing Rate Limiting on Authentication Endpoints
While Adonisjs includes rate limiting middleware, developers often forget to apply it to authentication routes. This omission enables brute-force attacks against login endpoints.

// Missing rate limiting (vulnerable)
Route.post('login', 'AuthController.login')

// Secure with rate limiting
Route.post('login', 'AuthController.login').middleware(['throttle:10,5m'])

5. Insecure File Upload Handling
Adonisjs's file upload system doesn't validate file types or scan for malware by default. Attackers can upload executable files or scripts that get served from your domain, leading to XSS or remote code execution.

// Vulnerable - accepts any file type
async upload({ request }) {
  const file = await request.file('file', {
    size: '2mb',
  })
  await file.move(uploadsPath)
}

// Secure - whitelist file types
async upload({ request }) {
  const file = await request.file('file', {
    size: '2mb',
    types: ['image'],
  })
  await file.move(uploadsPath)
}

Security Hardening Checklist

Authentication & Authorization
★ Implement policy-based authorization using Adonisjs's built-in policies ★ Never trust route parameters - always validate and authorize ★ Use prepared statements or ORM methods that prevent SQL injection ★ Implement proper session management with secure cookies

Input Validation
★ Use Adonisjs's validator with strict schemas for all inputs  Example: const schema = schema.create({ email: schema.string({}, [rules.email()]) })  Validate file uploads with type whitelisting and size limits  Sanitize all user inputs before database operations

API Security Headers
★ Configure Content Security Policy headers ★ Set proper CORS policies for production  Add security headers: X-Frame-Options, X-Content-Type-Options, Referrer-Policy  Use Helmet.js for comprehensive header security

// app/Controllers/Http/RootController.js
class RootController {
  async index({ response }) {
    response.implicitEnd = false
    response.safeHeader('X-Frame-Options', 'DENY')
    response.safeHeader('X-Content-Type-Options', 'nosniff')
    response.safeHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
    response.send('API is running')
  }
}

Rate Limiting & Monitoring
★ Apply rate limiting to all authentication and sensitive endpoints  Configure different limits for public vs private APIs  Implement request logging for audit trails  Set up alerting for unusual traffic patterns

Production Configuration
★ Never use debug mode in production  Configure proper error handling that doesn't leak stack traces  Use environment variables for secrets (API keys, database credentials)  Enable HTTPS with proper TLS configuration

Automated Security Testing
★ Scan your Adonisjs APIs with middleBrick before production deployment  middleBrick tests for BOLA, authentication bypass, and input validation issues specific to your API structure  Integrate middleBrick CLI into your CI/CD pipeline to catch regressions  Use the GitHub Action to automatically scan pull requests

Frequently Asked Questions

How does Adonisjs's Lucid ORM affect API security?
Lucid ORM's convenience can create security blind spots. Its automatic query building and relationship loading make it easy to accidentally expose related data. Always use explicit select statements and avoid loading entire relationships when you only need specific fields. The ORM doesn't enforce authorization, so you must manually verify user permissions before returning any data.
What's the best way to handle authentication in Adonisjs APIs?
Use Adonisjs's built-in authentication guard system with JWT or session-based auth. Never implement custom authentication logic. Store passwords with bcrypt (the default), use secure cookies with httpOnly and secure flags, and implement refresh token rotation. Always validate tokens on every protected route and handle token expiration gracefully.
Can middleBrick scan my Adonisjs API?
Yes, middleBrick works perfectly with Adonisjs APIs. Simply provide your API URL - middleBrick doesn't need access to your source code or database credentials. It tests the unauthenticated attack surface, checking for BOLA vulnerabilities, missing authentication, and input validation issues that are common in Adonisjs applications. The scan takes 5-15 seconds and provides a security score with specific remediation guidance.