Skip to content

fix: validate zi repository identity before destructive git operations; automate checksum generation#176

Merged
ss-o merged 19 commits into
mainfrom
copilot/fix-install-script-destroying-untracked-work
Jul 24, 2026
Merged

fix: validate zi repository identity before destructive git operations; automate checksum generation#176
ss-o merged 19 commits into
mainfrom
copilot/fix-install-script-destroying-untracked-work

Conversation

Copilot AI commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

install.sh's update path ran git clean -d -f -f + git reset --hard HEAD against ${ZI_HOME}/${ZI_BIN_DIR_NAME} after only checking for a .git directory — any git repo at that path would be destroyed. A secondary issue: the -b branch name was interpolated unescaped into a sed expression using | as delimiter.

Security fixes (public/sh/install.sh)

Repository identity validation — before any destructive git operation, the update path now verifies:

  1. zi.zsh sentinel file is present
  2. Remote origin is one of the four canonical zi URLs (exact match, not substring)
if test -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"; then
  case "$(command git -C "${ZI_HOME}/${ZI_BIN_DIR_NAME}" remote get-url origin 2>/dev/null || true)" in
    https://github.com/z-shell/zi | https://github.com/z-shell/zi.git \
    | git@github.com:z-shell/zi | git@github.com:z-shell/zi.git)
      _zi_valid=1 ;;
  esac
fi

Failure exits with a clear message directing the user to unset ZI_HOME/ZI_BIN_DIR_NAME.

BOPT validation — branch names containing |, \, or & are rejected before they reach the sed expression.

Checksum automation (public/sh/generate-checksums.sh)

New portable script regenerates public/checksum.txt using sha256sum (Linux) or shasum -a 256 (macOS). Replaces the third-party jmgilman/actions-generate-checksum action in checksum.yml. Added as a pre-test step in check-linux.yml and check-macos.yml so CI never runs against a stale checksum file.

Tests (tests/installers.sh)

  • Updated fake git double to handle -C <dir> prefix and remote get-url origin
  • Added three test cases: valid zi clone update, foreign repo rejection, wrong remote URL rejection — each asserting the error message

@ss-o
ss-o marked this pull request as ready for review July 24, 2026 03:33
Copilot AI review requested due to automatic review settings July 24, 2026 03:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot wasn't able to review any files in this pull request.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add zi repository validation (zi.zsh sentinel + z-shell/zi remote URL check)
  before git clean/reset/pull in the update path of install.sh
- Add BOPT validation to reject branch names containing '|', '\', or '&'
  to prevent sed delimiter injection when updating init.zsh
- Update fake git test double to handle '-C <dir>' prefix and 'remote get-url'
- Add tests: valid zi clone update, foreign repo rejection, wrong-remote rejection
- Update public/checksum.txt to match modified install.sh

Fixes: #175
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 24, 2026

Copy link
Copy Markdown

Deploying src with  Cloudflare Pages  Cloudflare Pages

Latest commit: ed4776b
Status: ✅  Deploy successful!
Preview URL: https://b6aee0bc.zi-src.pages.dev
Branch Preview URL: https://copilot-fix-install-script-d.zi-src.pages.dev

View logs

Copilot AI added 9 commits July 24, 2026 03:43
- Fix BOPT backslash case pattern: *'\\'* → *\\* to correctly match
  a single backslash (not two)
- Anchor the remote URL grep to 'github.com[/:]z-shell/zi' to prevent
  spoofing via URLs like 'evil.com/fake-z-shell/zi'
- Validate remote subcommand args in the fake git test double
- Capture and assert specific error messages in rejection tests
- Update checksum for modified install.sh
- Revert *'\''* (wrong: matches single-quote) back to *\\* (correct: matches
  single backslash) and add clarifying comment explaining *\\* semantics
