MEDIUM log injectionadonisjs

Log Injection in Adonisjs

How Log Injection Manifests in Adonisjs

Log injection in Adonisjs occurs when untrusted user input is directly written to log files without proper sanitization. This creates several security vulnerabilities specific to Adonisjs applications.

The most common pattern involves using console.log() or Adonisjs's Logger within route handlers to debug or track user activity. For example:

Route.post('users', async ({ request, response, logger }) => {
  const userData = request.only(['username', 'email', 'password'])
  
  // Vulnerable: Direct log injection
  logger.info(`User ${userData.username} created with email ${userData.email}`)
  
  // ... rest of logic
})

An attacker could submit a username like admin"; process.exit()//, causing the log to contain malicious content that could be executed if the log is processed by another system.

Adonisjs's Logger service, while powerful, doesn't automatically sanitize input. When using structured logging:

logger.info('User created', {
  user: request.input('username'),
  email: request.input('email')
})

The structured format helps but doesn't prevent injection if the values themselves contain malicious content like newline characters or log formatting sequences.

Another Adonisjs-specific scenario involves logging database query results or error objects that may contain user-controlled data:

try {
  const user = await User.findBy('email', email)
  logger.info(`Found user: ${user}`) // Could expose sensitive data
} catch (error) {
  logger.error(`Database error: ${error.message}`) // May log stack traces with sensitive paths
}

Adonisjs's development environment often logs stack traces that include absolute file paths, which can reveal application structure to attackers.

Adonisjs-Specific Detection

Detecting log injection in Adonisjs requires examining both code patterns and runtime behavior. Using middleBrick's API scanner, you can identify vulnerable endpoints by scanning your Adonisjs application's routes.

middleBrick analyzes the unauthenticated attack surface and identifies endpoints that accept user input likely to be logged. It specifically looks for:

  • Route handlers that accept parameters without validation
  • Direct use of console.log() or logger with request data
  • Structured logging with unvalidated user input
  • Middleware that logs request headers or body content
  • Database error logging that might expose stack traces

The scanner tests these endpoints with payloads containing newline characters, log formatting sequences, and other injection patterns. For example, it might submit a username like:

attacker
INFO:root:Malicious log entry
username

If your application logs this content directly, middleBrick will flag it as a log injection vulnerability.

Adonisjs developers can also use the built-in logger configuration to detect issues. Check your config/logger.ts for transports that write to files or external services:

import Logger from '@ioc:Adonis/Core/Logger'

export default class LogInjectionDetector {
  public static detectInjection(payload: string): boolean {
    // Check for newline characters, carriage returns, and log formatting
    const injectionPatterns = /[\n\r%]/
    return injectionPatterns.test(payload)
  }

  public static scanRoute(route: Route) {
    // Analyze route handlers for logging patterns
    const handlerCode = route.handler.toString()
    // Look for logger.info, logger.error, console.log patterns
  }
}

Run this analysis during development to catch potential log injection points before deployment.

Adonisjs-Specific Remediation

Remediating log injection in Adonisjs requires a defense-in-depth approach using the framework's native features. Start by implementing input sanitization in your route handlers:

import { sanitize } from 'sanitize-text'

Route.post('users', async ({ request, response, logger }) => {
  const userData = request.only(['username', 'email'])
  
  // Sanitize all user input before logging
  const safeUsername = sanitize(userData.username)
  const safeEmail = sanitize(userData.email)
  
  logger.info('User created', {
    username: safeUsername,
    email: safeEmail
  })
  
  // Continue with business logic
})

The sanitize-text package removes potentially dangerous characters while preserving readability.

Adonisjs's Logger service supports custom formatters that can automatically sanitize log messages. Create a custom formatter in app/Logger/Formatters/SafeFormatter.ts:

import { Formatter } from '@adonisjs/logger'

export class SafeFormatter extends Formatter {
  public format(level: string, message: string, meta: any) {
    // Sanitize message and metadata
    const safeMessage = this.sanitize(message)
    const safeMeta = Object.keys(meta).reduce((acc, key) => {
      acc[key] = this.sanitize(String(meta[key]))
      return acc
    }, {})
    
    return super.format(level, safeMessage, safeMeta)
  }

  private sanitize(input: string): string {
    // Remove newlines, carriage returns, and log formatting characters
    return input.replace(/[\n\r%]/g, '?')
  }
}

Configure it in config/logger.ts:

import { SafeFormatter } from 'App/Logger/Formatters/SafeFormatter'

const loggerConfig = {
  formatter: new SafeFormatter(),
  // ... other config
}

For structured logging, use Adonisjs's validation system to ensure log data meets safety requirements:

import { schema, rules } from '@ioc:Adonis/Core/Validator'

const logSchema = schema.create({
  username: schema.string.optional({
    escape: true,
    trim: true
  }),
  email: schema.string.optional({
    escape: true,
    trim: true,
    format: rules.email()
  })
})

Route.post('users', async ({ request, response, logger }) => {
  const logData = await request.validate({
    schema: logSchema,
    data: request.only(['username', 'email'])
  })
  
  logger.info('User created', logData)
  
  // Continue with business logic
})

This approach ensures only validated, sanitized data reaches your logs.

Frequently Asked Questions

How can I test if my Adonisjs application is vulnerable to log injection?
Use middleBrick's API scanner to automatically test your endpoints. It will submit payloads containing newline characters and log formatting sequences to identify vulnerable logging patterns. You can also manually test by submitting usernames with newline characters and checking your log files for unexpected formatting.
Does Adonisjs's built-in Logger automatically sanitize input?
No, Adonisjs's Logger does not automatically sanitize input. It's designed for flexibility and performance, leaving security measures like sanitization to the developer. You need to implement sanitization either through custom formatters, validation schemas, or manual input cleaning before logging.