Weakness reference
CWE-134

Use of Externally-Controlled Format String

A format string vulnerability occurs when user-supplied input is passed directly as a format string to functions like printf, sprintf, or similar formatting…

01Summary

A format string vulnerability occurs when user-supplied input is passed directly as a format string to functions like printf(), sprintf(), or similar formatting routines. An attacker can craft malicious input containing format specifiers (like %x or %n) to read from or write to arbitrary memory locations, potentially exposing sensitive data or executing code.

02How It Happens

Format string functions interpret special sequences in their format argument to control how subsequent arguments are processed and displayed. When an application constructs the format string from untrusted input—rather than using user input only as *data* to be formatted—an attacker gains direct control over the format specifiers themselves. The function then interprets the attacker's input as instructions to access the stack or heap, bypassing normal memory access controls. This is particularly dangerous because the vulnerability exists in widely-used, low-level functions that developers often assume are safe.

03Real-World Impact

Format string vulnerabilities can lead to information disclosure (reading stack memory to leak passwords, tokens, or addresses), memory corruption (overwriting critical variables or function pointers), or arbitrary code execution (by writing to executable memory or function pointers). The severity depends on the application's privileges and what data is accessible in memory, but in many cases the impact is severe enough to compromise the entire system.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sys

user_input = sys.argv[1]
message = "User said: %s" % user_input
print(message)

Why it's vulnerable:
If user_input contains format specifiers like %x or %s, the % operator will interpret them as formatting instructions rather than literal text, potentially reading from memory.

Fixed pattern
import sys

user_input = sys.argv[1]
message = "User said: %s" % (user_input,)
print(message)
Vulnerable pattern
<?php
$user_input = $_GET['message'];
printf($user_input);
?>

Why it's vulnerable:
The printf() function interprets format specifiers in $user_input. An attacker can supply %x%x%x to read stack values or %n to write to memory.

Fixed pattern
<?php
$user_input = $_GET['message'];
printf("%s", $user_input);
?>

05Prevention Checklist

Never pass user input directly as a format string.
Always use a fixed, hardcoded format string and pass user data as separate arguments.
Use parameterized formatting functions.
In Python, prefer f-strings or .format() with explicit placeholders; in PHP, always provide a format string literal to printf(), sprintf(), etc.
Validate and sanitize input.
Reject or escape any input containing % characters if format strings are unavoidable (though they should be avoided).
Use static analysis tools.
Linters and SAST scanners can flag cases where user input flows into format string functions.
Code review format-string functions.
During review, pay special attention to printf(), sprintf(), fprintf(), syslog(), and similar functions to ensure the format argument is always a literal string.
Apply principle of least privilege.
Run the application with minimal permissions to limit the damage if a format string vulnerability is exploited.

06Signs You May Already Be Affected

Look for unexpected memory reads or writes in application logs, crashes with segmentation faults or access violations, or unusual behavior when certain special characters (especially %) are submitted in form fields or query parameters. If an attacker has exploited this vulnerability, you may also observe unexpected changes to configuration files, unauthorized admin accounts, or evidence of code execution in system logs.

07Related Recent Vulnerabilities