HIGH email injectionadonisjsbasic auth

Email Injection in Adonisjs with Basic Auth

Email Injection in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

Email injection occurs when user-controlled data is improperly handled in email-related headers or commands, enabling an attacker to inject additional headers such as CC, BCC, or newlines that alter the email routing or recipients. In Adonisjs, this risk is amplified when Basic Auth is used for endpoint protection but the application does not treat the authenticated identity as strictly untrusted input.

Consider a typical Adonisjs route that sends a notification email after a user authenticates via HTTP Basic Auth. If the application reuses request body fields (e.g., a to or replyTo value) without strict validation and passes them directly to a mail driver or a lower-level email library, an attacker who knows the Basic Auth credentials can supply crafted input that introduces extra headers. For example, a newline (\n) or carriage return (\r) in the email address can terminate the current header and inject a CC or BCC header, redirecting copies of the email to unintended recipients.

When Basic Auth is in play, developers may assume the channel is trusted because a password is required. However, the authenticated identity does not sanitize the data the client submits. If the route handler uses the authenticated username or any request-supplied value in constructing email headers without normalization or allowlisting, the attack surface remains open. This becomes especially relevant when endpoints accept user-controlled input for message metadata and then feed it into templated emails or background jobs.

In the context of middleBrick’s checks, such a misconfiguration may be flagged in the Input Validation and Property Authorization categories because the framework’s validation schemas or route parameter rules did not enforce strict email formats or reject unexpected control characters. The scan can also surface BFLA or IDOR concerns if the Basic Auth identity is leveraged to determine which email addresses are permissible without proper ownership checks, allowing one authenticated user to send mail appearing to come from another user’s address.

An example of vulnerable behavior in Adonisjs might involve using the Mail contract with raw user input:

import Mail from '@ioc:Adonis/Addons/Mail'

export default class MessagesController {
  public async sendMessage({ request, auth }) {
    const user = auth.getUserOrFail()
    const { to, subject, body } = request.only(['to', 'subject', 'body'])
    await Mail.send((message) => {
      message
        .from(user.email)
        .to(to)
        .subject(subject)
        .htmlView('emails/notify', { body })
    })
  }
}

If the to field is not validated, an attacker authenticated with valid Basic Auth credentials could supply [email protected]\nCC: [email protected] as the email address, resulting in an injected CC header. The fix is not to rely on the protection of Basic Auth alone, but to validate and sanitize all email inputs, reject newlines, and use explicit allowlists for header construction, which aligns with the remediation guidance below.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on strict input validation, separation of authentication from message routing data, and avoiding the use of raw user input in email headers. Even when Basic Auth is used, treat all client-supplied data as potentially malicious.

1) Validate and normalize email addresses using a robust library or framework-level validation. In Adonisjs, you can use the built-in validator to enforce strict email formats and reject control characters:

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

const messageSchema = schema.create({
  to: schema.string({}, [ rules.email() ]),
  subject: schema.string({}, [ rules.minLength(1), rules.maxLength(255) ]),
  body: schema.string({}, [ rules.minLength(1) ])
})

export default class MessagesController {
  public async sendMessage({ request, auth, response }: HttpContextContract) {
    const payload = request.validate({ schema: messageSchema })
    const user = auth.getUserOrFail()

    // Ensure the authenticated user is allowed to send on behalf of the declared sender
    if (user.email !== payload.from) {
      return response.badRequest({ error: 'Unauthorized sender' })
    }

    await Mail.send((message) => {
      message
        .from(user.email)
        .to(payload.to)
        .subject(payload.subject)
        .htmlView('emails/notify', { body: payload.body })
    })
  }
}

2) Do not allow user input to dictate headers. Instead, construct the message with server-controlled values for from and explicit recipient lists. If you must support dynamic recipients, map them against an authorized list stored server-side rather than accepting raw addresses.

3) Reject or sanitize newlines and control characters. You can add a custom validation rule or sanitize strings before using them in email contexts:

import { sanitize } from 'some-safe-sanitizer'

const cleanTo = sanitize(payload.to, { stripNewlines: true, trim: true })

4) Use environment variables or configuration to set default sender addresses so that the application does not dynamically derive the from address from user data. Combine this with route-level middleware that enforces authentication for the endpoint while still validating all inputs independently.

5) If your application relies on scanning or automation, middleBrick’s CLI can be used to validate that your endpoints do not reflect unsanitized input in email headers when Basic Auth is enabled. Run middlebrick scan <url> to obtain an assessment of input validation and authorization coverage as part of your security testing workflow.

Frequently Asked Questions

Does using Basic Auth in Adonisjs automatically prevent email injection?
No. Basic Auth provides identity verification for requests but does not sanitize or validate user-submitted email data. Without strict validation of email headers and recipients, authenticated users can still supply malicious input that leads to email injection.
How can I test whether my Adonisjs endpoint is vulnerable to email injection when Basic Auth is used?
Use a tool like middleBrick to scan the endpoint. Submit the authenticated URL to the scanner, which will probe input validation and header handling. Additionally, manually test by sending crafted payloads with newline characters in email fields and verify that no unexpected headers are introduced in the outgoing mail.