From 7d2eeb0a6fae715d56cd025259d6371607809d62 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Fri, 28 Aug 2026 15:29:08 +1200 Subject: [PATCH 1/2] fix(cli): hide database URL from help --- CHANGELOG.md | 4 ++++ awa-cli/src/main.rs | 2 +- awa-cli/tests/help_cli_test.rs | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 awa-cli/tests/help_cli_test.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 61eb4b8b..1097fd31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Notable changes between releases. Detailed migration notes for storage transitio ## [Unreleased] +### Fixed + +- **`awa --help` no longer prints the resolved `DATABASE_URL`.** The CLI still accepts `DATABASE_URL` as its database target, and help still identifies the environment variable, but credentials and other connection details from its current value are hidden. + ## [0.6.6] — 2026-08-14 Patch release: storage-transition convergence and recovery fixes. No migrations, schema changes, or public API changes. diff --git a/awa-cli/src/main.rs b/awa-cli/src/main.rs index f317d906..28608e7b 100644 --- a/awa-cli/src/main.rs +++ b/awa-cli/src/main.rs @@ -14,7 +14,7 @@ mod storage_wait; )] struct Cli { /// Database URL (not required for migrate --sql without --pending) - #[arg(long, env = "DATABASE_URL")] + #[arg(long, env = "DATABASE_URL", hide_env_values = true)] database_url: Option, #[command(subcommand)] diff --git a/awa-cli/tests/help_cli_test.rs b/awa-cli/tests/help_cli_test.rs new file mode 100644 index 00000000..dcee1d9a --- /dev/null +++ b/awa-cli/tests/help_cli_test.rs @@ -0,0 +1,22 @@ +use assert_cmd::Command; + +#[test] +fn help_does_not_disclose_environment_database_url() { + let secret_url = "postgres://secret-user:secret-password@db.example/awa"; + let output = Command::cargo_bin("awa") + .expect("awa binary") + .env("DATABASE_URL", secret_url) + .arg("--help") + .output() + .expect("run awa --help"); + + assert!(output.status.success()); + let rendered = format!( + "{}{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + assert!(rendered.contains("DATABASE_URL")); + assert!(!rendered.contains(secret_url)); + assert!(!rendered.contains("secret-password")); +} From 689b9f011243ae91e310312f76b6d4cd54fcda32 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Sun, 30 Aug 2026 13:23:24 +1200 Subject: [PATCH 2/2] fix(cli): hide callback secrets from help --- CHANGELOG.md | 2 +- awa-cli/src/main.rs | 4 ++-- awa-cli/tests/help_cli_test.rs | 40 +++++++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1097fd31..eaac4693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Notable changes between releases. Detailed migration notes for storage transitio ### Fixed -- **`awa --help` no longer prints the resolved `DATABASE_URL`.** The CLI still accepts `DATABASE_URL` as its database target, and help still identifies the environment variable, but credentials and other connection details from its current value are hidden. +- **CLI help no longer prints credential-bearing environment values.** `awa --help` hides the resolved `DATABASE_URL`, while `awa serve --help` and `awa callbacks serve --help` hide `AWA_CALLBACK_HMAC_SECRET`. The CLI still accepts those environment variables and help still identifies their names, but their current values are never rendered. ## [0.6.6] — 2026-08-14 diff --git a/awa-cli/src/main.rs b/awa-cli/src/main.rs index 28608e7b..97f00edd 100644 --- a/awa-cli/src/main.rs +++ b/awa-cli/src/main.rs @@ -101,7 +101,7 @@ enum Commands { #[arg(long, default_value = "5", env = "AWA_CACHE_TTL")] cache_ttl: u64, /// Hex-encoded 32-byte key used to verify callback signatures. - #[arg(long, env = "AWA_CALLBACK_HMAC_SECRET")] + #[arg(long, env = "AWA_CALLBACK_HMAC_SECRET", hide_env_values = true)] callback_hmac_secret: Option, /// Force the server into read-only mode regardless of DB privilege. /// @@ -151,7 +151,7 @@ enum CallbackCommands { pool_acquire_timeout: u64, /// Hex-encoded 32-byte key used to verify callback signatures. /// Required unless `--allow-unsigned` is set. - #[arg(long, env = "AWA_CALLBACK_HMAC_SECRET")] + #[arg(long, env = "AWA_CALLBACK_HMAC_SECRET", hide_env_values = true)] callback_hmac_secret: Option, /// Path prefix the callback routes are mounted under. Defaults to /// `/api/callbacks`, matching the built-in `awa serve` layout. diff --git a/awa-cli/tests/help_cli_test.rs b/awa-cli/tests/help_cli_test.rs index dcee1d9a..1b15397e 100644 --- a/awa-cli/tests/help_cli_test.rs +++ b/awa-cli/tests/help_cli_test.rs @@ -1,22 +1,46 @@ use assert_cmd::Command; -#[test] -fn help_does_not_disclose_environment_database_url() { - let secret_url = "postgres://secret-user:secret-password@db.example/awa"; +fn rendered_help(args: &[&str], env_name: &str, secret: &str) -> String { let output = Command::cargo_bin("awa") .expect("awa binary") - .env("DATABASE_URL", secret_url) - .arg("--help") + .env(env_name, secret) + .args(args) .output() - .expect("run awa --help"); + .expect("run awa help command"); assert!(output.status.success()); - let rendered = format!( + format!( "{}{}", String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) - ); + ) +} + +#[test] +fn help_does_not_disclose_environment_database_url() { + let secret_url = "postgres://secret-user:secret-password@db.example/awa"; + let rendered = rendered_help(&["--help"], "DATABASE_URL", secret_url); assert!(rendered.contains("DATABASE_URL")); assert!(!rendered.contains(secret_url)); assert!(!rendered.contains("secret-password")); } + +#[test] +fn serve_help_does_not_disclose_callback_secret() { + let secret = "serve-callback-secret-sentinel"; + let rendered = rendered_help(&["serve", "--help"], "AWA_CALLBACK_HMAC_SECRET", secret); + assert!(rendered.contains("AWA_CALLBACK_HMAC_SECRET")); + assert!(!rendered.contains(secret)); +} + +#[test] +fn callback_receiver_help_does_not_disclose_callback_secret() { + let secret = "receiver-callback-secret-sentinel"; + let rendered = rendered_help( + &["callbacks", "serve", "--help"], + "AWA_CALLBACK_HMAC_SECRET", + secret, + ); + assert!(rendered.contains("AWA_CALLBACK_HMAC_SECRET")); + assert!(!rendered.contains(secret)); +}