use aethershell::safety::{
applescript_quote, ps_bare_number, ps_join, ps_quote, reject_option_like,
reject_sqlite_dot_command,
};
#[test]
fn ps_quote_defeats_subexpression_payloads_that_quote_escaping_missed() {
let payload = "$(New-Item -ItemType File -Path C:\\tmp\\pwned -Force)";
let quoted = ps_quote(payload).to_string();
assert_eq!(quoted, format!("'{payload}'"));
assert!(
!quoted.starts_with('"'),
"a double-quoted literal would re-enable $() expansion"
);
let with_quotes = "$(Get-Content 'C:\\secret')";
assert_eq!(
ps_quote(with_quotes).to_string(),
"'$(Get-Content ''C:\\secret'')'",
"apostrophes must be doubled while `$` stays inert"
);
}
#[test]
fn applescript_quote_escapes_backslash_before_quote() {
assert_eq!(applescript_quote("plain").to_string(), "\"plain\"");
assert_eq!(applescript_quote(r#"a\"#).to_string(), r#""a\\""#);
let attack = r#"" & (do shell script "touch /tmp/pwned") & ""#;
let quoted = applescript_quote(attack).to_string();
assert!(quoted.starts_with('"') && quoted.ends_with('"'));
let interior = "ed[1..quoted.len() - 1];
let mut chars = interior.chars().peekable();
while let Some(c) = chars.next() {
if c == '\\' {
chars.next();
} else {
assert_ne!(c, '"', "an unescaped quote closes the AppleScript literal");
}
}
}
#[test]
fn ps_quote_neutralizes_the_quote_that_ends_the_string() {
assert_eq!(ps_quote("plain").to_string(), "'plain'");
let attack = "x'; New-Item -ItemType File -Path 'C:\\tmp\\pwned' -Force; '";
let quoted = ps_quote(attack).to_string();
assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
let interior = "ed[1..quoted.len() - 1];
for run in interior.split(|c| c != '\'').filter(|r| !r.is_empty()) {
assert!(
run.len() % 2 == 0,
"an odd run of quotes escapes the literal: {run:?}"
);
}
}
#[test]
fn ps_quote_leaves_everything_else_alone() {
for s in [
r"C:\Program Files\thing.txt",
"$env:PATH",
"back`tick",
"semi;colon",
"a b c",
] {
assert_eq!(
ps_quote(s).to_string(),
format!("'{s}'"),
"only the quote character needs escaping in a single-quoted literal"
);
}
}
#[test]
fn sqlite_dot_commands_are_refused_where_sql_is_expected() {
for payload in [
".system cmd /c calc",
".shell /bin/sh",
" .system id",
"\t.shell id",
"\n.system id",
] {
assert!(
reject_sqlite_dot_command("db_sqlite_query", payload).is_err(),
"{payload:?} must be refused — .system and .shell run programs"
);
}
}
#[test]
fn ordinary_sql_still_passes() {
for sql in [
"SELECT * FROM t",
"SELECT t.a FROM t",
" INSERT INTO t VALUES (1)",
"UPDATE t SET x = 1.5",
"SELECT '.system' FROM t",
] {
assert!(
reject_sqlite_dot_command("db_sqlite_query", sql).is_ok(),
"{sql:?} is SQL and must be allowed"
);
}
}
#[test]
fn quoted_literals_are_a_distinct_type_that_only_the_escapers_produce() {
let rendered = format!("Start-Service {}", ps_quote("my service"));
assert_eq!(rendered, "Start-Service 'my service'");
let apple = format!("display dialog {}", applescript_quote("hi"));
assert_eq!(apple, "display dialog \"hi\"");
}
#[test]
fn bare_numeric_interpolations_are_validated_not_quoted() {
for good in ["4GB", "512MB", "1.5TB", "8080", "0", "20gb"] {
let v = ps_bare_number("vm_create", good)
.unwrap_or_else(|e| panic!("{good:?} should be accepted: {e}"));
assert_eq!(v.to_string(), good.trim(), "the value must pass through");
}
for bad in [
"4GB; calc",
"8080 && id",
"$(id)",
"1GB'",
"",
"GB",
"1.2.3",
"4 GB; rm -rf /",
] {
assert!(
ps_bare_number("vm_create", bad).is_err(),
"{bad:?} reaches a command unquoted and must be refused"
);
}
}
#[test]
fn ps_join_preserves_escaping_across_a_list() {
let joined = ps_join(
["a b".to_string(), "c'd".to_string()]
.iter()
.map(|s| ps_quote(s)),
",",
);
assert_eq!(joined.to_string(), "'a b','c''d'");
}
#[test]
fn option_like_paths_are_refused() {
for payload in [
"--use-compress-program=sh -c 'id'",
"--to-command=sh -c 'id'",
"-TTsh -c 'id'",
"-I/bin/sh",
"--exclude=x",
] {
let r = reject_option_like("tar_create", &[payload.to_string()]);
assert!(
r.is_err(),
"{payload:?} must be refused — several archivers execute it"
);
}
}
#[test]
fn ordinary_paths_are_accepted() {
let ok: Vec<String> = [
"file.txt",
"./file.txt",
"dir/file.txt",
r"C:\Users\x\file.txt",
"/abs/path",
"./-weird",
]
.iter()
.map(|s| s.to_string())
.collect();
assert!(
reject_option_like("tar_create", &ok).is_ok(),
"normal paths must pass, including the './-name' workaround"
);
}
#[test]
fn a_url_scheme_outside_the_web_set_is_refused() {
for url in [
"ms-msdt:/id PCWDiagnostic",
"search-ms:query=x",
"javascript:alert(1)",
"vbscript:x",
"data:text/html,payload",
] {
assert!(
aethershell::safety::reject_unsafe_url("web_open_url", url).is_err(),
"{url} dispatches to a registered handler that is not a browser"
);
}
}
#[test]
fn a_url_carrying_a_control_character_is_refused() {
for url in [
"http://example.com\nrm -rf /",
"http://x\r\ny",
"http://x\u{0}y",
] {
assert!(
aethershell::safety::reject_unsafe_url("web_open_url", url).is_err(),
"a newline separates commands in every shell and cannot appear in a URL"
);
}
}
#[test]
fn an_option_like_url_is_refused() {
for url in ["-a/Applications/Calculator.app", "--version", "-"] {
assert!(
aethershell::safety::reject_unsafe_url("web_open_url", url).is_err(),
"{url} is parsed as an option by open/xdg-open"
);
}
}
#[test]
fn ordinary_urls_still_open() {
for url in [
"https://example.com",
"http://example.com/path?a=1&b=2",
"https://example.com/?q=a%20b&r=1",
"HTTPS://EXAMPLE.COM",
"mailto:someone@example.com?subject=hi&body=x",
"file:///C:/Users/x/report.html",
"ftp://ftp.example.com/pub/",
] {
assert!(
aethershell::safety::reject_unsafe_url("web_open_url", url).is_ok(),
"{url} is an ordinary URL and must still open"
);
}
}
#[test]
fn a_bare_path_is_refused_rather_than_dispatched() {
for url in ["report.html", r"C:\Users\x\payload.hta", "/etc/passwd", ""] {
assert!(
aethershell::safety::reject_unsafe_url("web_open_url", url).is_err(),
"{url:?} has no scheme"
);
}
}