Skip to content

Commit 3c5bf74

Browse files
authored
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
1 parent 95a4a81 commit 3c5bf74

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

pkg/preflight/collect.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ func CollectHostWithContext(
145145
span.End()
146146
}
147147

148+
// Local host preflight collectors are the only collection path (cluster,
149+
// remote host, in-cluster support bundle) that skipped redaction entirely.
150+
// A `run` collector's captured environment in particular can carry
151+
// credentials verbatim (e.g. HTTPS_PROXY with embedded Basic Auth) into
152+
// the bundle. See https://github.com/replicatedhq/troubleshoot/issues/2100.
153+
if err := collect.RedactResult(opts.BundlePath, collect.CollectorResult(allCollectedData), nil); err != nil {
154+
return nil, errors.Wrap(err, "failed to redact host collector results")
155+
}
156+
148157
// The values of map entries will contain the collected data in bytes if the data was not stored to disk
149158
collectResult.AllCollectedData = allCollectedData
150159

pkg/preflight/collect_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package preflight
22

33
import (
4+
"context"
5+
"os"
6+
"path/filepath"
47
"reflect"
58
"testing"
69

@@ -209,3 +212,46 @@ func TestCollectWithContext_PreservesOrderAfterClusterResources(t *testing.T) {
209212
assert.Less(t, dataIndex, secretIndex, "data collectors should come before secret collectors, preserving relative order")
210213
}
211214
}
215+
216+
// TestCollectHostWithContext_RedactsSensitiveEnvValues verifies that a `run`
217+
// host collector's captured environment is redacted before being written to
218+
// the bundle. CollectHostWithContext is the only collection path (cluster,
219+
// host, remote) that skipped redaction entirely: every env var passed to the
220+
// command -- including credentials embedded in a proxy URL -- landed
221+
// verbatim in <collectorName>-info.json.
222+
func TestCollectHostWithContext_RedactsSensitiveEnvValues(t *testing.T) {
223+
bundlePath := t.TempDir()
224+
225+
hostPreflight := &troubleshootv1beta2.HostPreflight{
226+
Spec: troubleshootv1beta2.HostPreflightSpec{
227+
Collectors: []*troubleshootv1beta2.HostCollect{
228+
{
229+
HostRun: &troubleshootv1beta2.HostRun{
230+
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
231+
CollectorName: "proxy-credential-check",
232+
},
233+
Command: "sh",
234+
Args: []string{"-c", "echo ok"},
235+
IgnoreParentEnvs: true,
236+
Env: []string{
237+
"HTTPS_PROXY=http://alice:sw0rdfish@proxy.example.com:3128",
238+
},
239+
},
240+
},
241+
},
242+
},
243+
}
244+
245+
_, err := CollectHostWithContext(context.Background(), CollectOpts{
246+
ProgressChan: make(chan interface{}, 100),
247+
BundlePath: bundlePath,
248+
}, hostPreflight)
249+
require.NoError(t, err)
250+
251+
infoPath := filepath.Join(bundlePath, "host-collectors/run-host/proxy-credential-check-info.json")
252+
b, err := os.ReadFile(infoPath)
253+
require.NoError(t, err)
254+
255+
assert.NotContains(t, string(b), "sw0rdfish", "proxy credential leaked unredacted into the host preflight bundle")
256+
assert.Contains(t, string(b), "***HIDDEN***", "expected the built-in URL-userinfo redactor to mask the credential")
257+
}

0 commit comments

Comments
 (0)