HIGH log injectionadonisjsapi keys

Log Injection in Adonisjs with Api Keys

Log Injection in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability

Log injection occurs when untrusted data is written directly into application logs without proper sanitization or formatting. In AdonisJS, this risk is heightened when API keys are logged in a way that allows attackers to inject newline characters or structured log delimiters. If an API key is reflected in log output and contains carriage returns or line feeds (e.g., a key supplied via an Authorization header or a query parameter), an attacker can forge additional log entries that appear authoritative.

Consider a typical AdonisJS route that authenticates using an API key and logs the key for debugging:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Logger from '@ioc:Adonis/Core/Logger'

export default class AuthController {
  public async validateKey({ request, response }: HttpContextContract) {
    const apiKey = request.header('X-API-Key')
    Logger.info(`API key received: ${apiKey}`)
    if (apiKey !== process.env.API_KEY) {
      return response.unauthorized('Invalid key')
    }
    return response.ok({ valid: true })
  }
}

If an attacker sends a request with X-API-Key: abc123\n[CRITICAL] system failure, the log line can be split into two entries. The second line may be interpreted as a legitimate high-severity event by log monitoring tools, leading to alert fatigue or misleading incident response. This becomes particularly dangerous when logs are aggregated into dashboards or SIEMs that rely on newline delimited parsing.

AdonisJS does not inherently sanitize inputs before logging, so developers must treat API keys and other headers as potentially hostile. The framework’s built-in request validation and sanitization utilities should be used before any logging occurs. Additionally, structured logging formats (such as JSON) reduce the risk of injection by avoiding newline characters in field values, but they do not eliminate the need for input validation.

Another scenario involves logging failed authentication attempts with the provided API key. An attacker can include sequences like %0a (URL-encoded newline) or Unicode line separators to inject fabricated log lines. These injected lines can mimic successful authentication, privilege escalation, or system errors, complicating forensic analysis. Because API keys are often high-value targets, logs containing them become attractive reconnaissance sources for attackers probing log visibility and integrity.

Finally, the interaction between AdonisJS middleware and logging layers can amplify injection risks. If a middleware component logs the API key before validation and later middleware modifies the request state, logs may contain inconsistent or misleading information. Ensuring that logging occurs only after strict validation and normalization of the API key, and avoiding logging the raw key when possible, helps mitigate this class of vulnerabilities.

Api Keys-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on preventing API keys from directly entering log streams and ensuring that any logged representation is safe and non-interpretable. The primary approach is to avoid logging raw API keys entirely. Instead, log a deterministic, non-sensitive reference such as a key identifier or a hash of the key.

Example: Using a key identifier rather than the key itself:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Logger from '@ioc:Adonis/Core/Logger'

export default class AuthController {
  public async validateKey({ request, response }: HttpContextContract) {
    const apiKey = request.header('X-API-Key')
    // Derive a safe reference (e.g., hash or last 4 chars) for logging
    const keyRef = apiKey.slice(-4)
    Logger.info(`API key validation attempted, keyId: ${keyRef}`)
    if (apiKey !== process.env.API_KEY) {
      return response.unauthorized('Invalid key')
    }
    return response.ok({ valid: true })
  }
}

Example: Using environment-based constant-time comparison and structured JSON logging without newlines in values:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Logger from '@ioc:Adonis/Core/Logger'

export default class AuthController {
  public async validateKey({ request, response }: HttpContextContract) {
    const apiKey = request.header('X-API-Key')
    const safeValue = apiKey.replace(/[\r\n]+/g, ' ').substring(0, 64)
    Logger.info(JSON.stringify({ event: 'api_key_validation', keyHash: safeValue }))
    if (!this.timingSafeEqual(apiKey, process.env.API_KEY)) {
      return response.unauthorized('Invalid key')
    }
    return response.ok({ valid: true })
  }

  private timingSafeEqual(a: string, b: string): boolean {
    if (a.length !== b.length) return false
    let result = 0
    for (let i = 0; i < a.length; i++) {
      result |= a.charCodeAt(i) ^ b.charCodeAt(i)
    }
    return result === 0
  }
}

Additional measures include configuring the logging framework to sanitize fields, applying input validation rules to reject keys containing control characters, and ensuring that any error messages do not echo the raw key. Regular review of log schemas and red-team testing of log outputs help confirm that injection vectors remain closed.

Frequently Asked Questions

Can Log Injection in AdonisJS with API keys lead to remote code execution?
Log injection typically does not lead to remote code execution directly, but it can facilitate further attacks by manipulating log-based monitoring or by providing misleading evidence during incident response. The primary risk is log integrity and visibility, not immediate code execution.
Does using middleware that validates API keys before logging fully prevent log injection?
It significantly reduces risk only if validation rejects control characters and logging occurs after normalization. You must also avoid logging raw keys and prefer sanitized references or hashes to ensure log entries cannot be split or injected.