fix(preflight): redact local host preflight collector output (#2101)

CollectHostWithContext was the only collection path (in-cluster support
bundle, remote/SSH host collectors) that never ran collected data through
the redaction engine. A `run` collector's captured environment in
particular can carry credentials verbatim -- e.g. HTTPS_PROXY with
embedded Basic Auth -- straight into the bundle's <collectorName>-info.json
with no redaction applied.

Wire it through collect.RedactResult the same way CollectRemoteWithContext
and pkg/supportbundle/collect.go already do, so the built-in default
redactors apply to local host preflight output too.

Fixes #2100
This commit is contained in:
Benjamin Reed
2026-08-10 12:09:22 +12:00
committed by GitHub
parent 95a4a81bce
commit 3c5bf74750
2 changed files with 55 additions and 0 deletions
+9
View File
@@ -145,6 +145,15 @@ func CollectHostWithContext(
span.End()
}
// Local host preflight collectors are the only collection path (cluster,
// remote host, in-cluster support bundle) that skipped redaction entirely.
// A `run` collector's captured environment in particular can carry
// credentials verbatim (e.g. HTTPS_PROXY with embedded Basic Auth) into
// the bundle. See https://github.com/replicatedhq/troubleshoot/issues/2100.
if err := collect.RedactResult(opts.BundlePath, collect.CollectorResult(allCollectedData), nil); err != nil {
return nil, errors.Wrap(err, "failed to redact host collector results")
}
// The values of map entries will contain the collected data in bytes if the data was not stored to disk
collectResult.AllCollectedData = allCollectedData
+46
View File
@@ -1,6 +1,9 @@
package preflight
import (
"context"
"os"
"path/filepath"
"reflect"
"testing"
@@ -209,3 +212,46 @@ func TestCollectWithContext_PreservesOrderAfterClusterResources(t *testing.T) {
assert.Less(t, dataIndex, secretIndex, "data collectors should come before secret collectors, preserving relative order")
}
}
// TestCollectHostWithContext_RedactsSensitiveEnvValues verifies that a `run`
// host collector's captured environment is redacted before being written to
// the bundle. CollectHostWithContext is the only collection path (cluster,
// host, remote) that skipped redaction entirely: every env var passed to the
// command -- including credentials embedded in a proxy URL -- landed
// verbatim in <collectorName>-info.json.
func TestCollectHostWithContext_RedactsSensitiveEnvValues(t *testing.T) {
bundlePath := t.TempDir()
hostPreflight := &troubleshootv1beta2.HostPreflight{
Spec: troubleshootv1beta2.HostPreflightSpec{
Collectors: []*troubleshootv1beta2.HostCollect{
{
HostRun: &troubleshootv1beta2.HostRun{
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
CollectorName: "proxy-credential-check",
},
Command: "sh",
Args: []string{"-c", "echo ok"},
IgnoreParentEnvs: true,
Env: []string{
"HTTPS_PROXY=http://alice:sw0rdfish@proxy.example.com:3128",
},
},
},
},
},
}
_, err := CollectHostWithContext(context.Background(), CollectOpts{
ProgressChan: make(chan interface{}, 100),
BundlePath: bundlePath,
}, hostPreflight)
require.NoError(t, err)
infoPath := filepath.Join(bundlePath, "host-collectors/run-host/proxy-credential-check-info.json")
b, err := os.ReadFile(infoPath)
require.NoError(t, err)
assert.NotContains(t, string(b), "sw0rdfish", "proxy credential leaked unredacted into the host preflight bundle")
assert.Contains(t, string(b), "***HIDDEN***", "expected the built-in URL-userinfo redactor to mask the credential")
}