Skip to content

Rust: Implement a new query for Log Injection #20221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 13, 2025

This PR implements a comprehensive CodeQL query for detecting log injection vulnerabilities in Rust code, following the patterns established by existing log injection queries for other languages.

Overview

Log injection occurs when user-controlled data is included in log output without proper sanitization, allowing malicious users to forge log entries. This is particularly dangerous when logs are processed by automated systems or displayed in web interfaces.

Implementation

The query follows the same architecture as the existing rust/sql-injection query and includes:

Core Components

  • LogInjectionExtensions.qll: Defines sources, sinks, and barriers using ActiveThreatModelSource for sources and the existing sinkNode(this, "log-injection") infrastructure
  • LogInjection.ql: Main query with taint tracking configuration that detects data flow from user input to logging functions
  • LogInjection.qhelp: Documentation explaining the vulnerability with Rust-specific examples and remediation guidance

Examples

  • LogInjectionBad.rs: Demonstrates vulnerable code where user input flows directly to logging functions
  • LogInjectionGood.rs: Shows secure implementation with proper input sanitization

Test Coverage

  • Comprehensive test suite with 20 test cases covering various scenarios:
    • Direct logging through different log levels (info, warn, error, debug, trace)
    • Formatted strings and string concatenation with user input
    • Indirect flows through variables, function parameters, and data structures
    • Flow through collections (Vec, Option, Result)
    • Both vulnerable and safe patterns

Example Detection

use log::info;
use std::env;

fn main() {
    let username = env::args().nth(1).unwrap_or_default();
    
    // BAD: User input directly in log message
    info!("User login: {}", username); // Query will flag this
    
    // GOOD: Sanitized input
    let clean_username = username.replace('\n', "").replace('\r', "");
    info!("User login: {}", clean_username); // Safe
}

If a malicious user provides Guest\n[INFO] Admin logged in\n as input, the vulnerable code would create a forged log entry appearing to show an admin login.

Query Details

  • ID: rust/log-injection
  • Severity: Error (7.8 security severity)
  • Precision: Medium
  • Kind: Path-problem (shows data flow paths)

The implementation leverages existing logging sink models in rust/ql/lib/codeql/rust/frameworks/log.model.yml which already define appropriate sinks for the log crate and standard I/O functions.

Fixes github/codeql-team#4178.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits August 13, 2025 18:09
Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Rust: Implement a new query for Log Injection Rust: Implement a new query for Log Injection Aug 13, 2025
@Copilot Copilot AI requested a review from geoffw0 August 13, 2025 18:14
Copilot finished work on behalf of geoffw0 August 13, 2025 18:14
@github-actions github-actions bot added documentation Rust Pull requests that update Rust code labels Aug 13, 2025
Copy link
Contributor

github-actions bot commented Aug 14, 2025

QHelp previews:

rust/ql/src/queries/security/CWE-117/LogInjection.qhelp

Log injection

If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries.

Forgery can occur if a user provides some input with characters that are interpreted when the log output is displayed. If the log is displayed as a plain text file, then new line characters can be used by a malicious user. If the log is displayed as HTML, then arbitrary HTML may be included to spoof log entries.

Recommendation

User input should be suitably sanitized before it is logged.

If the log entries are in plain text, then line breaks should be removed from user input using String::replace or similar. Care should also be taken that user input is clearly marked in log entries.

For log entries that will be displayed in HTML, user input should be HTML-encoded before being logged, to prevent forgery and other forms of HTML injection.

Example

In the first example, a username, provided by the user via command line arguments, is logged using the log crate. If a malicious user provides Guest\n[INFO] User: Admin\n as a username parameter, the log entry will be split into multiple lines, where the second line will appear as [INFO] User: Admin, potentially forging a legitimate admin login entry.

use std::env;
use log::info;

