Skip to content

Conversation

@ArangoGutierrez
Copy link
Collaborator

Summary

  • Split single-use SSH session into two (mkdir + file write) in createKindConfig
  • Close local file that was previously leaked via missing defer

Audit Findings

Changes

  • pkg/provisioner/provisioner.go: Rewrite createKindConfig with two SSH sessions and proper resource cleanup

Test plan

  • gofmt — no formatting issues
  • go build — compiles
  • go test ./pkg/... — all tests pass

Copilot AI review requested due to automatic review settings February 12, 2026 20:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes critical SSH session management bugs in the createKindConfig function by addressing two audit findings: SSH session reuse after Run() (HIGH severity) and a local file resource leak (MEDIUM severity). The fix splits a single SSH session into two separate sessions and adds proper cleanup with defer statements.

Changes:

  • Split SSH session usage: mkdir operation now uses dedicated session1, file write uses dedicated session2
  • Added defer statement to close local file handle, fixing resource leak
  • Refactored to use local kindConfigPath variable instead of mutating the environment struct

Comment on lines 297 to 319
if err := session2.Start("cat > " + remoteFilePath); err != nil {
return fmt.Errorf("failed to start session: %w", err)
}

// open local file for reading
// first check if file path is relative or absolute
// if relative, then prepend the current working directory
if !filepath.IsAbs(env.Spec.Kubernetes.KindConfig) {
// Resolve local file path
kindConfigPath := env.Spec.Kubernetes.KindConfig
if !filepath.IsAbs(kindConfigPath) {
cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("failed to get current working directory: %w", err)
}

env.Spec.Kubernetes.KindConfig = filepath.Join(cwd, strings.TrimPrefix(env.Spec.Kubernetes.KindConfig, "./"))
kindConfigPath = filepath.Join(cwd, strings.TrimPrefix(kindConfigPath, "./"))
}

localFile, err := os.Open(env.Spec.Kubernetes.KindConfig)
localFile, err := os.Open(kindConfigPath)
if err != nil {
return fmt.Errorf("failed to open local file %s: %w", env.Spec.Kubernetes.KindConfig, err)
return fmt.Errorf("failed to open local file %s: %w", kindConfigPath, err)
}
defer func() { _ = localFile.Close() }()

// copy local file to remote file
if _, err := io.Copy(remoteFile, localFile); err != nil {
return fmt.Errorf("failed to copy local file %s to remote file %s: %w", env.Spec.Kubernetes.KindConfig, remoteFilePath, err)
return fmt.Errorf("failed to copy local file %s to remote file %s: %w", kindConfigPath, remoteFilePath, err)
}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an error occurs after session2.Start() is called (lines 304-319), the function returns without calling session2.Wait() or closing remoteFile properly. This could leave the SSH session in an incomplete state. Consider closing remoteFile and calling session2.Wait() in error paths, similar to how the provision() function handles this (lines 249-258).

Copilot uses AI. Check for mistakes.
@coveralls
Copy link

coveralls commented Feb 12, 2026

Pull Request Test Coverage Report for Build 21979597278

Details

  • 0 of 21 (0.0%) changed or added relevant lines in 1 file are covered.
  • 7 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.08%) to 47.42%

Changes Missing Coverage Covered Lines Changed/Added Lines %
pkg/provisioner/provisioner.go 0 21 0.0%
Files with Coverage Reduction New Missed Lines %
pkg/provisioner/provisioner.go 7 2.23%
Totals Coverage Status
Change from base Build 21955389842: -0.08%
Covered Lines: 2500
Relevant Lines: 5272

💛 - Coveralls

SSH sessions in x/crypto/ssh are single-use. The old code called
session.Run() then tried session.StdinPipe() on the same session,
which always failed. Split into two sessions (mkdir + file write),
following the pattern used in createKubeAdmConfig. Also close the
local file that was previously leaked.

Audit findings NVIDIA#2 (HIGH), NVIDIA#12 (MEDIUM).

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
@ArangoGutierrez ArangoGutierrez force-pushed the fix/provisioner-kind-config branch from ed1d8b9 to f362ca8 Compare February 13, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants