cli/internal/cmd/updater/docs/architecture.md
Snider f47e8211fb feat(mcp): add workspace root validation to prevent path traversal (#100)
* feat(mcp): add workspace root validation to prevent path traversal

- Add workspaceRoot field to Service for restricting file operations
- Add WithWorkspaceRoot() option for configuring the workspace directory
- Add validatePath() helper to check paths are within workspace
- Apply validation to all file operation handlers
- Default to current working directory for security
- Add comprehensive tests for path validation

Closes #82

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: move CLI commands from pkg/ to internal/cmd/

- Move 18 CLI command packages to internal/cmd/ (not externally importable)
- Keep 16 library packages in pkg/ (externally importable)
- Update all import paths throughout codebase
- Cleaner separation between CLI logic and reusable libraries

CLI commands moved: ai, ci, dev, docs, doctor, gitcmd, go, monitor,
php, pkgcmd, qa, sdk, security, setup, test, updater, vm, workspace

Libraries remaining: agentic, build, cache, cli, container, devops,
errors, framework, git, i18n, io, log, mcp, process, release, repos

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mcp): use pkg/io Medium for sandboxed file operations

Replace manual path validation with pkg/io.Medium for all file operations.
This delegates security (path traversal, symlink bypass) to the sandboxed
local.Medium implementation.

Changes:
- Add io.NewSandboxed() for creating sandboxed Medium instances
- Refactor MCP Service to use io.Medium instead of direct os.* calls
- Remove validatePath and resolvePathWithSymlinks functions
- Update tests to verify Medium-based behaviour

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: correct import path and workflow references

- Fix pkg/io/io.go import from core-gui to core
- Update CI workflows to use internal/cmd/updater path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(security): address CodeRabbit review issues for path validation

- pkg/io/local: add symlink resolution and boundary-aware containment
  - Reject absolute paths in sandboxed Medium
  - Use filepath.EvalSymlinks to prevent symlink bypass attacks
  - Fix prefix check to prevent /tmp/root matching /tmp/root2

- pkg/mcp: fix resolvePath to validate and return errors
  - Changed resolvePath from (string) to (string, error)
  - Update deleteFile, renameFile, listDirectory, fileExists to handle errors
  - Changed New() to return (*Service, error) instead of *Service
  - Properly propagate option errors instead of silently discarding

- pkg/io: wrap errors with E() helper for consistent context
  - Copy() and MockMedium.Read() now use coreerr.E()

- tests: rename to use _Good/_Bad/_Ugly suffixes per coding guidelines
  - Fix hardcoded /tmp in TestPath to use t.TempDir()
  - Add TestResolvePath_Bad_SymlinkTraversal test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style: fix gofmt formatting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style: fix gofmt formatting across all files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:59:34 +00:00

2.5 KiB

Architecture

The updater library is designed to facilitate self-updates for Go applications by replacing the running binary with a newer version downloaded from a remote source.

Update Mechanisms

The library supports two primary update sources:

  1. GitHub Releases: Fetches releases directly from a GitHub repository.
  2. Generic HTTP: Fetches update information from a generic HTTP endpoint.

GitHub Releases

When configured with a GitHub repository URL (e.g., https://github.com/owner/repo), the updater uses the GitHub API to find releases.

  • Channel Support: You can specify a "channel" (e.g., "stable", "beta"). The updater will filter releases based on this channel.
    • Ideally, this maps to release tags or pre-release status (though the specific implementation details of how "channel" maps to GitHub release types should be verified in the code).
  • Pull Request Updates: The library supports updating to a specific pull request artifact, useful for testing pre-release builds.

Generic HTTP

When configured with a generic HTTP URL, the updater expects the endpoint to return a JSON object describing the latest version.

Expected JSON Format:

{
  "version": "1.2.3",
  "url": "https://your-server.com/path/to/release-asset"
}

The updater compares the version from the JSON with the current application version. If the remote version is newer, it downloads the binary from the url.

Version Comparison

The library uses Semantic Versioning (SemVer) to compare versions.

  • Prefix Handling: The ForceSemVerPrefix configuration option allows you to standardize version tags by enforcing a v prefix (e.g., v1.0.0 vs 1.0.0) for consistent comparison.
  • Logic:
    • If Remote Version > Current Version: Update available.
    • If Remote Version <= Current Version: Up to date.

Self-Update Process

The actual update process is handled by the minio/selfupdate library.

  1. Download: The new binary is downloaded from the source.
  2. Verification: (Depending on configuration/implementation) Checksums may be verified.
  3. Apply: The current executable file is replaced with the new binary.
    • Windows: The old binary is renamed (often to .old) before replacement to allow the write operation.
    • Linux/macOS: The file is unlinked and replaced.
  4. Restart: The application usually needs to be restarted for the changes to take effect. The updater library currently handles the replacement, but the restart logic is typically left to the application.