Repository navigation
fix(ssh): harden logging and execution cleanup - #299
Merged
Merged
Conversation
- Remove credential dumps and redact forwarded environment values - Wait for started hosts and report each host failure once - Disable closed stream channels to prevent busy loops - Add regression tests and document execution behavior
- Keep godump output for non-sensitive connection settings - Mask configured SSH and proxy credentials in a display-only copy - Verify original credentials and unset fields remain unchanged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Debug mode previously dumped SSH/proxy credentials and forwarded environment values. A host failure could also leave workers blocked sending errors after
Execreturned, and closed output channels could keep the stream reader spinning.godumpand render a display-only configuration copy: redact non-empty SSH/proxy keys, passwords, and passphrases while preserving other settings and distinguishing unset credentials. Log forwarded environment values as[REDACTED]while preserving the actual remote values.testing/synctestregressions and document the changed failure and logging behavior.Related issues
GitHub/Jira: N/A; no issue was supplied.
Architecture / flow
flowchart TD A["main.go: run — dump redacted Config copy"] --> B["plugin.go: Exec / execHosts"] B --> C{"Sync?"} C -->|Yes| D["Run hosts in order; stop on failure"] C -->|No| E["Start workers; buffer at most one error per host"] D --> F["exec: redact debug environment values; start SSH"] E --> F F --> G["readStream: disable closed channels; return one result"] G --> H["execHosts: finish started workers; return first error or success"] style A fill:#dbeafe style B fill:#dbeafe style D fill:#dbeafe style E fill:#dbeafe style F fill:#dbeafe style G fill:#dbeafe style H fill:#dbeafeAI authorship
main.go,plugin.go,plugin_regression_test.go,plugin_test.go,DOCS.md.Change classification
Plan reference
Scope: fix credential disclosure in debug metadata, blocked error reporting, and closed-channel busy loops. IPv6 parsing, concurrency limits, and general output synchronization are outside this change.
Verification
Setup
Check out
fix/ssh-execution-safetyand run commands from the repository root. Local checks require Go 1.26.8. The complete suite additionally needs Docker, IPv6, and an Alpine SSH fixture; it must not runmake ssh-serveron the host OS.The following reproduces the isolated environment used for the full test run. It copies the checkout rather than relying on host directory mounts. Docker must expose its Unix socket to the container and support
host-gateway.Readiness is a successful
ssh-keyscan localhost; the test completion signals arePASS, packageok, and container exit code0. Inspect verbose output for skips as well as failures. The testcontainers cases create disposable SSH containers through the Docker socket. Cleanup removes the test runner; testcontainers removes its SSH fixtures. The completed verification run cleaned up its runner.Automated checks
All checks below ran against the files included in this PR.
go test -race -v -count=1 -timeout 10m ./...in the Alpine fixtureokin 15.606s; all cases passed, no skips or race reportsmake lintat repository rootmake fmt-checkat repository rootgo vet ./...at repository rootgo build -o /tmp/drone-ssh-pr-4641 .at repository rootgit diff --staged --checkbefore commitBehavioral scenarios
The focused tests below require no SSH service or Docker. From the checked-out repository root, run each command with
go test -race -v -count=1 -timeout 60s -run '<pattern>' ./..., substituting the pattern from the table. Each row is Passed as part of the full run above; expected assertions and observed outcomes are recorded separately.^(TestRunDebugRedactsCredentials|TestConfigRedactedPreservesOriginal|TestDebugRedactsEnvironment)$^TestExecHosts^TestReadStream^TestExecMultipleConnectionFailures$For the actual remote environment-value preservation scenario, the complete Docker run executes
TestEnvOutputandTestAllEnvs: original values (including quotes and whitespace) must reach the remote script while debug metadata is redacted. Passed; both assertions passed. The focused tests clean up their own temporary files and environment variables.Security check
Risk and rollback
errors.Is/errors.Asbehavior.Reviewer guide
Request two or more reviewers, including the module owner. Read
main.go:runandplugin.go:exec,readStream, andexecHostsline by line, especially timeout/error ordering and worker completion. ReviewConfig.redactedand its regression assertions to confirm debug rendering preserves the actual connection configuration; check the documented compatibility changes. No human line-by-line review has been recorded yet.