fix(web): isolate untrusted remote content - #6545
Draft
SeniorZhai wants to merge 3 commits into
Draft
Conversation
Restrict wallet bridges to the reviewed HTTPS origin and block mixed content. Reject unsafe app-card cover targets and avoid fetches during save or share. Leave the app-wide cleartext network policy unchanged.
Contributor
There was a problem hiding this comment.
Pull request overview
Hardens embedded web content and app-card media handling against untrusted origins and network targets.
Changes:
- Restricts injectable WebViews to HTTPS origins and blocks mixed content.
- Validates app-card cover URLs before display.
- Makes app-card save/share operations cache-only.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
app/src/test/java/one/mixin/android/vo/AppCardDataTest.kt |
Adds cover URL validation tests. |
app/src/main/java/one/mixin/android/vo/AppCardData.kt |
Introduces app-card image URL filtering. |
app/src/main/java/one/mixin/android/ui/web/WebFragment.kt |
Adds WebView origin restrictions and bridge gating. |
app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt |
Resolves app-card images only from disk cache. |
app/src/main/java/one/mixin/android/ui/conversation/holder/AppCard.kt |
Filters cover URLs before rendering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Filter every DNS result and verify the connected route for image requests, including redirects. Disable proxies for the image client so target resolution cannot bypass the public-address policy. Cover IPv6 ULA and reserved ranges.
Block untrusted subframe requests without launching the system browser. Track redirects and external navigation only for main-frame requests.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
app/src/main/java/one/mixin/android/util/image/ImageNetworkPolicy.kt:66
- This condition blocks the entire
192.0.0.0/16, not just the non-public special-purpose ranges inside it. Globally routable hosts in that /16 (for example,192.0.66.0/24) will therefore fail every Coil image request now that this policy is installed app-wide. Narrow this check to the actual reserved prefixes (and preserve the globally reachable exceptions in192.0.0.0/24).
bytes[0] == 192 && bytes[1] == 0 ||
app/src/main/java/one/mixin/android/util/image/ImageNetworkPolicy.kt:39
- The HTTPS check is only applied to the original app-card URL. OkHttp follows HTTPS-to-HTTP redirects by default, and this interceptor validates only the connected address, so an accepted cover can still be fetched over cleartext after a redirect. Revalidate the scheme on redirect requests (without blocking unrelated direct HTTP image loads, which the PR says remain supported).
private object PublicImageNetworkInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val address = chain.connection()?.route()?.socketAddress?.address
if (address == null || address.isBlockedImageAddress()) {
throw IOException("Blocked non-public image target")
}
return chain.proceed(chain.request())
app/src/main/java/one/mixin/android/ui/media/pager/MediaPagerActivity.kt:471
- This returns the disk-cache backing file after
usehas closed the snapshot. Once the snapshot is closed, Coil may evict or replace that entry; save copies it shortly afterward, but sharing hands the URI to another app that may open it much later, so the share can fail if the cache changes. Copy the cached bytes to a stable temporary file while the snapshot is open and return that copy.
imageLoader.diskCache?.openSnapshot(coverUrl)?.use { snapshot ->
snapshot.data.toFile()
}
Comment on lines
+1043
to
+1046
| }, | ||
| ), | ||
| "_mw_", | ||
| ) |
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.
What changed
Why
Wallet bridges could remain available after cross-origin navigation, and the asset-origin check always evaluated true. App-card cover URLs could also trigger requests to local or private targets during rendering or save/share.
Impact
Cross-origin links open in the system browser. Unsafe app-card covers are ignored, and uncached covers cannot be saved or shared. The existing app-wide cleartext/HTTP network policy is unchanged.
Validation
./gradlew --no-configuration-cache :app:testGooglePlayDebugUnitTest --tests one.mixin.android.vo.AppCardDataTest./gradlew --no-configuration-cache :app:compileGooglePlayDebugKotlin