Skip to content

release: v0.4.0 portability and hardening - #20

Merged
bolens merged 59 commits into
mainfrom
release/v0.4.0
Aug 9, 2026
Merged

release: v0.4.0 portability and hardening#20
bolens merged 59 commits into
mainfrom
release/v0.4.0

Conversation

@bolens

@bolens bolens commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • ship portable macOS arm64 and Windows amd64 release archives
  • harden cache, provider, pack, configuration, daemon, and native discovery boundaries
  • add extensive hostile-input, offline/cache-first, portability, and release-contract coverage
  • prepare the v0.4.0 changelog

Validation

  • make check
  • go test -race ./...

Release

After review and green required checks, merge this PR and follow docs/releasing.md to tag v0.4.0, verify release assets, refresh packaging in a separate PR, and update the local installation.

bolens added 30 commits August 8, 2026 14:34
Revalidate every redirect against the configured HTTPS host allowlist, including when callers inject a custom HTTP client.
Block direct metadata and link-local archive targets. Require HTTPS for every redirect and reject loopback or private IP destinations across IPv4 and IPv6.
Apply the archive-wide uncompressed size limit to local pack bundles so many individually valid members cannot bypass extraction bounds.
Revalidate every redirect from injected HTTP clients so shared CDN stages cannot escape their configured HTTPS host allowlists.
Revalidate asset redirects even for injected HTTP clients so downloads remain within the documented HTTPS host allowlist.
Keep redirected asset requests on the configured HTTPS host even when callers inject an HTTP client with redirect following enabled.
Keep token-bearing image redirects on the configured HTTPS host even when an injected HTTP client follows redirects.
Keep OAuth-signed API redirects on the configured HTTPS host even when an injected HTTP client follows redirects.
Treat configured test endpoints as additional HTTPS hosts instead of disabling validation, and revalidate every authenticated redirect.
Validate paths, symlink parents, expansion limits, member streams, and gzip completion before an untrusted bundle can overwrite existing pack files.
Restore the previous pack tree when source registration fails after a successful archive extraction.
Reject dot-derived names and explicit root destinations before cleanup can remove unrelated installed packs.
bolens added 23 commits August 8, 2026 16:30
Limit untrusted index reads to 4 MiB and reject normalized key collisions before filesystem fallback. Prefer shallow matches independent of depth-first traversal order.
Bound hostile archives to 10,000 members in validation and extraction paths so zero-byte entries cannot exhaust inodes or CPU while remaining under byte limits.
Reject malformed and non-image responses before they can be cached as SVG artifacts.
Invalid source configuration must not trigger remote requests or modify existing pack files before registration fails.
A symlink to an existing Git checkout could bypass destination safety checks and update files outside the pack root.
Pack paths must be absolute or use ~/ so CLI and daemon resolution cannot diverge by working directory. Existing relative paths must be updated.
Limit each daemon frame to 256 queries so compact batches cannot amplify into unbounded sequential resolver work.
Copilot AI lite review requested due to automatic review settings August 8, 2026 23:57

Copilot AI left a comment

Copy link
Copy Markdown

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 prepares the v0.4.0 release by expanding portable release artifact generation/verification and by hardening cache/config/provider/pack/daemon boundaries with a strong emphasis on cache-first + hostile-input safety across platforms.

Changes:

  • Add portable release build + verification scripts, wire them into CI/Make targets, and update the changelog/docs accordingly.
  • Harden resolution pipeline behavior (global offline mode, context cancel checks, daemon batch limits, stricter config decoding/validation).
  • Strengthen cache and pack safety (symlink/path containment, atomic replacement/locking, archive extraction caps/rollback) and provider redirect allowlisting.

Reviewed changes

