Skip to content

sec(ssh): Debug derive on SshConfig/SshTarget/BotAuthConfig leaks credentials in logs #1189

@chaliy

Description

@chaliy

Summary

`SshConfig`, `SshTarget`, and `BotAuthConfig` all derive `Debug`, which means formatting them with `{:?}` dumps plaintext passwords, private key material, and Ed25519 signing keys. The `SshClient` Debug implementation also includes the full `SshConfig`. Any code path that logs, traces, or includes these structs in error messages will leak credentials.

Threat category: TM-INF (Information Disclosure) — extends TM-INF-016
Severity: Medium
Component:

  • `crates/bashkit/src/ssh/config.rs` line 50: `SshConfig` contains `default_password` and `default_private_key`
  • `crates/bashkit/src/ssh/handler.rs` line 17: `SshTarget` contains `private_key` and `password`
  • `crates/bashkit/src/network/bot_auth.rs` line 31: `BotAuthConfig` contains `signing_key: SigningKey`
  • `crates/bashkit/src/ssh/client.rs` line 26: `SshClient` Debug includes full `SshConfig`

Root Cause

```rust
#[derive(Debug, Clone)]
pub struct SshConfig {
pub default_password: Option, // Leaked by Debug
pub default_private_key: Option, // Leaked by Debug
// ...
}

#[derive(Debug, Clone)]
pub struct SshTarget {
pub password: Option, // Leaked by Debug
pub private_key: Option, // Leaked by Debug
// ...
}

#[derive(Debug, Clone)]
pub struct BotAuthConfig {
pub signing_key: SigningKey, // Ed25519 key leaked by Debug
// ...
}
```

Impact

  • Password disclosure: SSH passwords appear in any debug log or error message
  • Private key leakage: SSH private keys and Ed25519 signing keys exposed
  • AI agent context: If these structs are formatted in tool output, credentials flow into LLM context
  • Panic backtraces: Panics in code using these types include credential values in the backtrace

Acceptance Criteria

  • Implement custom `Debug` for `SshConfig`, `SshTarget`, `BotAuthConfig` that redacts sensitive fields
  • Example: `password: Some("[REDACTED]")` instead of the actual value
  • Remove `Debug` derive and replace with manual impl for all credential-holding structs
  • Audit all `Debug` derives across codebase for other credential-holding types
  • Add test: `format!("{:?}", ssh_config)` does not contain the actual password/key

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions