fix(reinstall-app): validate the artifact before uninstalling anything - #674
Open
filip131311 wants to merge 2 commits into
Open
fix(reinstall-app): validate the artifact before uninstalling anything#674filip131311 wants to merge 2 commits into
filip131311 wants to merge 2 commits into
Conversation
reinstall-app uninstalls unconditionally and only then hands the path to the installer, so a bad artifact left the device with no copy of the app — and the uninstall takes the app's data with it, with no way back. Reproduced on the released build: passing an existing non-APK made adb reject it on a filename check, and the package was gone. All four platform impls now check the artifact first, while the current installation is still on the device. Everything checked is a local stat or a four-byte read; nothing touches the device. iOS wants a directory ending .app with an Info.plist at its root — which also rejects a macOS bundle, since those keep it under Contents/. Android wants a file ending .apk or .apex that starts with a zip header, enough to catch a renamed text file or a truncated build output. Vega wants a .vpkg file; its container format is not documented here, so guessing a signature would risk rejecting valid packages. The extension test is case-insensitive because adb's is: UPPER.APK installs fine, so a stricter rule would reject artifacts that work today. iOS also refuses a path inside the target simulator's own container. That is the reported iOS case and the one place where validation alone is not enough to notice: the path exists and looks like a real bundle, but the uninstall deletes the container it lives in, so the install then fails on a path that no longer exists. Checked against the default set and every configured additional set, because deviceSetForUdid returns null both for the default set and for a UDID it has not seen. ios-remote gets the structural checks but not the container check — the simulator is on another host, so the local CoreSimulator layout says nothing about it. What this does not fix: a device rejecting a well-formed artifact. Wrong ABI, a minimum OS version, a signature mismatch or a test-only APK all still fail after the uninstall, and the app is still gone. The tool exists to clear app data, so no amount of validation can promise to preserve it. The description now says both halves of that.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #625. This is the one issue in the sweep that destroys user state, so the PR body is explicit about what it does and does not cover.
Reproduced on the released build
adbrejected the file on a filename check — the cheapest validation there is — but argent had already uninstalled the app, and the uninstall takes the app's data with it. All four platform impls share the shape: resolve → uninstall (swallowed) → install, with nothing checked in between. The tool's own description already promised the opposite.The fix
Each platform now validates while the current installation is still on the device. Everything is a local
stator a 4-byte read — nothing touches the device..app;Info.plistat the root (which also rejects a macOS bundle, since those nest it underContents/).apk/.apex; starts with a zip header — catches a renamed text file or a truncated build output.vpkg— no magic check, the container format isn't documented here and guessing a signature risks rejecting valid packagesThe extension test is case-insensitive, because adb's is. I verified this:
UPPER.APKinstalls fine. A stricter rule would have rejected artifacts that work today — worth calling out, since "match adb exactly" invites the opposite assumption.iOS also refuses a path inside the target simulator's own container. That's the reported iOS case and the one place validation alone can't see the problem: the path exists and is a real bundle, but the uninstall deletes the container it lives in, so the install then fails on a path that no longer exists. Checked against the default set and every configured additional set, because
deviceSetForUdidreturnsnullboth for "the default set" and for a UDID it hasn't seen.ios-remotegets the structural checks but not the container check — the simulator is on another host, so the local CoreSimulator layout says nothing about it.Live, after the fix — same call that destroyed the app:
What this does NOT fix — stated plainly
A device rejecting a well-formed artifact still destroys the installation: wrong ABI,
minSdkVersion, signature mismatch, a device-slice.app, a valid zip whose contents are corrupt.I hit one of these by accident while verifying, on a genuine artifact: reinstalling argent's own helper APK failed with
INSTALL_FAILED_TEST_ONLY(argent never passesadb install -t) — validation correctly passed, the device refused, and the app was gone. That is the honest residual.And no fix can promise data preservation: the tool exists to clear app data, so the previous state is unrecoverable by design. The description now says both halves.
The stronger fix, measured and deliberately deferred
The destructive window can be closed entirely by reordering, and I measured that it works:
adb install -rover an existing install → Success, no uninstall neededinstall -r→ app and data fully intactpm clear→ wipes data, app stays installedSo Android could be
install -r→pm clear: no destructive window, and one install instead of today's uninstall+install. iOS behaves the same way (simctl installover an existing install preserves the container).I'm not shipping it here because it changes the mechanism, not just the ordering:
pm clearrevokes runtime permissions where-ggrants them, it needs a fallback forINSTALL_FAILED_UPDATE_INCOMPATIBLE(a signature mismatch — common with debug vs release keystores), andios-remoteshouldn't reorder at all since a double install doubles a network upload. That deserves its own review rather than riding on a validation fix. Filed as a follow-up with the measurements.Checks
vega-reinstall-result.test.tsneeded a real temp.vpkg: it used/tmp/app.vpkg, which doesn't exist, so validation correctly rejected it..APKis still accepted.