#![allow(deprecated)]
#![allow(non_snake_case)] #![allow(clippy::unwrap_used)] #![allow(clippy::expect_used)]
use assert_cmd::Command;
use std::io::Write;
use tempfile::NamedTempFile;
fn bashrs_cmd() -> Command {
assert_cmd::cargo_bin_cmd!("bashrs")
}
const LITERAL: &str = r#"#!/bin/bash
set -euo pipefail
OUT_DIR="build/results"
mkdir -p "$OUT_DIR"
cat > "$OUT_DIR/report.md" <<'INNER'
hello
INNER
"#;
const TAINTED: &str = r#"#!/bin/bash
OUT_DIR="build/$1"
mkdir -p "$OUT_DIR"
cat > "$OUT_DIR/report.md" <<'INNER'
hello
INNER
"#;
const HARDENED: &str = r#"#!/bin/bash
case "$1" in ""|*..*|/*) echo "bad name" >&2; exit 2 ;; esac
OUT_DIR="build/$1"
mkdir -p "$OUT_DIR"
cat > "$OUT_DIR/report.md" <<'INNER'
hello
INNER
"#;
const NOOP_VALIDATOR: &str = r#"#!/bin/bash
validate_path() {
:
}
OUT_DIR="build/$1"
validate_path "$OUT_DIR"
mkdir -p "$OUT_DIR"
cat > "$OUT_DIR/report.md" <<'INNER'
hello
INNER
"#;
fn path_findings(script: &str) -> (usize, usize) {
let mut file = NamedTempFile::with_suffix(".sh").unwrap();
file.write_all(script.as_bytes()).unwrap();
file.flush().unwrap();
let output = bashrs_cmd()
.arg("lint")
.arg("--no-ignore")
.arg("--format")
.arg("json")
.arg(file.path())
.output()
.unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
(
stdout.matches("\"SEC010\"").count(),
stdout.matches("\"SEC014\"").count(),
)
}
#[test]
fn test_GH227_cli_literal_paths_produce_no_traversal_findings() {
assert_eq!(path_findings(LITERAL), (0, 0));
}
#[test]
fn test_GH227_cli_positional_taint_is_still_reported() {
assert_eq!(path_findings(TAINTED), (2, 1));
}
#[test]
fn test_GH227_cli_dominating_guard_clears_findings() {
assert_eq!(path_findings(HARDENED), (0, 0));
}
#[test]
fn test_GH227_cli_noop_validator_does_not_clear_findings() {
assert_eq!(path_findings(NOOP_VALIDATOR), (2, 1));
}
#[test]
fn test_GH227_cli_literal_script_exits_zero() {
let mut file = NamedTempFile::with_suffix(".sh").unwrap();
file.write_all(LITERAL.as_bytes()).unwrap();
file.flush().unwrap();
bashrs_cmd()
.arg("lint")
.arg("--no-ignore")
.arg(file.path())
.assert()
.success();
}
#[test]
fn test_GH227_cli_positional_taint_exits_two() {
let mut file = NamedTempFile::with_suffix(".sh").unwrap();
file.write_all(TAINTED.as_bytes()).unwrap();
file.flush().unwrap();
bashrs_cmd()
.arg("lint")
.arg("--no-ignore")
.arg(file.path())
.assert()
.code(2);
}