Interlace ESLint
ESLint Interlace
Secure CodingRules

no-format-string-injection

Detects format string injection vulnerabilities. This rule is part of [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugin-secure-coding)

Keywords: format string injection, CWE-134, printf, util.format, logging, security

Detects format string injection vulnerabilities. This rule is part of eslint-plugin-secure-coding.

💼 This rule is set to error in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-134 (Format String Vulnerability)
SeverityCritical (CVSS 9.8)
Auto-Fix💡 Suggestions available
CategoryInjection Prevention

Vulnerability and Risk

Vulnerability: Format string injection occurs when user input is passed as the format string argument to functions like printf or util.format in Node.js.

Risk: Attackers can use format specifiers (like %s, %d, or %n) to read data from the stack, crash the application (DoS), or potentially execute arbitrary code if the underlying library or language supports writing to memory via format strings.

Rule Details

Format string injection occurs when user input is used as a format string in functions like util.format(), printf-style functions, or logging functions. Attackers can use format specifiers (%s, %d, %x) to:

  • Leak sensitive memory contents
  • Crash the application (DoS)
  • Read stack data and bypass ASLR
  • Potentially execute arbitrary code

Why This Matters

IssueImpactSolution
💾 Memory LeakInformation disclosureUse static format strings
💥 CrashDenial of serviceValidate format specifiers
🔓 Code ExecutionFull system compromiseEscape user input

Examples

❌ Incorrect

// User input as format string
const message = util.format(userInput, data);

// Printf-style with user-controlled format
console.log(userFormat, value);
logger.info(req.body.message);

// Template string from user input
const format = getUserFormat();
const output = sprintf(format, ...args);

✅ Correct

// Hardcoded format string
const message = util.format('User %s logged in from %s', username, ip);

// User input as argument, not format
console.log('User message: %s', userInput);
logger.info('Event: %s', req.body.message);

// Escape or validate user format
const safeFormat = escapeFormatSpecifiers(userInput);
const message = util.format('%s', safeFormat);

Configuration

{
  rules: {
    'secure-coding/no-format-string-injection': ['error', {
      formatFunctions: ['util.format', 'sprintf', 'printf'],
      formatSpecifiers: ['%s', '%d', '%x', '%n'],
      userInputVariables: ['req', 'request', 'input', 'body']
    }]
  }
}

Options

OptionTypeDefaultDescription
formatFunctionsstring[]['util.format', 'sprintf']Format functions to check
formatSpecifiersstring[]['%s', '%d', '%x', '%n']Format specifiers to detect
userInputVariablesstring[]['req', 'request', 'input']User input patterns
safeFormatLibrariesstring[][]Libraries with safe formatting

Error Message Format

🔒 CWE-134 OWASP:A03-Injection CVSS:9.8 | Format String Injection | CRITICAL [SOC2,PCI-DSS]
   Fix: Use hardcoded format strings or validate user formats | https://cwe.mitre.org/...

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Query from Variable

Why: Query strings from variables not traced.

// ❌ NOT DETECTED - Query from variable
const query = `SELECT * FROM users WHERE id = ${userId}`;
db.execute(query);

Mitigation: Always use parameterized queries.

Custom Query Builders

Why: Custom ORM/query builders not recognized.

// ❌ NOT DETECTED - Custom builder
customQuery.where(userInput).execute();

Mitigation: Review all query builder patterns.

Template Engines

Why: Template-based queries not analyzed.

// ❌ NOT DETECTED - Template
executeTemplate('query.sql', { userId });

Mitigation: Validate all template variables.

Further Reading

On this page