fn main() {
    env_logger::init();

    // Get username from command line arguments
    let args: Vec<String> = env::args().collect();
    let username = args.get(1).unwrap_or(&String::from("Guest")).clone();

    // BAD: log message constructed with unsanitized user input
    info!("User login attempt: {}", username);
}

In the second example, String::replace is used to ensure no line endings are present in the user input before logging.

use std::env;
use log::info;

fn sanitize_for_logging(input: &str) -> String {
    // Remove newlines and carriage returns to prevent log injection
    input.replace('\n', "").replace('\r', "")
}

fn main() {
    env_logger::init();

    // Get username from command line arguments
    let args: Vec<String> = env::args().collect();
    let username = args.get(1).unwrap_or(&String::from("Guest")).clone();

    // GOOD: log message constructed with sanitized user input
    let sanitized_username = sanitize_for_logging(username.as_str());
    info!("User login attempt: {}", sanitized_username);
}

References

Copy link
Contributor

@geoffw0 geoffw0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot This looks great - amazing work!

There are a few things to clean up (see my other comments). Then I will try the query out for myself and get others involved in reviewing.

Co-authored-by: geoffw0 <40627776+geoffw0@users.noreply.github.com>
@Copilot Copilot AI requested a review from geoffw0 August 14, 2025 13:16
Copilot finished work on behalf of geoffw0 August 14, 2025 13:16
@geoffw0
Copy link
Contributor

geoffw0 commented Aug 18, 2025

DCA run LGTM.

Ready for docs review. Note that this PR was generated by Copilot agent, under my supervision. I don't know if that changes anything, I am ultimately responsible for what gets merged.

Ready for code review. I've already reviewed Copilots work, but I did make a few changes myself and in any case I need approval from another person. Questions and suggestions are also welcome of course. The query doesn't have any barriers at the moment, so that's a priority for follow-up work, but as a @precision medium query I think we're OK merging this as it is. There are also some issues with missing data flow in the tests which we could definitely improve as follow-up.

@geoffw0 geoffw0 marked this pull request as ready for review August 18, 2025 08:26
@geoffw0 geoffw0 requested a review from a team as a code owner August 18, 2025 08:26
@Copilot Copilot AI review requested due to automatic review settings August 18, 2025 08:26
@geoffw0 geoffw0 added the ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. label Aug 18, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a comprehensive CodeQL query for detecting log injection vulnerabilities in Rust code. Log injection occurs when user-controlled data is included in log output without proper sanitization, allowing malicious users to forge log entries by inserting newlines or other control characters.

Key changes:

  • Implements core log injection detection infrastructure following existing patterns in the codebase
  • Adds comprehensive test coverage with both vulnerable and safe code patterns
  • Provides documentation and examples demonstrating the vulnerability and remediation

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
LogInjectionExtensions.qll Core detection logic with sources, sinks, and barriers for log injection vulnerabilities
LogInjection.ql Main taint tracking query that identifies data flow from user input to logging functions
LogInjection.qhelp Documentation explaining the vulnerability with Rust-specific examples and remediation
LogInjectionBad.rs / LogInjectionGood.rs Example code demonstrating vulnerable and secure logging patterns
main.rs Comprehensive test file with 20+ test cases covering various log injection scenarios
Stats.qll Integration with existing threat model infrastructure
Query suite files Integration with existing security query suites

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

* insertion of forged log entries by a malicious user.
* @kind path-problem
* @problem.severity error
* @security-severity 2.6
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The security severity should be 7.8 according to the PR description, not 2.6. This inconsistency could lead to incorrect risk assessment.

Suggested change
* @security-severity 2.6
* @security-severity 7.8

Copilot uses AI. Check for mistakes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generated it with the cwe-scores tool. I appreciate that the number differs from other versions of the query, I haven't looked into why but I'm guessing its because something the tool bases its score on has changed since they were created.

Copy link

@sophietheking sophietheking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny nit to move a comma. 🐜

geoffw0 and others added 2 commits August 18, 2025 10:29
Co-authored-by: Sophie <29382425+sophietheking@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants