CVE-2021-36753: Uncontrolled Search Path Element (CWE-427)
value: sharkdp BAT before 0.18.2 executes less.exe from the current working directory.
CWE description: The product uses a fixed or controlled search path to find resources, but one or more locations in that path can be under the control of unintended actors.
CVSS v3 base score: 7.8
Published: 2021-07-15T20:15Z
Repository: https://github.com/sharkdp/bat
Language: Rust
Files changed: Cargo.lock, Cargo.toml, src/less.rs, src/output.rs
Commit date: 2021-07-12 23:17:30 +0200
Commit message: Fix for Windows: do not run binaries from CWD

This fixes a bug on Windows where `Command::new` would also run
executables from the current working directory, possibly resulting in
accidental runs of programs called `less`.

Diff: diff --git a/Cargo.lock b/Cargo.lock
index a6d2d33..6170e94 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,7 +1,9 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "adler"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
@@ -95,10 +97,11 @@ dependencies = [
  "dirs-next",
  "encoding",
  "error-chain",
  "git2",
  "globset",
+ "grep-cli",
  "lazy_static",
  "nix",
  "path_abs",
  "predicates",
  "semver",
@@ -485,10 +488,27 @@ dependencies = [
  "fnv",
  "log",
  "regex",
 ]
 
+[[package]]
+name = "grep-cli"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dd110c34bb4460d0de5062413b773e385cbf8a85a63fc535590110a09e79e8a"
+dependencies = [
+ "atty",
+ "bstr",
+ "globset",
+ "lazy_static",
+ "log",
+ "regex",
+ "same-file",
+ "termcolor",
+ "winapi-util",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
@@ -1141,10 +1161,19 @@ checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
 dependencies = [
  "libc",
  "winapi",
 ]
 
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "terminal_size"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406"
diff --git a/Cargo.toml b/Cargo.toml
index 42a9f50..e9b99b6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -49,10 +49,11 @@ serde_yaml = "0.8"
 semver = "0.11"
 path_abs = { version = "0.5", default-features = false }
 clircle = "0.3"
 bugreport = "0.4"
 dirs-next = { version = "2.0.0", optional = true }
+grep-cli = "0.1.6"
 
 [dependencies.git2]
 version = "0.13"
 optional = true
 default-features = false
diff --git a/src/less.rs b/src/less.rs
index f1adca8..2575fe1 100644
--- a/src/less.rs
+++ b/src/less.rs
@@ -2,11 +2,13 @@
 
 use std::ffi::OsStr;
 use std::process::Command;
 
 pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<usize> {
-    let cmd = Command::new(less_path).arg("--version").output().ok()?;
+    let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;
+
+    let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
     parse_less_version(&cmd.stdout)
 }
 
 fn parse_less_version(output: &[u8]) -> Option<usize> {
     if output.starts_with(b"less ") {
diff --git a/src/output.rs b/src/output.rs
index 4aff768..8bc2da0 100644
--- a/src/output.rs
+++ b/src/output.rs
@@ -61,11 +61,18 @@ impl OutputType {
 
         if pager.kind == PagerKind::Bat {
             return Err(ErrorKind::InvalidPagerValueBat.into());
         }
 
-        let mut p = Command::new(&pager.bin);
+        let resolved_path = match grep_cli::resolve_binary(&pager.bin) {
+            Ok(path) => path,
+            Err(_) => {
+                return Ok(OutputType::stdout());
+            }
+        };
+
+        let mut p = Command::new(resolved_path);
         let args = pager.args;
 
         if pager.kind == PagerKind::Less {
             // less needs to be called with the '-R' option in order to properly interpret the
             // ANSI color sequences printed by bat. If someone has set PAGER="less -F", we

Vulnerable code:     let cmd = Command::new(less_path).arg("--version").output().ok()?;
        let mut p = Command::new(&pager.bin);
Fixed code: version = 3

 "grep-cli",
[[package]]
name = "grep-cli"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dd110c34bb4460d0de5062413b773e385cbf8a85a63fc535590110a09e79e8a"
dependencies = [
 "atty",
 "bstr",
 "globset",
 "lazy_static",
 "log",
 "regex",
 "same-file",
 "termcolor",
 "winapi-util",
]

[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
 "winapi-util",
]

grep-cli = "0.1.6"
    let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;

    let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
        let resolved_path = match grep_cli::resolve_binary(&pager.bin) {
            Ok(path) => path,
            Err(_) => {
                return Ok(OutputType::stdout());
            }
        };

        let mut p = Command::new(resolved_path);