Skip to content

fix(instances): return errors from GenerateInstanceID, validate ID format#648

Merged
ArangoGutierrez merged 1 commit intoNVIDIA:mainfrom
ArangoGutierrez:fix/instance-id-errors
Feb 13, 2026
Merged

fix(instances): return errors from GenerateInstanceID, validate ID format#648
ArangoGutierrez merged 1 commit intoNVIDIA:mainfrom
ArangoGutierrez:fix/instance-id-errors

Conversation

@ArangoGutierrez
Copy link
Collaborator

Summary

  • Change GenerateInstanceID to return (string, error) instead of silently returning empty string on crypto/rand failure (which produced a cache file named .yaml)
  • Add hex format validation to GetInstanceCacheFile to prevent path traversal attacks (rejects ../../etc/passwd, shell metacharacters, etc.)
  • Accept both 8-char hex IDs (new format) and UUID format (backward compatibility)
  • Update all callers in cmd/cli/create/create.go and internal methods (GetInstance, DeleteInstance, GetInstanceByFilename)

Audit findings: #8 (MEDIUM), #35 (LOW)

Test plan

  • TestGenerateInstanceID — verifies 8-char hex output and error return
  • TestGetInstanceCacheFile — verifies valid hex and UUID IDs accepted
  • TestGetInstanceCacheFile_RejectsTraversal — verifies ../../etc/passwd rejected
  • TestGetInstanceCacheFile_RejectsInvalidFormat — verifies empty, short, uppercase, non-hex, shell injection, path separators all rejected
  • All existing tests updated and passing
  • gofmt clean
  • golangci-lint — 0 issues
  • go test ./internal/instances/... ./cmd/cli/create/... -v — PASS
  • go build -o bin/holodeck cmd/cli/main.go — compiles
  • go mod tidy && go mod verify — clean

…rmat

GenerateInstanceID silently returned empty string on rand failure,
producing a cache file named '.yaml'. Change to return (string, error).
Also validate instance IDs match hex format in GetInstanceCacheFile
to prevent path traversal.

Audit findings NVIDIA#8 (MEDIUM), NVIDIA#35 (LOW).

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Copilot AI review requested due to automatic review settings February 12, 2026 19:46
@coveralls
Copy link

Pull Request Test Coverage Report for Build 21961744234

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 47.501%

Totals Coverage Status
Change from base Build 21955389842: 0.0%
Covered Lines: 2500
Relevant Lines: 5263

💛 - Coveralls

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 hardens instance ID handling in Holodeck by making instance ID generation/reporting fail loudly on entropy errors and by validating instance IDs before constructing cache file paths (mitigating path traversal).

Changes:

  • Change GenerateInstanceID to return (string, error) and propagate crypto/rand failures.
  • Add strict instance ID format validation in GetInstanceCacheFile (accept 8-char lowercase hex + lowercase UUID for backwards compatibility).
  • Update CLI create flow and instance manager methods/tests to handle the new error-returning APIs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
internal/instances/instances.go Add ID format regex validation, return errors from ID generation and cache-path construction, and plumb errors through instance operations.
internal/instances/instances_test.go Update tests for new signatures and add validation/traversal rejection coverage.
cmd/cli/create/create.go Update create command to handle (string, error) and validated cache file path creation.

Comment on lines +214 to 216
// Test deleting instance with invalid ID format
err = manager.DeleteInstance("nonexistent")
assert.Error(t, 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.

This test case now exercises only the invalid-ID-format path ("nonexistent" is rejected by the new format validation) and no longer verifies behavior when a valid instance ID is provided but the cache file is missing. Consider adding a separate subtest that calls DeleteInstance with a valid-looking ID that has no cache file and asserting the expected error (e.g., wraps the read-cache-file failure).

Copilot generated this review using guidance from repository custom instructions.
opts.cacheFile = manager.GetInstanceCacheFile(instanceID)
instanceID, err := manager.GenerateInstanceID()
if err != nil {
return fmt.Errorf("failed to generate instance ID: %w", 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.

GenerateInstanceID already wraps rand.Read failures with failed to generate instance ID: ..., and this call site wraps again with the same prefix, producing a duplicated error message. Consider returning the original error directly here, or wrapping with different context to avoid repetition.

Suggested change
return fmt.Errorf("failed to generate instance ID: %w", err)
return err

Copilot uses AI. Check for mistakes.
Comment on lines 331 to +334
// GetInstanceByFilename returns details for a specific instance by its filename
func (m *Manager) GetInstanceByFilename(filename string) (*Instance, error) {
cacheFile := m.GetInstanceCacheFile(filename)
cacheFile, err := m.GetInstanceCacheFile(filename)
if err != nil {
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.

The GetInstanceByFilename docstring/parameter name implies callers can pass an actual filename, but the implementation validates the value as an instance ID and appends .yaml via GetInstanceCacheFile. This will fail if a caller passes something like abcd1234.yaml. Consider clarifying in the comment (and/or renaming the parameter) that this expects the cache filename stem / instance ID without the .yaml extension.

Copilot uses AI. Check for mistakes.
Comment on lines +171 to 173
// Test getting instance with invalid ID format
_, err = manager.GetInstance("nonexistent")
assert.Error(t, 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.

These assertions now only cover the invalid-ID-format path ("nonexistent" is neither 8-char hex nor UUID). This drops coverage for the "valid ID but cache file does not exist" behavior in GetInstance, which is still an important error path after the refactor. Consider adding a subtest that uses a valid-looking ID (e.g. a1b2c3d4) that has no corresponding cache file and asserting the returned error.

Copilot generated this review using guidance from repository custom instructions.
@ArangoGutierrez ArangoGutierrez merged commit 8feb790 into NVIDIA:main Feb 13, 2026
25 checks passed
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.

3 participants