Skip to content

refactor: File Access to use os.Root (Mitigate G304) #76

@drlucaa

Description

@drlucaa

We are currently suppressing gosec G304 warnings (Potential file inclusion via variable) using //nolint:gosec comments in several adapters. With our upgrade to Go 1.25+, we can now leverage the os.Root API introduced in Go 1.24 to enforce secure, directory-scoped file access.

Using os.Root guarantees that file operations cannot escape the intended directory, effectively mitigating path traversal vulnerabilities at the filesystem level. This allows us to remove the linter suppressions and improve the actual security posture of the application.

Note: This refactor applies to file access (G304). It does not apply to command execution (G204) in shell/executor.go, as os.Root does not support executing binaries.

Goals

  1. Refactor internal/adapters/cas to use os.OpenRoot for the CAS store directory.
  2. Refactor internal/adapters/nix to use os.OpenRoot for the NixHub cache directory.
  3. Refactor internal/adapters/config to safely load configuration files relative to the project root.
  4. Remove //nolint:gosec directives in the refactored files.

Implementation Plan

1. CAS Store (internal/adapters/cas/store.go)

  • Update Store struct to hold *os.Root instead of a string path.
  • In NewStore, use os.OpenRoot to open the .same/store directory.
  • Replace os.ReadFile and os.WriteFile calls with s.root.ReadFile and s.root.WriteFile.
  • Remove path joining logic that constructs absolute paths for artifacts; use relative names with the root handle.

2. Nix Resolver (internal/adapters/nix/resolver.go)

  • Update Resolver to hold *os.Root for the cache directory.
  • Replace atomicWriteFile and loadFromCache logic to operate on the root handle.
  • Ensure the root is properly closed on shutdown if necessary.

3. Config Loader (internal/adapters/config/loader.go)

  • When loading a project, open the project directory using os.OpenRoot.
  • Load same.yaml using the root handle to prevent a malicious config from pointing input fields to sensitive system files outside the project scope (e.g., ../../../etc/passwd).

Acceptance Criteria

  • internal/adapters/cas/store.go no longer requires //nolint:gosec for file reads/writes.
  • internal/adapters/nix/resolver.go no longer requires //nolint:gosec.
  • internal/adapters/config/loader.go uses os.Root for file operations.
  • All existing tests pass (nix develop -c go test ./cli/...).
  • golangci-lint passes without the removed suppressions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions