HIGH token leakageadonisjs

Token Leakage in Adonisjs

How Token Leakage Manifests in Adonisjs

Token leakage in Adonisjs applications occurs when authentication tokens—whether JWTs, API keys, or session identifiers—are inadvertently exposed through logs, error responses, or insecure storage mechanisms. Adonisjs's middleware-based architecture and logging system create specific patterns where this vulnerability commonly appears.

The most frequent manifestation occurs in Adonisjs's built-in logger. By default, Adonisjs logs all request data, including headers, query parameters, and body content. When authentication tokens are included in these request components, they appear verbatim in log files. Consider this typical Adonisjs route handler:

Route.post('auth/login', async ({ auth, request, response }) => {
  const { email, password } = request.body()
  const token = await auth.attempt(email, password)
  logger.info('Login successful', { user: email, token })
  return response.ok({ token })
})

Here, the token is logged directly, creating a persistent record in log files that may be accessible to unauthorized users or stored in less-secure locations. The same issue appears when tokens are included in error responses—Adonisjs's default error handling may expose stack traces containing token values.

Another Adonisjs-specific pattern involves the HttpContext object. When developers log the entire context for debugging:

Route.get('profile', async ({ auth, response }) => {
  logger.debug('User context', auth.ctx)
  return response.ok(await User.find(auth.user.id))
})

The auth.ctx object contains the token, which gets logged in plaintext. Additionally, Adonisjs's session management can leak tokens if sessions are stored in databases without proper encryption, or if session IDs are exposed through URL parameters in development environments.

Adonisjs-Specific Detection

Detecting token leakage in Adonisjs requires examining both code patterns and runtime behavior. Start by auditing your route handlers for direct token logging:

grep -r "logger\.\|console\.log"  | grep -E "(token|auth|jwt)"

Look for patterns where tokens are passed directly to logging functions or included in response objects. Next, examine your auth configuration in config/auth.js:

module.exports = {
  authenticator: 'jwt',
  secret: Env.get('APP_KEY'),
  expiry: '1 days',
  // Check if tokens are being logged in middleware
  logging: false // Set to false to prevent auth logging
}

Adonisjs's middleware stack can be inspected to identify where tokens might be exposed. The auth middleware, by default, attaches tokens to the request context, making them accessible throughout the request lifecycle.

middleBrick's API security scanner specifically detects token leakage in Adonisjs applications by:

  • Scanning for hardcoded tokens in configuration files
  • Detecting tokens in response bodies through black-box testing
  • Identifying insecure logging patterns through code analysis
  • Checking for tokens in error responses and stack traces

The scanner's LLM/AI Security module also tests for system prompt leakage if you're using Adonisjs with AI integrations, which is particularly relevant for applications using AdonisJS Lucid models with AI-generated content.

For runtime detection, enable Adonisjs's request logging middleware with filtering:

const { route } = use('@adonisjs/core/http2/route')

Route
 .get('/api/*', async (ctx) => {
    // Request logging with token masking
    const maskedHeaders = Object.fromEntries(
      Object.entries(ctx.request.headers()).map(([key, value]) => 
        key.toLowerCase().includes('authorization') ? [key, 'REDACTED'] : [key, value]
      )
    )
    logger.info('API request', { headers: maskedHeaders })
    return await next(ctx)
  })
 .use(async (ctx, next) => {
    // Mask tokens in response logging
    const originalSend = ctx.response.send.bind(ctx.response)
    ctx.response.send = async (body) => {
      if (body?.token) body.token = 'REDACTED'
      return originalSend(body)
    }
    return next(ctx)
  })

Adonisjs-Specific Remediation

Remediating token leakage in Adonisjs requires a layered approach using the framework's built-in features. Start with the logger configuration in config/app.js:

module.exports = {
  logger: {
    transport: 'file',
    level: 'info',
    // Mask sensitive data in logs
    mask: ['password', 'token', 'authorization', 'api_key', 'secret']
  }
}

This configuration automatically redacts sensitive fields from log entries. For more granular control, create a custom logging middleware:

const { Service } = require('@adonisjs/core/di')

class SecureLogger extends Service {
  constructor(logger) {
    this.logger = logger
  }

  info(message, context = {}) {
    const sanitized = this.sanitize(context)
    this.logger.info(message, sanitized)
  }

  sanitize(obj) {
    if (typeof obj !== 'object' || obj === null) return obj
    
    return Object.fromEntries(
      Object.entries(obj).map(([key, value]) => {
        if (key.match(/token|auth|key|secret/i)) {
          return [key, value ? 'REDACTED' : value]
        }
        if (typeof value === 'object') {
          return [key, this.sanitize(value)]
        }
        return [key, value]
      })
    )
  }
}

module.exports = SecureLogger

Implement token-aware error handling by extending Adonisjs's error handler:

const { Service } = require('@adonisjs/core/di')

class SecureErrorHandler extends Service {
  async handle(error, { response }) {
    // Remove tokens from error context
    if (error.context) {
      error.context = Object.fromEntries(
        Object.entries(error.context).filter(([key]) => 
          !key.match(/token|auth|key|secret/i)
        )
      )
    }
    
    response.status(error.status || 500).json({
      error: error.message,
      code: error.code,
      // Never expose tokens in error responses
    })
  }
}

module.exports = SecureErrorHandler

For API responses, implement a response wrapper that automatically masks tokens:

const { Service } = require('@adonisjs/core/di')

class SecureResponse extends Service {
  constructor(response) {
    this.response = response
  }

  ok(data, options = {}) {
    const sanitized = this.sanitize(data)
    return this.response.ok(sanitized, options)
  }

  sanitize(data) {
    if (typeof data !== 'object' || data === null) return data
    
    if (data.token) data.token = 'REDACTED'
    
    return Object.fromEntries(
      Object.entries(data).map(([key, value]) => {
        if (typeof value === 'object') {
          return [key, this.sanitize(value)]
        }
        return [key, value]
      })
    )
  }
}

module.exports = SecureResponse

Finally, integrate middleBrick's CLI into your development workflow to continuously scan for token leakage:

# Install middleBrick CLI
npm install -g middlebrick

# Scan your Adonisjs API
middlebrick scan https://your-api.com --type=adonisjs --output=json > report.json

# Add to package.json scripts
"scripts": {
  "security:scan": "middlebrick scan https://your-api.com --type=adonisjs"
}

This combination of code patterns, middleware, and automated scanning ensures comprehensive protection against token leakage in Adonisjs applications.

Frequently Asked Questions

How does token leakage differ between Adonisjs and other Node.js frameworks?
Adonisjs's convention-over-configuration approach means tokens are more likely to be automatically included in logging and error handling contexts. The framework's active record pattern with Lucid models can also inadvertently expose tokens through model relationships, whereas Express.js requires more explicit handling but gives developers finer control over what gets logged.
Can middleBrick detect token leakage in Adonisjs applications that use custom authentication strategies?
Yes, middleBrick's black-box scanning methodology tests the actual runtime behavior of your API endpoints, regardless of the authentication implementation. It examines response bodies, error messages, and logs for token patterns, and its code analysis can detect insecure logging patterns even in custom authentication middleware.