MEDIUM email injectionfeathersjsapi keys

Email Injection in Feathersjs with Api Keys

Email Injection in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability

Email Injection in FeathersJS occurs when user-controlled input is concatenated into email headers or message bodies without validation or sanitization. This becomes particularly relevant when API access is controlled via Api Keys, because developers may assume that key-based authentication alone limits risk. In FeathersJS, services typically accept payloads that include fields such as to, from, or message when sending emails through integrations like SMTP or email APIs. If these fields are directly interpolated into headers or templates, an attacker can inject additional headers (e.g., CC, BCC, or Reply-To) or newline characters to alter the routing of the email.

When Api Keys are used, the API endpoint may expose an unauthenticated or weakly scoped route that accepts email-sending requests. Because middleBrick scans unauthenticated attack surfaces by default, it can detect whether email-sending endpoints are reachable via Api Key parameters that are improperly validated. Attackers can exploit this by injecting newline sequences (e.g., %0D%0A or \r\n) into header fields, leading to header manipulation or cross-protocol injection. For example, a crafted payload could append a second To: header or inject a Bcc: header to silently copy the email to an attacker-controlled address.

Real-world attack patterns include using CRLF injection to bypass intended recipients, which may expose internal communications or trigger phishing campaigns from a trusted domain. This maps to the OWASP API Top 10 category 'Broken Object Level Authorization' and can be detected by middleBrick’s BOLA/IDOR and Input Validation checks. The scanner tests whether newline characters in email fields lead to unexpected header splits, and whether Api Key–protected endpoints allow unauthenticated invocation of the email-sending service.

Because FeathersJS often relies on hooks and external transports like nodemailer, improperly sanitized input can propagate into SMTP transactions. middleBrick’s Email Injection checks validate that user-supplied data is escaped or whitelisted before being passed to transport layers. The tool also cross-references OpenAPI specs, so if your email-sending route is defined with parameters such as email.to or email.subject

In summary, the combination of FeathersJS email services and Api Keys does not inherently secure the system; if input validation is weak, Api Keys can become a vector for abuse where endpoints accept maliciously crafted email headers. middleBrick detects these issues by running active probes and spec–runtime correlation without requiring credentials, ensuring that injection risks are surfaced regardless of authentication assumptions.

Api Keys-Specific Remediation in Feathersjs — concrete code fixes

To remediate Email Injection in FeathersJS when using Api Keys, ensure that all email-related input is validated, sanitized, and strictly scoped. Avoid directly inserting user input into email headers. Instead, use a dedicated library or framework utilities to construct headers safely. Below are concrete code examples demonstrating secure patterns.

// src/services/email-notification/service.js
const { Service } = require('feathersjs');
const nodemailer = require('nodemailer');

class EmailNotificationService extends Service {
  async create(data, params) {
    const { apiKey } = params.query || {};
    // Validate Api Key before proceeding (example validation)
    if (!apiKey || !isValidApiKey(apiKey)) {
      throw new Error('Invalid API Key');
    }

    const { to, subject, text } = data;

    // Strict validation: allow only alphanumeric and limited special chars in email
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (!emailRegex.test(to)) {
      throw new Error('Invalid recipient email');
    }

    // Sanitize subject: remove newlines and control characters
    const sanitizedSubject = subject.replace(/[\r\n]+/g, ' ').substring(0, 255);

    // Sanitize text body if needed
    const sanitizedText = text ? text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '') : '';

    // Use nodemailer with secure header construction
    const transporter = nodemailer.createTransport({
      host: process.env.SMTP_HOST,
      port: parseInt(process.env.SMTP_PORT, 10) || 587,
      secure: false,
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS,
      },
    });

    const mailOptions = {
      from: process.env.EMAIL_FROM,
      to: to,
      subject: sanitizedSubject,
      text: sanitizedText,
      // Explicitly avoid injecting custom headers from user input
    };

    await transporter.sendMail(mailOptions);
    return { status: 'sent' };
  }
}

function isValidApiKey(key) {
  // Example: compare against stored hashed keys
  return key && key.length === 32;
}

module.exports = function () {
  const app = this;
  app.use('/email-notify', new EmailNotificationService({
    name: 'email-notify',
    paginate: { default: 10, max: 100 },
  }));

  const emailService = app.service('email-notify');
  emailService.hooks({
    before: {
      create: [context => {
        // Ensure Api Key presence and optionally scope permissions
        if (!context.params.query || !context.params.query.apiKey) {
          throw new Error('Api Key is required');
        }
        return context;
      }],
    },
  });
};

In this example, the Api Key is validated before any email processing, and user-supplied to and subject fields are strictly validated and sanitized. Note that headers are not constructed by concatenating raw user input, preventing CRLF injection. middleBrick can verify these protections by checking that the endpoint does not reflect raw newline characters in responses and that Api Key usage is enforced through hooks.

Additionally, ensure that your OpenAPI specification defines strict schemas for email service operations. For example:

paths:
  /email-notify:
    post:
      summary: Send notification email
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - to
                - subject
                - text
              properties:
                to:
                  type: string
                  pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
                subject:
                  type: string
                  maxLength: 255
                text:
                  type: string
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: Api-Key

middleBrick’s OpenAPI/Swagger analysis will flag missing patterns or insecure header usage, and its Input Validation checks will confirm that payloads are properly constrained. By combining strict input rules, header-safe construction, and Api Key gating, you reduce the risk of Email Injection while maintaining service functionality.

Frequently Asked Questions

Can middleBrick detect Email Injection in FeathersJS endpoints that use Api Keys?
Yes. middleBrick tests unauthenticated attack surfaces and can identify whether newline characters in email fields lead to header injection, even when Api Keys are present, by correlating spec definitions with runtime behavior.
Does using Api Keys alone prevent Email Injection in FeathersJS?
No. Api Keys manage access to the API endpoint but do not sanitize email headers or body content. Without input validation and safe header construction, attackers can still inject malicious headers via user-controlled fields.