- Change test double error message from '$*' to a fixed descriptive string
- Update checksum for modified install.sh
Replace partial grep match 'github.com[/:]z-shell/zi' with an exact
shell case pattern that accepts only the four canonical zi remote URLs:
- https://github.com/z-shell/zi
- https://github.com/z-shell/zi.git
- git@github.com:z-shell/zi
- git@github.com:z-shell/zi.git

This prevents spoofing via URLs like 'evil.com/github.com/z-shell/zi'
and eliminates false-positive risk on empty _zi_remote values.
- Add actual args to test double error message for debuggability
- Add comment on canonical URL block pointing to z-shell/zi on GitHub
- Update checksum for modified install.sh
Remove positional parameters from error message and add comment
explaining argument state after -C strip and cmd shift.
- Add public/sh/generate-checksums.sh for local and CI use
- Update check-linux.yml and check-macos.yml to regenerate checksums
  before the test run, keeping public/checksum.txt in sync automatically
Add public/sh/generate-checksums.sh that regenerates public/checksum.txt
using sha256sum (Linux) or shasum -a 256 (macOS). Integrate it into the
CI pipelines so checksums are never stale:

- check-linux.yml: run generate-checksums.sh before tests/installers.sh
- check-macos.yml: run generate-checksums.sh before tests/installers.sh
- checksum.yml: replace jmgilman/actions-generate-checksum action with
  the new script; add generate-checksums.sh to trigger paths

Developers can now run `sh public/sh/generate-checksums.sh` locally
instead of manually updating public/checksum.txt after editing scripts.
- tests/installers.sh: remove _sub/_arg temp variables in remote handler;
  use $1/$2 directly in the condition (simpler, reviewer preference)
- public/sh/install.sh: reformat case pattern continuation so each line
  ends with the | pipe rather than beginning with \; add comment naming
  the four canonical URL forms (HTTPS/SSH, with/without .git suffix)
- public/sh/generate-checksums.sh: add comment on bare > redirection
  explaining that it clears/creates the checksum file
- public/checksum.txt: regenerate after install.sh formatting change
…e _exit_code

- public/sh/install.sh: inline _zi_remote command substitution directly
  into the case statement; eliminates the temporary variable
- tests/installers.sh: rename _exit_code to exit_code in two test
  functions to match the no-leading-underscore convention used elsewhere
