Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions crates/bashkit/docs/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,12 @@ Control characters are filtered, and newlines are escaped.

### Unsafe Options

For debugging in **non-production** environments only:
For debugging in **non-production** environments only. These methods require the
`BASHKIT_UNSAFE_LOGGING=1` environment variable to take effect; without it they
are no-ops that emit a warning:

```rust
# use bashkit::LogConfig;
```rust,ignore
// First: export BASHKIT_UNSAFE_LOGGING=1 in your shell
// WARNING: May expose sensitive data
let config = LogConfig::new()
.unsafe_disable_redaction() // Disable ALL redaction
Expand Down
48 changes: 44 additions & 4 deletions crates/bashkit/src/logging_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,16 @@ impl LogConfig {
/// # Warning
///
/// This may expose secrets in logs. Only use in trusted debugging environments.
/// Requires `BASHKIT_UNSAFE_LOGGING=1` environment variable; otherwise this is a no-op.
pub fn unsafe_disable_redaction(mut self) -> Self {
self.redact_sensitive = false;
if std::env::var("BASHKIT_UNSAFE_LOGGING").as_deref() == Ok("1") {
eprintln!("WARNING: Log redaction disabled — secrets may appear in logs");
self.redact_sensitive = false;
} else {
eprintln!(
"WARNING: unsafe_disable_redaction() ignored — set BASHKIT_UNSAFE_LOGGING=1 to enable"
);
}
self
}

Expand All @@ -141,8 +149,16 @@ impl LogConfig {
/// # Warning
///
/// Scripts may contain embedded secrets, credentials, or sensitive data.
/// Requires `BASHKIT_UNSAFE_LOGGING=1` environment variable; otherwise this is a no-op.
pub fn unsafe_log_scripts(mut self) -> Self {
self.log_script_content = true;
if std::env::var("BASHKIT_UNSAFE_LOGGING").as_deref() == Ok("1") {
eprintln!("WARNING: Script content logging enabled — secrets may appear in logs");
self.log_script_content = true;
} else {
eprintln!(
"WARNING: unsafe_log_scripts() ignored — set BASHKIT_UNSAFE_LOGGING=1 to enable"
);
}
self
}

Expand Down Expand Up @@ -411,9 +427,11 @@ mod tests {
assert!(formatted.contains("2 lines"));
assert!(!formatted.contains("echo"));

// With unsafe flag: log content
let config = config.unsafe_log_scripts();
// With unsafe flag: log content (requires env var)
unsafe { std::env::set_var("BASHKIT_UNSAFE_LOGGING", "1") };
let config = LogConfig::new().unsafe_log_scripts();
let formatted = format_script_for_log(script, &config);
unsafe { std::env::remove_var("BASHKIT_UNSAFE_LOGGING") };
assert!(formatted.contains("echo"));
}

Expand All @@ -428,7 +446,9 @@ mod tests {

#[test]
fn test_disabled_redaction() {
unsafe { std::env::set_var("BASHKIT_UNSAFE_LOGGING", "1") };
let config = LogConfig::new().unsafe_disable_redaction();
unsafe { std::env::remove_var("BASHKIT_UNSAFE_LOGGING") };

// Should not redact when disabled
assert!(!config.should_redact_env("PASSWORD"));
Expand All @@ -437,4 +457,24 @@ mod tests {
"https://user:pass@example.com"
);
}

#[test]
fn test_unsafe_methods_noop_without_env() {
// Ensure env var is NOT set
unsafe { std::env::remove_var("BASHKIT_UNSAFE_LOGGING") };

// unsafe_disable_redaction should be a no-op
let config = LogConfig::new().unsafe_disable_redaction();
assert!(
config.redact_sensitive,
"redact_sensitive should remain true without BASHKIT_UNSAFE_LOGGING=1"
);

// unsafe_log_scripts should be a no-op
let config = LogConfig::new().unsafe_log_scripts();
assert!(
!config.log_script_content,
"log_script_content should remain false without BASHKIT_UNSAFE_LOGGING=1"
);
}
}
7 changes: 7 additions & 0 deletions crates/bashkit/tests/logging_security_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,11 @@ mod redaction_tests {
// Test for TM-LOG-002: Content shown only with explicit unsafe flag
use bashkit::logging::format_script_for_log;

// Requires BASHKIT_UNSAFE_LOGGING=1 for unsafe_log_scripts to take effect
unsafe { std::env::set_var("BASHKIT_UNSAFE_LOGGING", "1") };
let config = LogConfig::new().unsafe_log_scripts();
unsafe { std::env::remove_var("BASHKIT_UNSAFE_LOGGING") };

let script = "echo hello";

let formatted = format_script_for_log(script, &config);
Expand Down Expand Up @@ -628,7 +632,10 @@ mod disabled_redaction_tests {
#[test]
fn test_disabled_redaction_shows_secrets() {
// Test that unsafe_disable_redaction actually disables redaction
// Requires BASHKIT_UNSAFE_LOGGING=1 for the method to take effect
unsafe { std::env::set_var("BASHKIT_UNSAFE_LOGGING", "1") };
let config = LogConfig::new().unsafe_disable_redaction();
unsafe { std::env::remove_var("BASHKIT_UNSAFE_LOGGING") };

// Env var redaction disabled
assert!(
Expand Down
Loading