4.4 KiB
FAIL
Ran cargo test -p ely-platform (all pass) and cargo clippy -p ely-platform --all-targets (clean). Probes A–C ran against a local server in a scratch crate that depends on ely-platform.
-
crates/ely-platform/src/update.rs:221-230: The rule "https only, loopback excepted" can be bypassed with userinfo. The code checks the URL by string prefix, and
"http://127.0.0.1:" + anythingpasses. ureq treats127.0.0.1:1@as userinfo and connects to the host after@. Scenario (probe B):check(.., "http://127.0.0.1:1@192.168.31.221:PORT/latest.json")returnedOk(Available(..)). The server loggedhost: 192.168.31.221, so the manifest came over plain http from a non-loopback host. Whoever controls the network then picks the URL and the sha256, and the downloaded file passes verification.plain_http_is_for_this_machine_onlydoes not cover this case. Fix: parse the URL withhttp::Uriorureq::http::Uri, reject userinfo, and decide by scheme plus the parsed host. Add the userinfo case to the test. -
crates/ely-platform/src/update.rs:77, 232-246:
ensure_securechecks only the first URL. Both agents use ureq's defaults (max_redirects10,https_onlyfalse), so redirects tohttp://are followed for the manifest and for the download. Scenario (probe A):http://127.0.0.1:P/redirectanswered 302 tohttp://192.168.31.221:P/latest.json.checkfollowed it and returnedAvailable. Anhttps://manifest URL that redirects tohttp://is followed the same way, so the manifest arrives over plain http. Fix: check every hop. Either turn redirects off (max_redirects(0)) and followLocationmanually throughensure_secure, or usehttps_only(true)for non-loopback URLs. Add a test where a redirect leaves loopback. -
crates/ely-platform/src/update.rs:175-180, 239-246: The comment "the user can cancel" is not true. The download agent has no read timeout, and the cancel flag is checked only between
readcalls. A stalled connection blocksreadforever: cancel does nothing, and no error is ever returned. Scenario (probe C): the server sent the headers and 1000 of 1000000 bytes, then went silent. I setcancelto true 1 s in.downloadwas still blocked 19 s later. In the field, a dropped Wi-Fi link or a hung CDN leaves the download hung for good. Fix: put an idle-read timeout on the socket (for example a custom connector or transport withset_read_timeout) so thatreadreturns,cancelis honoured, and a stall becomes an error. Add a test with a stalled server. -
crates/ely-platform/src/update.rs:62, 66-73:
APPIMAGEis an inherited environment variable, and it overrides the package-manager prefixes. A distro-installed binary launched from inside any AppImage is treated asSelfManaged. Scenario: the user starts a terminal emulator or editor that ships as an AppImage, then runs/usr/bin/ely-doc(installed by pacman) from its terminal.APPIMAGEis set, soinstall_policy()returnsSelfManagedand the app would update itself over files the package manager owns. This breaks PRD §4.2 ("Linux 包管理器安装的版本不绕过包管理器自行覆盖文件"). Fix: count it as an AppImage only whencurrent_exelies under$APPDIR(the mount of this AppImage), not just becauseAPPIMAGEexists. Cover the inherited-variable case in the unit test. -
crates/ely-platform/src/update.rs:142-147: The download's own error is lost when removing the
.partfile fails, because the?onremove_filereturns the removal error instead. Scenario: the hash does not match, and on Windows an antivirus scanner still holdsElyDoc.exe.part. The caller sees "cannot remove …part", and "the file has sha256 X, the release says Y" never reaches the user. Fix: keep the original error and attach the removal failure to it, or log the removal failure and still return the original error. -
crates/ely-platform/src/update.rs:76-102, 138-141: Rule 4 (key paths are logged) is not met.
checkmakes a network request and logs neither the request nor the outcome (current, available, or which failure). A cancelled download is not logged either. Only a successful download logs anything. Scenario: QA-25 asks for an audit of outgoing update requests, and a user reports "check for updates does nothing". The log has no line showing a check was made or what it returned. Fix: log the manifest host and the result incheck, and log a cancelled download (version only, no secrets).