Last active
July 28, 2026 02:57
-
-
Save kristovatlas/544b2d7a8314cf21c67e33b5a081695a to your computer and use it in GitHub Desktop.
Install Claude Code based on known-good hash instead of curl-bashing; Install Codex with Socket.dev Firewall
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # ── Helpers ────────────────────────────────────────────────────── | |
| info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; } | |
| ok() { printf '\033[1;32m[OK]\033[0m %s\n' "$*"; } | |
| err() { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*" >&2; } | |
| # ── Pre-flight: require npm ────────────────────────────────────── | |
| if ! command -v npm &>/dev/null; then | |
| err "npm is not installed. Please install Node.js/npm first." | |
| exit 1 | |
| fi | |
| info "Node $(node -v) / npm $(npm -v)" | |
| # ── Check for Socket Firewall (sfw) ───────────────────────────── | |
| if command -v sfw &>/dev/null; then | |
| ok "Socket Firewall is already installed: $(sfw --version 2>/dev/null || echo 'version unknown')" | |
| else | |
| info "Socket Firewall not found. Installing globally via npm..." | |
| npm i -g sfw | |
| # Verify the install succeeded | |
| if command -v sfw &>/dev/null; then | |
| ok "Socket Firewall installed successfully." | |
| else | |
| err "sfw command not found after install. Check that npm's global bin directory is in your PATH." | |
| err "Hint: npm config get prefix → add <prefix>/bin to your PATH" | |
| exit 1 | |
| fi | |
| fi | |
| # ── Clear npm cache (recommended by Socket before first use) ───── | |
| info "Clearing npm cache so sfw can intercept all network requests..." | |
| npm cache clean --force | |
| # ── Run the guarded install ────────────────────────────────────── | |
| info "Running: sfw npm i -g @openai/codex" | |
| sfw npm i -g @openai/codex | |
| ok "Done! @openai/codex installed with Socket Firewall protection." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| curl -fsSL https://code.kimi.com/kimi-code/install.sh -o install.sh && checksum="$(sha256sum install.sh | awk '{print $1}')"; if [ "$checksum" = "638927825e96825edbb563de5e0cb06f8a0551c53e026ade8b717b0f25cb83d2" ]; then echo "Checksum matched."; echo "Proceed with installation? (Y/n)"; read response; if [ "$response" = "Y" ] || [ "$response" = "y" ] || [ -z "$response" ]; then bash install.sh && rm -f install.sh; else echo "Installation aborted."; rm -f install.sh; exit 0; fi; else echo "Error: Checksum failed"; exit 1; fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| PKG="@z_ai/coding-helper" | |
| # ── Helpers ────────────────────────────────────────────────────── | |
| info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; } | |
| ok() { printf '\033[1;32m[OK]\033[0m %s\n' "$*"; } | |
| err() { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*" >&2; } | |
| # ── Pre-flight: require npm ────────────────────────────────────── | |
| if ! command -v npm &>/dev/null; then | |
| err "npm is not installed. Please install Node.js/npm first." | |
| exit 1 | |
| fi | |
| info "Node $(node -v) / npm $(npm -v)" | |
| # ── Check for Socket Firewall (sfw) ───────────────────────────── | |
| if command -v sfw &>/dev/null; then | |
| ok "Socket Firewall is already installed: $(sfw --version 2>/dev/null || echo 'version unknown')" | |
| else | |
| info "Socket Firewall not found. Installing globally via npm..." | |
| npm i -g sfw | |
| if command -v sfw &>/dev/null; then | |
| ok "Socket Firewall installed successfully." | |
| else | |
| err "sfw command not found after install. Check that npm's global bin directory is in your PATH." | |
| err "Hint: npm config get prefix → add <prefix>/bin to your PATH" | |
| exit 1 | |
| fi | |
| fi | |
| # ── Clear npm cache (recommended by Socket before first use) ───── | |
| # npx resolves through the same cache, so a stale cache means sfw | |
| # never sees the fetch. | |
| info "Clearing npm cache so sfw can intercept all network requests..." | |
| npm cache clean --force | |
| # ── Fetch the package under the firewall ───────────────────────── | |
| # Installing globally (rather than letting npx pull it on every run) | |
| # means the download happens exactly once, inside sfw. | |
| info "Running: sfw npm i -g $PKG" | |
| sfw npm i -g "$PKG" | |
| ok "$PKG installed with Socket Firewall protection." | |
| # ── Install a shell alias so future launches stay gated ────────── | |
| # Without this, typing `npx @z_ai/coding-helper` out of habit runs the | |
| # TUI with unrestricted network access — the firewall only ever covers | |
| # the command it directly wraps. The alias makes the safe form the | |
| # default one. | |
| ALIAS_NAME="zai-helper" | |
| ALIAS_LINE="alias ${ALIAS_NAME}='sfw npx --yes ${PKG}'" | |
| # Write to whichever rc files actually exist; fall back to ~/.bashrc. | |
| RC_FILES=() | |
| for rc in "$HOME/.bashrc" "$HOME/.zshrc"; do | |
| [[ -f "$rc" ]] && RC_FILES+=("$rc") | |
| done | |
| [[ ${#RC_FILES[@]} -eq 0 ]] && RC_FILES=("$HOME/.bashrc") | |
| for rc in "${RC_FILES[@]}"; do | |
| # Match on the alias name, not the whole line, so an older version | |
| # of the alias gets reported instead of silently duplicated. | |
| if grep -q "alias ${ALIAS_NAME}=" "$rc" 2>/dev/null; then | |
| info "An alias named '${ALIAS_NAME}' already exists in ${rc} — leaving it alone." | |
| else | |
| { | |
| printf '\n# Added by install-zai-helper-sfw.sh — run the z.ai TUI behind Socket Firewall\n' | |
| printf '%s\n' "$ALIAS_LINE" | |
| } >> "$rc" | |
| ok "Added '${ALIAS_NAME}' alias to ${rc}" | |
| fi | |
| done | |
| # Aliases are read at shell startup, so this one is not live yet in the | |
| # caller's session. | |
| info "Run 'source ${RC_FILES[0]}' or open a new shell to use: ${ALIAS_NAME}" | |
| # ── Launch, still gated ────────────────────────────────────────── | |
| info "Launching: sfw npx $PKG" | |
| exec sfw npx --yes "$PKG" "$@" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| curl -fsSL https://claude.ai/install.sh -o install.sh && checksum="$(sha256sum install.sh | awk '{print $1}')" | |
| if [ "$checksum" = "cde4f1702d3b1695f92b73d26888364e17bca476e17f0fd676484c951d36c125" ]; then | |
| echo "Checksum matched." | |
| echo "Proceed with installation? (Y/n)" | |
| read response | |
| if [ "$response" = "Y" ] || [ "$response" = "y" ] || [ -z "$response" ]; then bash install.sh && rm -f install.sh; else | |
| echo "Installation aborted." | |
| rm -f install.sh | |
| exit 0 | |
| fi | |
| else | |
| echo "Error: Checksum failed" | |
| exit 1 | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| curl -fsSL https://claude.ai/install.sh -o install.sh && checksum="$(sha256sum install.sh | awk '{print $1}')"; if [ "$checksum" = "cde4f1702d3b1695f92b73d26888364e17bca476e17f0fd676484c951d36c125" ]; then echo "Checksum matched."; echo "Proceed with installation? (Y/n)"; read response; if [ "$response" = "Y" ] || [ "$response" = "y" ] || [ -z "$response" ]; then bash install.sh && rm -f install.sh; else echo "Installation aborted."; rm -f install.sh; exit 0; fi; else echo "Error: Checksum failed"; exit 1; fi |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Latest CC review:
The two
curllines are inert. Both sit insideechostring arguments going to stderr — they're guidance text, never executed. The URL ishttps://claude.ai/install.sh: correct domain spelling, no typosquat, no lookalike TLD, HTTPS. The# pinned-dep-allowcomments accurately describe what they're suppressing, which is a good sign rather than a red flag. One thing to confirm in review: that the lint rule those comments suppress is line-scoped, so a suppression can't accidentally cover a genuinely executed fetch elsewhere in the file.The guard's logic is sound and its direction is privilege-reducing. It fires only when euid is 0 and
SUDO_USERis set to a non-root user, so plain root (containers, CI, root-only boxes) is untouched, as the comment claims.${SUDO_USER:-}and${CLAUDE_INSTALL_ALLOW_SUDO:-}are properly defaulted forset -u. Nothing here writes files, reads credentials, or touches the network. A change that refuses root is the opposite shape from what an attacker inserts.Three things worth flagging as ordinary review comments:
sudo CLAUDE_INSTALL_ALLOW_SUDO=1 bashsets the variable via sudo, which most default configs reject ("you are not allowed to set the following environment variables") unless the sudoers rule carriesSETENVor the name is inenv_keep.sudo env CLAUDE_INSTALL_ALLOW_SUDO=1 bashis the portable form. Users hitting a hardexit 1and then a second failure on the documented escape hatch is a bad path.sudo -iorsudo su -resets the environment, droppingSUDO_USER, so a user who takes a root login shell first sails past the guard and installs into/root— exactly the footgun being defended against. Probably acceptable, but it means the check catches the common form, not the class.curl … | sudo bash. Those pipelines will start failing at this newexit 1. Worth a changelog note.The snippet is cut off at both ends, so I can't see the check that precedes it or confirm the
exit 1that presumably follows these messages. If you want a verdict on the whole change, paste the full diff — in particular anything downstream that resolves$HOMEor does the actual download andchmod, since that's where an installer's real risk lives.The sudo guard. Placement is good — it sits after argument validation and before any network activity or filesystem writes, so it fails early and cheaply. The logic matches the comment: it fires only on euid 0 with a non-root
SUDO_USER, leaving plain root untouched. Nothing in the block touches the network, credentials, or disk. One correction to my earlier note: I said the${SUDO_USER:-}defaults were "properly defaulted forset -u" — the script only setsset -e, so those defaults aren't load-bearing. Harmless either way, but I overstated it. Theexit 1I couldn't see is present and correct.The rest of the script checks out. Both
curlinvocations in the error text remain inert (echoto stderr). The real fetches go todownloads.claude.aiover HTTPS, no IP literals or lookalike hosts. The trust chain is sound: binary verified against a SHA256 frommanifest.jsonon the same origin, checksum format anchored to^[a-f0-9]{64}$, mismatch deletes the file and exits nonzero,chmod +xhappens only after verification, and the download is removed afterward. Noeval, no base64 blobs, no shell-rc writes, no persistence, no env exfiltration.TARGETreaches the binary as a single quoted argv element and its regex forbids a leading-, so no option or shell injection.Three defense-in-depth notes, none of them about the change itself:
^[0-9]+\.[0-9]+\.[0-9]+), unlike the fully anchoredTARGETcheck.$versionthen flows intobinary_path="$DOWNLOAD_DIR/claude-$version-$platform", so server-controlled content like1.2.3/../../../../tmp/xwould place and execute the file outside$DOWNLOAD_DIR. It only matters ifdownloads.claude.aiitself is serving bad content — in which case you have worse problems — but adding(-[^[:space:]]+)?$costs nothing.set -o pipefail. It happens to be safe here: every pipeline that could swallow a failure (shasum | cut,jq) yields an empty string that then fails a subsequent check. That's fail-safe by accident rather than by construction.[^}]*can't cross the closing brace of the platform's object, so it can't bind a different platform's checksum, and$platforminterpolates from a fixed set ofuname-derived literals. It does silently depend onchecksumappearing after the platform key.My two substantive comments on the change stand:
sudo VAR=1 bashis rejected by default sudoers withoutSETENV, so the documented escape hatch will likely fail for the people who need it (sudo env CLAUDE_INSTALL_ALLOW_SUDO=1 bashis portable), andsudo -i/sudo su -dropsSUDO_USERand walks straight past the guard into/root.