mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-20 06:04:55 +00:00
3 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e250d6e314
|
feat: add qwen update and /update commands with auto-update support (#5780)
Some checks are pending
* fix: align standalone-update RC markers with install script, add version to update output ## Changes ### Compatibility fixes (standalone-update.ts) - ensurePathInShellRc: use install script's begin/end block markers (# Qwen Code PATH block begin/end) instead of single-line marker, preventing duplicate PATH entries - ensurePathInShellRc: fish shell uses set -gx PATH (matching install script) - ensurePathInShellRc: use single-quoted paths with shell_quote-style escaping - ensureBinWrapper: use #!/usr/bin/env sh shebang (matching install script) ### Version output - qwen update: show current version in 'up to date' message (Qwen Code X.Y.Z is up to date!) - /update slash command: same version display ### Build fix - esbuild.config.js: add ink/dom and ink/components/CursorContext aliases for ink 7.x compatibility ### i18n - en.js: add 9 update-related translation keys Co-Authored-By: Claude <noreply@anthropic.com> * i18n: add update command translations for all 8 non-English locales - zh: Simplified Chinese - zh-TW: Traditional Chinese - ja: Japanese - ru: Russian - de: German - pt: Portuguese (Brazil) - fr: French - ca: Catalan Co-Authored-By: Claude <noreply@anthropic.com> * fix update command review feedback * address update command review followups * fix update command test args type * address update review hardlink and fallback feedback * fix update tar filter typing and sdk bundle guard * fix(cli): address update review feedback * address update review followups * restore windows archive traversal scan * address update review observations * address latest update review findings * fix latest update review regressions * fix(cli): localize update command output * fix(cli): localize update install guidance * fix(cli): harden update review follow-ups * fix(cli): address latest update review comments * fix(cli): honor explicit update requests * fix(cli): address update command review feedback * fix(cli): address update slash command review feedback * fix(cli): address latest update review feedback * fix(cli): address update review follow-ups * add code * fix(cli): add .deferred marker to prevent Windows deferred update race On Windows, when atomicReplace returns 'deferred', a bat script runs detached to complete the swap after the Node process exits. The lock file alone was insufficient because acquireLock falls through when the Node PID is dead (process.kill check), allowing a second `qwen update` to steal the lock and interfere with the in-flight bat script. Add a .deferred marker file containing the bat script's PID. acquireLock now checks this marker via isProcessAlive(batPid) before allowing lock theft, blocking concurrent updates while the swap is still in progress. Co-Authored-By: Claude <noreply@anthropic.com> * fix(cli): harden update review edge cases * fix(cli): address PR #5780 review feedback on update engine * test(cli): fix update check test import * fix(cli): avoid duplicate startup update checks --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: 易良 <1204183885@qq.com> Co-authored-by: liziwl <23000702+liziwl@users.noreply.github.com> Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com> Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> Co-authored-by: yiliang114 <effortyiliang@gmail.com> |
||
|
|
7a4f080230
|
fix(cli): allow double dots in update archives (#5521) | ||
|
|
9e4bea606a
|
feat(cli): add standalone auto-update support (#4629)
* feat(cli): add standalone auto-update support Standalone installs (via install-qwen-standalone.sh) previously fell through to npm global detection, causing auto-update to run `npm install -g` which doesn't update the standalone binary. Now the CLI detects standalone installs by looking for manifest.json in ancestor directories, then performs a self-update: download archive from OSS/GitHub, verify SHA256, extract, and atomically replace the installation directory. Includes: input validation (semver + target allowlist), lockfile for concurrency, Windows deferred replacement via helper script, and tar path traversal protection. Closes #4627 * feat(cli): harden standalone update — smoke test, rollback, signature - Smoke test: spawn new binary with --version after extraction, before replacing the installation. Rejects broken/wrong-arch packages. - Rollback: keep .old directory after updates. Export rollbackStandaloneUpdate() for future /doctor rollback integration. - Signature: Ed25519 verification of SHA256SUMS via node:crypto. Embeds public key; CI signs with scripts/sign-release.sh. Graceful degradation when .sig is not yet published (transition period). Set QWEN_REQUIRE_SIGNATURE=1 to enforce strict mode. * fix(cli): address CI + review findings on standalone update - Fix TS4111: use bracket notation for process.env index signature - Fix CodeQL: validate paths for cmd.exe metacharacters before bat script - Fix Windows lock race: keep lock alive during deferred swap, release in bat script after move completes * fix(cli): use event payload in update UI + add rollback tests - handleAutoUpdate: handleUpdateFailed/handleUpdateSuccess now read the message from the event payload instead of hardcoding text. Windows deferred users now see the correct "applied after exit" message. - Add standalone-update.test.ts with 4 tests covering rollback scenarios. * fix(cli): address review findings — 5 bugs in standalone-update 1. SHA256SUMS: handle GNU coreutils binary-mode `*` prefix in filename 2. acquireLock: treat NaN (empty/corrupt lock file) as stale, not held 3. tryFetch: consume response body on non-OK status to release sockets 4. Windows bat: add 30s timeout to PID wait loop preventing infinite hang 5. Finally block: clean orphaned .new directory on Windows error path * fix(cli): update handleAutoUpdate tests for payload-driven messages Tests previously asserted hardcoded handler text. After making handlers read messages from event payload, the assertions need to reflect the emitted payload values instead. * feat(cli): auto-migrate npm users to standalone when prefix is not writable When a global npm install requires sudo (prefix not writable), the auto-update now falls back to the standalone path instead of spawning a doomed `npm install -g` that always EACCES. - installationInfo.ts: detect writable prefix with fs.accessSync; return isStandalone=true with fallback dir when not writable - standalone-update.ts: support first-time migration (no existing manifest), detect platform target, create bin wrapper, refuse to overwrite unmanaged directories Closes #4643 * fix(cli): remove unused _mockedAccessSync (TS6133) * fix(cli): address wenshao review — Windows deferred, PATH, rollback, headers - Fix Windows deferred update: move pendingDir cleanup to catch block so it only runs on error, not on successful deferred path - Add ensurePathInShellRc: auto-append ~/.local/bin to shell rc on npm→standalone migration so the wrapper is actually discoverable - Wire rollbackStandaloneUpdate into /doctor rollback subcommand - Add license headers to all 4 new source files - Fix spawnAndCapture double-settle with settled flag - Add tests for ensureBinWrapper and ensurePathInShellRc - Clarify signature verification comments (test key, not production) * fix(cli): add i18n translations for /doctor rollback command The mustTranslateKeys test requires zh-CN and zh-TW translations for all built-in command descriptions. Add translations for the new rollback subcommand and its user-facing messages. * fix(cli): skip Unix-only wrapper tests on Windows The ensureBinWrapper Unix-wrapper test asserts on POSIX file mode bits (mode & 0o111) which Windows NTFS does not implement. Skip Unix-specific tests when running on Windows runners. * fix(cli): address CodeQL + test coverage on standalone-update - Add assertPathWithin() and resolve install paths before spawning the smoke-test process. Closes the CodeQL "shell command built from environment values" finding by guaranteeing nodeBin/cliBin stay inside the freshly extracted install directory. - Add performStandaloneUpdate test coverage for the four pre-flight failure cases (bad version, missing manifest, unknown target, concurrent lock) so the core update path is no longer untested. * fix(cli): address wenshao review round 2 — bat error handling, rollback safety, shell injection, lock race, test coverage Five issues raised in PR #4629 review (2026-06-01): 1. Windows bat: add errorlevel checks after each move, rollback on second-move failure, timestamped log to qwen-update.log 2. Unix rollback: inner try/catch on recovery rename; compound error with manual mv instructions if both renames fail 3. Shell injection: assertSafeForShellEmbed() validates paths before embedding in /bin/sh wrappers and shell rc (platform-aware: allows backslash on Windows) 4. Lock-file race: bat writes .swap sentinel before rename; acquireLock refuses to reclaim stale-PID lock while sentinel exists 5. Test coverage: 4 new handleAutoUpdate standalone-path tests (done, deferred, error, npm-not-entered) + 3 shell-safety rejection tests * fix(cli): prevent symlink attack on staging directory via mkdtempSync Replace fixed-name .qwen-code-update-staging with mkdtempSync random suffix — an attacker who can write to parentDir can no longer pre-create a symlink to hijack recursive deletion. Also adds lstat guard before cleanup rmSync (defense-in-depth) and fixes a potential tempDir leak if mkdtempSync for extractDir fails. * fix(cli): harden standalone-update — download size guard, shell-meta coverage, cleanup logging - Add MAX_DOWNLOAD_BYTES (512 MB) streaming size guard in downloadToFile to prevent resource exhaustion from oversized responses - Extend UNSAFE_SHELL_META_UNIX to also reject semicolon and single-quote - Add debugLogger.warn when extractDir cleanup is skipped (unexpected type) - Add Windows backslash acceptance test for assertSafeForShellEmbed * fix(cli): harden standalone-update — tar preservePaths, timeout signal, shell-rc validation Defense-in-depth improvements from independent code review: - Explicitly set preservePaths:false on tar extract to prevent symlink path traversal - Check err.signal in spawnAndCapture for cross-platform timeout detection - Validate binDir in ensurePathInShellRc independently of calling context * fix(cli): address review round 3 — archive timeout, stderr capture, rollback result type 1. Separate ARCHIVE_TIMEOUT_MS (5 min) from FETCH_TIMEOUT_MS (30s) so large archive downloads on slow networks don't time out prematurely 2. Capture stderr from smoke-test execFile and include it in the error message so users see the actual crash reason (missing lib, etc.) 3. Change rollbackStandaloneUpdate return from boolean to discriminated result type (ok/reason/detail) so doctorCommand shows accurate messages for each failure mode instead of a generic "not found" * fix(test): drop pre-mkdir in shell-safety double-quote test The 'rejects standaloneDir with embedded double-quote' test called fs.mkdirSync on a path containing `"`, which ENOENTs on Windows since NTFS forbids `"` in path components. The validator assertSafeForShellEmbed runs synchronously before any FS access in ensureBinWrapper, so the pre-mkdir was vestigial — removing it makes the test pass on Windows without weakening the assertion. * refactor(standalone-update): remove over-engineered defenses Remove theoretical security mechanisms that solve near-impossible attack scenarios but introduce real complexity and new bug surface: - sentinel mechanism (solves a <2s race window requiring 3 independent low-probability events to align) - assertSafeForShellEmbed + UNSAFE_SHELL_META regexes (default paths are ~/.local/lib/qwen-code, never contain metacharacters) - assertPathWithin (execFile doesn't invoke shell; CodeQL false positive) - lstatSync symlink guard (mkdtempSync random naming already prevents predictable symlink pre-creation) Retains unsafeCmdChars in atomicReplace (bat script interpolation is a real context), bat error handling, archive timeout, and stderr capture. * fix(cli): harden standalone-update error paths and lock release * fix(cli): address multi-model review findings on standalone-update Security: - Preserve per-mirror error details in downloadWithFallback diagnostics - Deduplicate SHA256SUMS.sig download via downloadWithFallback - Upgrade signature-skip log from info to warn with enforcement hint - Add post-extraction path traversal validation for Windows ZIP - Add symlink target validation in tar extraction filter - Add shell metacharacter validation (assertSafeForShellEmbed) for binDir in ensurePathInShellRc and standaloneDir in ensureBinWrapper - Validate cmd.exe metacharacters BEFORE filesystem mutation in atomicReplace Windows path Correctness: - Fix spawnAndCapture treating string error codes as exit 0 - Release lock when mkdtempSync for extractDir fails - Add concurrent lock protection to rollbackStandaloneUpdate - Fix misleading manual-recovery message after auto-recovery succeeds - Fix t() dynamic i18n key — split into translated prefix + raw detail - Reject unsupported architectures in detectTarget instead of silent fallback to linux-x64 Performance: - Compute SHA256 hash during download stream (single-pass), eliminating the second full read of the 50-150 MB archive Quality: - Fix macOS bash shell rc priority (.bash_profile over .bashrc) - Rename npmPrefixDir to npmPackageDir for accuracy - Extract magic number 3 to MAX_MANIFEST_SEARCH_DEPTH constant Tests: - Add rollback concurrent lock protection tests (live + dead PID) - Add fish shell ensurePathInShellRc test - Add shell metacharacter rejection test for ensurePathInShellRc * fix(cli): move shell validation after platform branch in ensureBinWrapper assertSafeForShellEmbed rejects backslashes, which are normal in Windows paths. Move the call into the Unix-only else branch so Windows wrapper creation uses only the cmd.exe metacharacter check. * fix(cli): add post-extraction path validation for Unix tar Matches the Windows zip path's validateExtractedPaths call. The tar filter's string-level path.resolve check cannot detect chained symlink attacks (symlink A → ".", then A/payload → "../../etc"). The post-extraction realpath walk catches these. * fix(cli): fix standalone auto-update reachability and rebase conflicts - Add missing isStandalone/standaloneDir fields to getStandaloneInstallInfo so handleAutoUpdate and /doctor rollback can detect standalone installs - Remove redundant findStandaloneDir (conflicted with stricter detection) - Fix race condition: move mkdirSync after lock acquisition - Ensure parent directory exists before lock file creation - Clean up empty .old directory after first-time npm→standalone migration - Align bash RC file selection with install script (Linux → .bashrc) - Use ?? instead of || for manifest.target fallback - Upgrade ensureBinWrapper failure logging from debug to warn - Add debug logging for SHA256SUMS.sig download failures |