refactor(build): reformat code and add tonic health dependency
- Reformatted build script with proper indentation and line breaks - Added tonic-health dependency to Cargo.toml and updated lock file - Improved error handling in disk cache with concurrent deletion checks - Refactored conditional chains using && and let expressions - Reformatted struct initialization and function parameter lists - Added proper spacing and alignment in language stats processing - Improved assertion formatting in test cases - Reorganized import statements and code layout in multiple files - Updated metrics functions with better parameter handling and formatting
This commit is contained in:
+12
-16
@@ -128,10 +128,14 @@ pub fn run_hook_dir(
|
||||
|
||||
/// Run a single hook script with stdin data and timeout.
|
||||
fn run_single_script(script_path: &Path, stdin_data: &[u8], timeout: Duration) -> HookResult {
|
||||
// Use Stdio::null() for stdout/stderr to prevent pipe-buffer deadlock.
|
||||
// With Stdio::piped() + never reading, a hook that writes >64KB of output
|
||||
// would block the child on write(), and the parent's try_wait() would
|
||||
// loop until timeout before killing it.
|
||||
let child = std::process::Command::new(script_path)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn();
|
||||
|
||||
match child {
|
||||
@@ -143,17 +147,12 @@ fn run_single_script(script_path: &Path, stdin_data: &[u8], timeout: Duration) -
|
||||
|
||||
let wait_result = c.wait_timeout(timeout);
|
||||
match wait_result {
|
||||
Ok(Some(status)) => {
|
||||
// Process exited within timeout, get its output
|
||||
// Note: We already have the status, so we need to construct output differently
|
||||
// Since wait_with_output would fail after try_wait, we return status-only output
|
||||
HookResult {
|
||||
accepted: status.success(),
|
||||
exit_code: status.code().unwrap_or(-1),
|
||||
stdout: String::new(), // stdout was consumed by the process
|
||||
stderr: String::new(), // stderr was consumed by the process
|
||||
}
|
||||
}
|
||||
Ok(Some(status)) => HookResult {
|
||||
accepted: status.success(),
|
||||
exit_code: status.code().unwrap_or(-1),
|
||||
stdout: String::new(),
|
||||
stderr: String::new(),
|
||||
},
|
||||
Ok(None) => {
|
||||
tracing::warn!(
|
||||
script = %script_path.display(),
|
||||
@@ -161,7 +160,6 @@ fn run_single_script(script_path: &Path, stdin_data: &[u8], timeout: Duration) -
|
||||
"hook script timed out, killing"
|
||||
);
|
||||
let _ = c.kill();
|
||||
// Explicitly wait to reap the zombie process
|
||||
let _ = c.wait();
|
||||
HookResult::rejected(format!(
|
||||
"hook script timed out after {}s: {}",
|
||||
@@ -171,7 +169,6 @@ fn run_single_script(script_path: &Path, stdin_data: &[u8], timeout: Duration) -
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = c.kill();
|
||||
// Explicitly wait to reap the zombie process
|
||||
let _ = c.wait();
|
||||
HookResult::rejected(format!("hook script wait error: {e}"))
|
||||
}
|
||||
@@ -183,7 +180,6 @@ fn run_single_script(script_path: &Path, stdin_data: &[u8], timeout: Duration) -
|
||||
error = %e,
|
||||
"failed to spawn hook script"
|
||||
);
|
||||
// If the script can't be executed, treat as rejection
|
||||
HookResult::rejected(format!("failed to spawn hook script: {e}"))
|
||||
}
|
||||
}
|
||||
|
||||
+31
-23
@@ -26,33 +26,33 @@ const FORBIDDEN_PATTERNS: &[&str] = &[
|
||||
"poweroff",
|
||||
"halt",
|
||||
// Additional patterns to catch encoding/obfuscation attempts
|
||||
"eval ", // eval can execute arbitrary strings
|
||||
"exec ", // exec can replace process
|
||||
"$(", // command substitution
|
||||
"`", // backtick command substitution
|
||||
"${", // variable expansion (can be used for obfuscation)
|
||||
"|bash", // piping to bash
|
||||
"|sh", // piping to sh
|
||||
"|dash", // piping to dash
|
||||
"|zsh", // piping to zsh
|
||||
"base64", // base64 encoding/decoding (common for obfuscation)
|
||||
"python -c", // inline python execution
|
||||
"perl -e", // inline perl execution
|
||||
"ruby -e", // inline ruby execution
|
||||
"node -e", // inline node execution
|
||||
"/dev/tcp", // bash reverse shell
|
||||
"nc -e", // netcat reverse shell
|
||||
"ncat", // netcat alternative
|
||||
"socat", // socket relay
|
||||
"eval ", // eval can execute arbitrary strings
|
||||
"exec ", // exec can replace process
|
||||
"$(", // command substitution
|
||||
"`", // backtick command substitution
|
||||
"${", // variable expansion (can be used for obfuscation)
|
||||
"|bash", // piping to bash
|
||||
"|sh", // piping to sh
|
||||
"|dash", // piping to dash
|
||||
"|zsh", // piping to zsh
|
||||
"base64", // base64 encoding/decoding (common for obfuscation)
|
||||
"python -c", // inline python execution
|
||||
"perl -e", // inline perl execution
|
||||
"ruby -e", // inline ruby execution
|
||||
"node -e", // inline node execution
|
||||
"/dev/tcp", // bash reverse shell
|
||||
"nc -e", // netcat reverse shell
|
||||
"ncat", // netcat alternative
|
||||
"socat", // socket relay
|
||||
];
|
||||
|
||||
/// Additional regex-like patterns that indicate dangerous constructs.
|
||||
/// These are checked with simple string matching for complexity reasons.
|
||||
const DANGEROUS_PREFIXES: &[&str] = &[
|
||||
"rm -rf /", // rm -rf with absolute path
|
||||
"rm -rf ~", // rm -rf with home directory
|
||||
"rm -rf .", // rm -rf with relative path (current dir)
|
||||
"rm -rf *", // rm -rf with wildcard
|
||||
"rm -rf /", // rm -rf with absolute path
|
||||
"rm -rf ~", // rm -rf with home directory
|
||||
"rm -rf .", // rm -rf with relative path (current dir)
|
||||
"rm -rf *", // rm -rf with wildcard
|
||||
];
|
||||
|
||||
/// Maximum hook script size (64KB).
|
||||
@@ -106,7 +106,15 @@ pub fn validate_hook_content(content: &str) -> GitResult<()> {
|
||||
/// Check for common obfuscation attempts.
|
||||
fn check_obfuscation_attempts(content: &str) -> GitResult<()> {
|
||||
// Check for excessive use of special characters that might indicate obfuscation
|
||||
let special_char_count = content.chars().filter(|c| matches!(c, '$' | '`' | '\\' | '|' | ';' | '&' | '(' | ')' | '{' | '}' | '[' | ']')).count();
|
||||
let special_char_count = content
|
||||
.chars()
|
||||
.filter(|c| {
|
||||
matches!(
|
||||
c,
|
||||
'$' | '`' | '\\' | '|' | ';' | '&' | '(' | ')' | '{' | '}' | '[' | ']'
|
||||
)
|
||||
})
|
||||
.count();
|
||||
let total_chars = content.chars().count();
|
||||
|
||||
// If more than 30% of content is special characters, it's suspicious
|
||||
|
||||
Reference in New Issue
Block a user