Log Injection in Adonisjs with Basic Auth
Log Injection in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability
Log injection occurs when untrusted input is written directly into log files without sanitization or formatting control. In AdonisJS applications that use HTTP Basic Authentication, this risk arises at the intersection of authentication handling and application-generated logs. When Basic Auth credentials are processed, developers sometimes record authentication events—such as successful logins, failed attempts, or user identification—using unchecked request data (e.g., usernames, tokens, or custom headers) in log messages.
AdonisJS uses its logging system, typically based on the ace logger, where you might write entries like Logger.info('User login', { username: authUser.username }). If the username originates directly from the Basic Auth header and contains newline characters, structured log parsers can be misled. For example, a username such as alice\nMalicious: injected can cause log entries to be split into multiple logical lines, altering the structure of logs consumed by monitoring or SIEM tools. This can obscure the origin of events, bypass simple regex-based detection rules, and complicate incident response.
Another scenario involves injecting into JSON or key-value style logs. If your application logs each authentication attempt with interpolated strings like `User ${username} authenticated`, and the username includes characters that break the expected format, downstream log analysis may misinterpret severity, context, or even trigger secondary issues in log ingestion pipelines. In distributed systems where logs are aggregated centrally, a malformed entry from one service can affect correlation and search capabilities across the environment.
Basic Auth exacerbates this because the credentials are transmitted with every request and are often logged for auditing. If an endpoint logs the presence of a token or role claim extracted from Basic Auth without validation, an attacker who controls the credential string can manipulate log content across multiple dimensions: line-based formats, structured fields, or metadata appended by middleware. This does not require authentication bypass—simply sending a crafted Authorization header is sufficient to pollute logs, potentially hiding follow-up attacks or evading detection.
While middleBrick does not perform fixes, its scans highlight log injection risks in authentication flows by correlating runtime behavior with OpenAPI specifications and the OWASP API Top 10. The tool identifies endpoints where authentication inputs are reflected in observable outputs such as logs, and it provides remediation guidance to help developers structure log entries safely and validate inputs before they are recorded.
Basic Auth-Specific Remediation in Adonisjs — concrete code fixes
To mitigate log injection in AdonisJS when using Basic Auth, ensure that any user-controlled data written to logs is sanitized, escaped, or omitted. The following examples show secure patterns for handling Basic Auth credentials and logging them safely.
Secure Basic Auth handling and logging
First, configure Basic Auth in AdonisJS using middleware that validates credentials against a known source. Avoid directly logging the raw credential string. Instead, extract only the necessary, validated fields and escape them before logging.
// start/hooks.ts
import { Exception } from '@poppinss/utils'
export const handle = async (ctx, next) => {
const authHeader = ctx.request.headers().authorization
if (!authHeader || !authHeader.startsWith('Basic ')) {
throw new Exception('Unauthorized', 401, 'E_UNAUTHORIZED')
}
const base64 = authHeader.split(' ')[1]
const decoded = Buffer.from(base64, 'base64').toString('utf-8')
const [username, password] = decoded.split(':')
// Perform your authentication check here (e.g., compare password hash)
const user = await User.findBy('username', username)
if (!user || user.password !== hashPassword(password)) {
// Log with sanitized input: use a fixed identifier, not raw username
Logger.warn('Failed login attempt', { userId: user?.id || 'unknown' })
throw new Exception('Invalid credentials', 401, 'E_INVALID_CREDENTIALS')
}
// On success, log using an immutable user ID, not the raw credential
Logger.info('User login', { userId: user.id, username: user.username })
ctx.auth.login(user)
await next()
}
In the example above, the raw username from the Basic Auth header is used only for lookup. When logging, we reference user.id (a database primary key) rather than the potentially problematic username. If you must include the username in logs, escape newline and control characters:
const safeUsername = (user.username || '').replace(/[\r\n]/g, '\\n')
Logger.info('User login', { username: safeUsername })
Additionally, ensure that any structured logging format (such as JSON) does not allow injection of extra fields. Validate that usernames and passwords do not contain characters that could split lines or break parsers. For middleware-based authentication, you can also centralize logging in a single location to enforce consistency across routes.
Complementary practices
- Use structured logging libraries that enforce schema validation for log entries.
- Avoid logging raw Authorization headers; if necessary, redact or hash sensitive parts.
- Review log aggregation settings to ensure parsers are configured to handle escaped characters correctly.
middleBrick can detect endpoints where authentication inputs are overly permissive or reflected in log-related outputs. By scanning your API with the CLI (middlebrick scan <url>) or through the Web Dashboard, you can identify risky patterns in your Basic Auth implementation and receive prioritized findings with remediation steps aligned with OWASP API Top 10 and compliance frameworks.