Add confirm=true import gated by trusted caller (adb/shell-only) - #3073
Draft
djbclark wants to merge 3 commits into
Draft
Add confirm=true import gated by trusted caller (adb/shell-only)#3073djbclark wants to merge 3 commits into
djbclark wants to merge 3 commits into
Conversation
obtainium://update/all?autoInstall=true&headless=true obtainium://update?appId=id1,id2&silentOnly=true obtainium://settings/installer?mode=shizuku&headless=true obtainium://settings/background?enabled=true&wifiOnly=true obtainium://settings/updates?interval=720&checkOnStart=true The maybeExit() helper reads the headless/exit query param and calls SystemNavigator.pop() after a short delay, enabling fully automated workflows via Tasker, MacroDroid, ADB, or browser links.
Adds markTrustedIfPrivileged() which checks Activity.referrer. A null referrer means the intent came from am start (ADB shell) or the system — not from a browser or third-party app. In that case confirmedBy=system is appended to the URI so the Dart side can distinguish trusted launches from browser-based phishing links.
obtainium://apps/<json>?confirm=true&headless=true confirm=true only takes effect when the intent came from a privileged caller (ADB shell / am start), detected via Activity.referrer == null in MainActivity.kt. Browser and third-party app links always set a non-null referrer, so phishing links with ?confirm=true are ignored and the confirmation dialog still appears. The importHeadless param works independently — it exits after import regardless of confirm=true, relying on PR 1's maybeExit() helper.
djbclark
added a commit
to djbclark/Obtainium
that referenced
this pull request
Jul 14, 2026
Requires confirmedBy=system marker (set by MainActivity.kt when Activity.referrer == null, i.e. ADB/shell launch) for confirm=true to take effect. Browser phishing links can't fabricate this marker. docs: update HANDOFF.md with PR ImranR98#3071 and ImranR98#3073 status
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.
This PR adds an optional
confirm=trueparameter to theobtainium://apps/<json>deep-link that skips the import confirmationdialog — but only when the intent came from a trusted caller (ADB/shell).
Usage
adb shell am start -d "obtainium://apps/<json>?confirm=true&headless=true"When
confirm=trueis present and the caller is trusted, the catalog isimported immediately. When combined with
headless=true(from #3071),the app exits after import.
Security model
confirm=trueonly takes effect when the intent was launched from aprivileged caller, detected via
Activity.referrer == nullinMainActivity.kt. A null referrer means the ActivityManager launchedthe activity directly (e.g.
adb shell am start) — regular apps andbrowsers always set a non-null referrer that identifies the calling app.
When the caller IS privileged,
MainActivity.ktappendsconfirmedBy=systemto the URI before Flutter processes it. The Dartside checks for this marker — a phishing link with
?confirm=truealone won't bypass the dialog since it can't fabricate the
confirmedBy=systemparameter.Changes
MainActivity.kt:markTrustedIfPrivileged()checks referrer andappends
confirmedBy=systemfor ADB/shell launcheshome.dart:confirm=trueis honored only whenconfirmedBy=systemis presentDependency
Depends on #3071 for the
maybeExit()helper used in the headlessexit path.