Weakness reference
CWE-140

Improper Neutralization of Delimiters

This weakness occurs when software fails to properly handle or escape delimiter characters such as quotes, commas, newlines, or pipes that are used to…

01Summary

This weakness occurs when software fails to properly handle or escape delimiter characters (such as quotes, commas, newlines, or pipes) that are used to structure data. An attacker can inject extra delimiters into user input to break out of intended data boundaries, causing the application to misinterpret the structure of the data and execute unintended logic or expose sensitive information.

02How It Happens

Delimiters are special characters used to mark boundaries between data fields or records — for example, commas in CSV files, quotes in SQL strings, or newlines in log entries. When an application accepts user input and incorporates it directly into a delimited data structure without escaping or validating those delimiter characters, an attacker can inject additional delimiters to alter how the parser interprets the data. The application may then treat injected content as a new field, record, or command rather than as literal data, leading to logic bypass or data corruption.

03Real-World Impact

Delimiter injection can lead to several serious outcomes. In CSV or log contexts, injected newlines can create fake log entries that hide malicious activity or frame legitimate users. In configuration files or data serialization, delimiter injection can alter application behavior or inject malicious settings. In some cases, delimiter injection combined with other weaknesses (such as insufficient input validation) can facilitate SQL injection, command injection, or privilege escalation. The severity depends on what data structure is being manipulated and what trust is placed in its contents downstream.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import csv
import io

def export_user_data(username, email):
    # User input is directly inserted into CSV without escaping
    csv_line = f"{username},{email}\n"
    return csv_line

# Attacker input: username = "admin\nmalicious,data"
# Result: CSV structure is broken; parser sees two rows instead of one
output = export_user_data("admin\nmalicious", "attacker@example.com")
print(output)

Why it's vulnerable:
The newline character in the username is not escaped, allowing an attacker to inject a fake CSV row that will be parsed as a separate record.

Fixed pattern
import csv
import io

def export_user_data(username, email):
    # Use csv.writer to properly escape delimiters
    output = io.StringIO()
    writer = csv.writer(output)
    writer.writerow([username, email])
    return output.getvalue()

# Attacker input: username = "admin\nmalicious,data"
# Result: Newline and comma are properly escaped; parser sees one row
output = export_user_data("admin\nmalicious", "attacker@example.com")
print(output)
Vulnerable pattern
<?php
function log_user_action($user_id, $action) {
    // User input is directly concatenated into log entry
    $log_entry = "$user_id | $action\n";
    file_put_contents('activity.log', $log_entry, FILE_APPEND);
}

// Attacker input: $action = "login\nadmin | delete_user"
// Result: Log contains a fake entry that appears to be from admin
log_user_action(123, "login\nadmin | delete_user");
?>

Why it's vulnerable:
The newline and pipe characters in the action string are not escaped, allowing an attacker to inject a fake log line that mimics a different user or action.

Fixed pattern
<?php
function log_user_action($user_id, $action) {
    // Escape delimiters: replace newlines and pipes with safe alternatives
    $user_id = str_replace(["\n", "\r", "|"], "", $user_id);
    $action = str_replace(["\n", "\r", "|"], "", $action);
    $log_entry = "$user_id | $action\n";
    file_put_contents('activity.log', $log_entry, FILE_APPEND);
}

// Attacker input: $action = "login\nadmin | delete_user"
// Result: Delimiters are stripped; log entry is safe
log_user_action(123, "login\nadmin | delete_user");
?>

05Prevention Checklist

Identify all delimiters
used in your data structures (CSV commas, newlines, pipes, quotes, etc.) and document them.
Use built-in libraries
for structured data formats (e.g., csv module in Python, fputcsv() in PHP) rather than manual string concatenation.
Escape or remove delimiter characters
from user input before incorporating it into delimited data; use the appropriate escaping method for your format.
Validate input format
— reject or sanitize input that contains unexpected delimiter characters if they are not part of the intended data.
Test with adversarial input
— include newlines, quotes, commas, and other delimiters in your test cases to verify they are handled safely.
Review log and configuration parsing
— ensure that any code that reads delimited data (logs, configs, CSV files) does not trust the structure without validation.

06Signs You May Already Be Affected

Look for unexpected or malformed entries in log files, CSV exports, or configuration data — particularly entries that appear to come from users who were not active at that time, or entries with unusual formatting. If you notice that user input containing special characters (newlines, quotes, pipes) appears to have altered application behavior or created duplicate records, delimiter injection may be occurring. Review access logs and audit trails for entries that seem out of place or inconsistent with normal user activity patterns.

07Related Recent Vulnerabilities