Copilot reviewed 66 out of 66 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
SECURITY.md Updates security guarantees for local pack hardening boundaries.
scripts/ci/verify-release.sh Adds portable checksum verification via sha256sum/shasum fallback.
scripts/ci/check-verify-release.sh New contract test for release verification portability and corruption/missing handling.
scripts/ci/check-release-build.sh New contract test for release archive naming, contents, and version metadata.
scripts/ci/build-release.sh New release archive builder for multiple GOOS/GOARCH targets + checksums.
README.md Documents pack path constraints and updates install/checksum examples.
Makefile Adds release contract checks to check target.
internal/xdg/xdg.go Rejects non-absolute XDG data dirs; trims env inputs.
internal/xdg/xdg_test.go Extends home expansion tests and rejects named-user ~someone paths.
internal/xdg/theme.go Centralizes home expansion via userpath.ExpandHome.
internal/xdg/portability_test.go Adds portability tests for XDG dir handling.
internal/xdg/native.go Improves native app index invalidation via scoped fingerprints/hashes.
internal/xdg/native_cache_test.go Adds cache invalidation tests for shortcuts and macOS bundles.
internal/xdg/desktop.go Adds hidden desktop handling + nested .desktop discovery + stable IDs.
internal/xdg/desktop_hidden_test.go New tests for hidden desktop masking and nested IDs.
internal/svgl/svgl.go Adds redirect allowlisting and URL-hash-based cache invalidation.
internal/svgl/svgl_test.go Tests redirect allowlist enforcement and URL-change cache separation.
internal/svgl/allowlist_test.go Expands AssetFileName tests for URL edge cases.
internal/slugcdn/slugcdn.go Adds redirect allowlisting to CDN downloads.
internal/slugcdn/slugcdn_test.go Adds tests for empty cache refetch and redirect policy behavior.
internal/resolve/suggest.go Switches catalog title reads to shared catalog parsing helper.
internal/resolve/sources.go Adds locked read-modify-write updates + stricter stage/path/env validation.
internal/resolve/resolve.go Adds global offline mode + context cancellation checks per-stage.
internal/resolve/resolve_test.go Tests APPICON_OFFLINE prevents remote resolution.
internal/resolve/overrides.go Makes ConfigDir portable; normalizes overrides with validation + ambiguity detection.
internal/resolve/overrides_test.go Adds tests for ConfigDir fallback and override normalization errors.
internal/resolve/features_more_test.go Adds context-cancel behavior tests and catalog format coverage.
internal/resolve/configfile.go Disallows unknown fields + rejects multiple JSON/YAML documents.
internal/resolve/config_auth_test.go Tests unknown-field and multi-document config rejection + stage validation.
internal/resolve/complete.go Adds catalog wrapper parsing (items) and malformed-cache handling.
internal/resolve/batch.go Avoids calling Resolve when ctx already canceled.
internal/packs/packs.go Hardens pack installs (offline, redirects, staging/rollback, limits, symlink checks).
internal/packs/packs_test.go Adds extensive hostile-input and rollback/portability/redirect tests.
internal/packs/bundle_total_test.go New tests for bundle total-size and entry-count caps.
internal/pack/pack.go Caps index read size; rejects ambiguous keys; improves symlink containment and deterministic selection.
internal/pack/pack_test.go Tests oversized index, key collisions, symlink containment, and shallow-match preference.
internal/nounproject/nounproject.go Adds query→ID cache, redirect allowlisting, and wrapped download decoding.
internal/nounproject/nounproject_test.go Adds cache-first/offline tests, wrapped payload decode tests, and redirect policy tests.
internal/logodev/logodev.go Adds redirect allowlisting for provider downloads.
internal/logodev/logodev_test.go Tests unsafe redirects rejection and redirect policy preservation.
internal/limitio/limitio.go Prevents max+1 overflow when max is near MaxInt.
internal/limitio/limitio_test.go Adds regression test for maximum bound behavior.
internal/iconify/iconify.go Adds redirect allowlisting for iconify downloads.
internal/iconify/iconify_test.go Tests unsafe redirects rejection and redirect policy preservation.
internal/httpindex/httpindex.go Separates index cache by URL identity + locks refresh; adds redirect allowlisting and URL-hash asset names.
internal/httpindex/httpindex_test.go Adds tests for concurrency, redirect enforcement, and index URL separation.
internal/githubicon/githubicon.go Adds cache-first probe for default repo assets + redirect allowlisting on client.
internal/githubicon/githubicon_test.go Adds tests for cache-first behavior and redirect/host enforcement.
internal/daemon/server.go Enforces a max query count for resolve-batch requests.
internal/daemon/protocol.go Defines MaxBatchQueries and hardens XDG_RUNTIME_DIR handling.
internal/daemon/daemon_test.go Adds tests for offline forwarding, response validation, and batch query limits.
internal/daemon/client.go Validates daemon response identity + enforces batch limits client-side.
internal/cache/rename_windows.go Adds Windows atomic replace behavior via MoveFileEx.
internal/cache/rename_other.go Adds non-Windows rename wrapper.
internal/cache/flock_windows.go Adds Windows file-lock implementation.
internal/cache/flock_other.go Adjusts build tags to exclude Windows from non-unix stub.
internal/cache/cache.go Adds empty-artifact rejection, symlink checks, process+OS locking, and safer TTL freshness semantics.
internal/cache/cache_test.go Adds tests for empty artifacts, symlink refusal, and process/goroutine lock serialization.
docs/sources.schema.json Documents pack path expectations and env var name regex patterns.
docs/sources.md Documents portable env var naming and absolute XDG path requirements.
docs/packs.md Updates pack layout and hardening guarantees (limits, redirects, index bounds).
docs/consumer-contract.md Documents daemon batch limit in the consumer contract.
cmd/appicon/daemon_integration_test.go Ensures batch miss hints are present when using daemon + explain.
CHANGELOG.md Adds v0.4.0 release notes and highlights portability/hardening work.
.github/workflows/release.yml Switches release workflow to new build-release script.
.github/workflows/ci.yml Runs release build/verification contract tests in the Windows compile job.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/packs/packs.go
Comment thread scripts/ci/check-verify-release.sh
@bolens
bolens merged commit fc6b5e6 into main Aug 9, 2026
47 checks passed
@bolens
bolens deleted the release/v0.4.0 branch August 9, 2026 00:07
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