- public/checksum.txt: regenerate after install.sh change
Copilot AI changed the title [WIP] Fix destructive git reset/clean in install.sh fix: validate zi repository identity before destructive git operations; automate checksum generation Jul 24, 2026
Copilot finished work on behalf of ss-o July 24, 2026 04:01
Copilot AI requested a review from ss-o July 24, 2026 04:01
@ss-o
ss-o requested a review from Copilot July 24, 2026 04:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread public/sh/install.sh Outdated
Comment thread public/sh/generate-checksums.sh
ss-o and others added 3 commits July 24, 2026 05:15
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>
@ss-o
ss-o marked this pull request as draft July 24, 2026 04:29
Copilot finished work on behalf of ss-o July 24, 2026 04:31
@ss-o
ss-o marked this pull request as ready for review July 24, 2026 06:07
@ss-o
ss-o merged commit 196e21c into main Jul 24, 2026
8 checks passed
@ss-o
ss-o deleted the copilot/fix-install-script-destroying-untracked-work branch July 24, 2026 06:09
github-actions Bot pushed a commit that referenced this pull request Jul 24, 2026
…s; automate checksum generation (#176)

* fix: validate zi repository identity before destructive git operations

- Add zi repository validation (zi.zsh sentinel + z-shell/zi remote URL check)
  before git clean/reset/pull in the update path of install.sh
- Add BOPT validation to reject branch names containing '|', '\', or '&'
  to prevent sed delimiter injection when updating init.zsh
- Update fake git test double to handle '-C <dir>' prefix and 'remote get-url'
- Add tests: valid zi clone update, foreign repo rejection, wrong-remote rejection
- Update public/checksum.txt to match modified install.sh

Fixes: #175

* fix: address code review feedback on security validation

- Fix BOPT backslash case pattern: *'\\'* → *\\* to correctly match
  a single backslash (not two)
- Anchor the remote URL grep to 'github.com[/:]z-shell/zi' to prevent
  spoofing via URLs like 'evil.com/fake-z-shell/zi'
- Validate remote subcommand args in the fake git test double
- Capture and assert specific error messages in rejection tests
- Update checksum for modified install.sh

* fix: address remaining code review issues

- Revert *'\''* (wrong: matches single-quote) back to *\\* (correct: matches
  single backslash) and add clarifying comment explaining *\\* semantics
- Change test double error message from '$*' to a fixed descriptive string
- Update checksum for modified install.sh

* fix: strengthen URL matching with exact case pattern instead of grep

Replace partial grep match 'github.com[/:]z-shell/zi' with an exact
shell case pattern that accepts only the four canonical zi remote URLs:
- https://github.com/z-shell/zi
- https://github.com/z-shell/zi.git
- git@github.com:z-shell/zi
- git@github.com:z-shell/zi.git

This prevents spoofing via URLs like 'evil.com/github.com/z-shell/zi'
and eliminates false-positive risk on empty _zi_remote values.

* fix: add clarity improvements from code review

- Add actual args to test double error message for debuggability
- Add comment on canonical URL block pointing to z-shell/zi on GitHub
- Update checksum for modified install.sh

* fix: clarify test double error message for remote subcommand validation

Remove positional parameters from error message and add comment
explaining argument state after -C strip and cmd shift.

* chore: add automated checksum generation script and integrate into CI

- Add public/sh/generate-checksums.sh for local and CI use
- Update check-linux.yml and check-macos.yml to regenerate checksums
  before the test run, keeping public/checksum.txt in sync automatically

* feat: automate checksum generation with generate-checksums.sh

Add public/sh/generate-checksums.sh that regenerates public/checksum.txt
using sha256sum (Linux) or shasum -a 256 (macOS). Integrate it into the
CI pipelines so checksums are never stale:

- check-linux.yml: run generate-checksums.sh before tests/installers.sh
- check-macos.yml: run generate-checksums.sh before tests/installers.sh
- checksum.yml: replace jmgilman/actions-generate-checksum action with
  the new script; add generate-checksums.sh to trigger paths

Developers can now run `sh public/sh/generate-checksums.sh` locally
instead of manually updating public/checksum.txt after editing scripts.

* refactor: address code review feedback - minor clarity improvements

- tests/installers.sh: remove _sub/_arg temp variables in remote handler;
  use $1/$2 directly in the condition (simpler, reviewer preference)
- public/sh/install.sh: reformat case pattern continuation so each line
  ends with the | pipe rather than beginning with \; add comment naming
  the four canonical URL forms (HTTPS/SSH, with/without .git suffix)
- public/sh/generate-checksums.sh: add comment on bare > redirection
  explaining that it clears/creates the checksum file
- public/checksum.txt: regenerate after install.sh formatting change

* refactor: address second code review round - inline _zi_remote, rename _exit_code

- public/sh/install.sh: inline _zi_remote command substitution directly
  into the case statement; eliminates the temporary variable
- tests/installers.sh: rename _exit_code to exit_code in two test
  functions to match the no-leading-underscore convention used elsewhere
- public/checksum.txt: regenerate after install.sh change

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>

* Checksum 83d3f57

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>

* fix: satisfy shellcheck in checksum generator

* fix: remove remaining shellcheck warning

* chore: refresh installer checksum

* test: clarify fake git remote errors

* chore: address validation feedback

---------

Signed-off-by: Sal <59910950+ss-o@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Sal <59910950+ss-o@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: digital-teams[bot] <actions@zshell.dev> 196e21c
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.

install.sh: destructive git reset/clean on unvalidated ZI_HOME/ZI_BIN_DIR_NAME target

4 participants