Email Injection in Feathersjs
How Email Injection Manifests in Feathersjs
Email injection in Feathersjs applications typically occurs through the feathers-authentication-management service or custom email services that accept user input for email headers. The vulnerability arises when user-controlled data flows into email headers without proper validation, allowing attackers to inject additional recipients, modify message content, or spoof sender information.
In Feathersjs, the most common attack vectors include:
- User registration flows where the
emailfield is used in thefromorreplyToheaders - Password reset tokens sent via email where the
subjectorbodycontains user input - Notification systems that construct email headers from database fields
- Custom email services that concatenate user data into MIME headers
The core issue stems from how email protocols handle newline characters. An attacker can inject \r\n sequences to add new headers. For example, if a Feathersjs application constructs an email like this:
const email = {
from: user.email,
to: '[email protected]',
subject: 'New registration',
text: `User ${user.name} registered with email ${user.email}`
};An attacker could register with an email like:
[email protected]\r\nCc: [email protected]\r\nSubject: Hacked!This would result in the email being sent to both the intended recipient and the attacker's hidden BCC address, with a modified subject line.
Feathersjs applications using feathers-authentication-management are particularly vulnerable because the library constructs emails for verification, password resets, and welcome messages. If the application extends or customizes these templates without proper input sanitization, attackers can manipulate the email content.
Another Feathersjs-specific scenario occurs when using the mailer service with dynamic templates. If user input is interpolated directly into template variables that become part of email headers, injection becomes possible. For instance:
const template = `
From: ${user.email}
To: [email protected]
Subject: ${subject}
${body}
`;Without validation, an attacker could craft a subject containing newline characters to inject arbitrary headers.
Feathersjs-Specific Detection
Detecting email injection in Feathersjs applications requires examining both the codebase and runtime behavior. Start by auditing your authentication and email services:
Code Analysis: Search for patterns where user input flows into email headers. Look for:
- Direct interpolation of user fields into email objects
- Dynamic construction of
from,to,subject, orreplyToheaders - Use of
req.userorhook.params.userin email templates - Custom email services that concatenate strings for headers
Runtime Testing: Test your application with specially crafted inputs containing \r\n sequences. For example, attempt to register with an email like:
[email protected]\r\nBCC: [email protected]Monitor the email headers in your mail logs to see if the injection succeeded.
middleBrick Scanning: middleBrick's black-box scanning can detect email injection vulnerabilities by testing unauthenticated endpoints for header injection patterns. The scanner sends payloads containing newline characters and analyzes responses for signs of successful injection. For Feathersjs applications, middleBrick specifically checks:
- Authentication endpoints that send verification emails
- Password reset flows
- User registration services
- Custom email notification endpoints
The scan tests for both basic newline injection and more sophisticated attacks like header smuggling. When vulnerabilities are found, middleBrick provides the exact payload that triggered the issue and maps it to the OWASP API Security Top 10 category A4: Lack of Input Validation.
Static Analysis with middleBrick: If you have access to your OpenAPI spec, middleBrick can analyze it alongside runtime scanning. This is particularly useful for Feathersjs applications using feathers-swagger or feathers-openapi, as the scanner can identify endpoints that accept email-related parameters and prioritize them for injection testing.
middleBrick's LLM security checks also add value here, as they can detect if your Feathersjs application has AI-powered email features (like automated email generation) that might introduce additional injection vectors through prompt injection.
Feathersjs-Specific Remediation
Securing Feathersjs applications against email injection requires a defense-in-depth approach. Here are Feathersjs-specific remediation strategies:
Input Validation: Implement strict validation for all email-related fields using libraries like validator.js:
const { isEmail, normalizeEmail } = require('validator');In your hooks or services, validate email addresses before they're used in headers:
const validateEmailHeader = async (context) => {
const { email } = context.data;
if (email && (email.includes('\r') || email.includes('\n'))) {
throw new Error('Invalid email format');
}
if (email && !isEmail(email)) {
throw new Error('Invalid email address');
}
return context;
};Sanitization: Create a Feathersjs hook to sanitize email headers:
const sanitizeEmailHeaders = async (context) => {
const sanitize = (str) => str.replace(/\r/g, '').replace(/\n/g, '');
if (context.data) {
if (context.data.email) context.data.email = sanitize(context.data.email);
if (context.data.subject) context.data.subject = sanitize(context.data.subject);
}
if (context.params.query) {
if (context.params.query.email) context.params.query.email = sanitize(context.params.query.email);
if (context.params.query.subject) context.params.query.subject = sanitize(context.params.query.subject);
}
return context;
};Service-Level Protection: For feathers-authentication-management, override the email options to ensure safe header construction:
const authManagement = require('feathers-authentication-management');
app.configure(authManagement({
service: 'users',
email: {
from: process.env.EMAIL_FROM || '[email protected]',
emailField: 'email',
subject: {
verify: 'Please verify your email',
verifyChange: 'Verify your email change',
reset: 'Password reset requested'
},
// Use templates that escape user input
templates: {
verify: {
subject: (options) => 'Please verify your email',
text: (options) => `Hello ${options.user.name}, please verify your email.`
}
}
}
}));Custom Email Services: If using Nodemailer or similar, always use the API correctly rather than string concatenation:
const sendSafeEmail = async (to, subject, text, from = process.env.EMAIL_FROM) => {
const sanitizedSubject = subject.replace(/[^\w\s.!?,]/g, '');
const sanitizedText = text.replace(/\r/g, ' ').replace(/\n/g, ' ');
return await transporter.sendMail({
from,
to,
subject: sanitizedSubject,
text: sanitizedText
});
};CI/CD Integration: Use middleBrick's GitHub Action to automatically scan your Feathersjs API before deployment:
- name: Scan with middleBrick
uses: middlebrick/middlebrick-action@v1
with:
token: ${{ secrets.MIDDLEBRICK_TOKEN }}
fail-on-severity: high
scan-url: ${{ secrets.API_URL }}
env:
MIDDLEBRICK_TOKEN: ${{ secrets.MIDDLEBRICK_TOKEN }}This ensures email injection vulnerabilities are caught in your pipeline before reaching production.