Skip to content

Port MASTG-TEST-0028: Testing for Testing Deep Links (android) (by @appknox) - #3463

Closed
ScreaMy7 wants to merge 18 commits into
OWASP:masterfrom
ScreaMy7:Testing-deeplink-draft
Closed

Port MASTG-TEST-0028: Testing for Testing Deep Links (android) (by @appknox)#3463
ScreaMy7 wants to merge 18 commits into
OWASP:masterfrom
ScreaMy7:Testing-deeplink-draft

Conversation

@ScreaMy7

Copy link
Copy Markdown
Collaborator

closes #2980

Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXA.md Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ScreaMy7 ⚠️ PLEASE BE CAREFUL:

I see that a lot of the information contained in this test is being lost right now. Please consider porting it all:

  • What information is knowledge and belongs in https://mas.owasp.org/MASTG/knowledge/android/MASVS-PLATFORM/MASTG-KNOW-0019/
  • What information describes best practices and should be added to a new MASTG-BEST-XXXX? (each test should have at least one best practice linked)
  • What techniques are here that don't have a MASTG-TECH-XXXX entry? e.g.
    • "Check for Deep Link Usage"
    • "Check for Correct Website Association"
    • "Monitoring Deep Links"
    • "Invoking Deep Links"
    • etc
  • What tools are used and don't have a MASTG-TOOL-XXXX entry? e.g. "Android App Link Verification Tester"
  • What tests are missing?
    • "Use of Unverified App Links"
    • "Use of Unverified Custom URL Schemes"
    • "Use of Verified App Links with Incorrect Website Association"

@@ -0,0 +1,24 @@
---
title: Deep Link Intent Filter Missing android:autoVerify

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be "Use of Unverified App Links" plus an additional "Use of Unverified Custom URL Schemes" which is now missing.

@cpholguera

Copy link
Copy Markdown
Collaborator

Also please use "fake IDs" (e.g. MASTG-TEST-0x28-1, MASTG-TEST-0x28-2, MASTG-DEMO-00xx-1, MASTG-DEMO-00xx-2) until we're ready to merge, to avoid conflicts.

@cpholguera cpholguera changed the title MASTG v1->v2 MASTG-TEST-0028: Testing for Testing Deep Links (android) (by @appknox) Port MASTG-TEST-0028: Testing for Testing Deep Links (android) (by @appknox) Oct 28, 2025
@cpholguera
cpholguera requested a review from serek8 November 7, 2025 11:08
@cpholguera

Copy link
Copy Markdown
Collaborator

@ScreaMy7 any news on this?

@ScreaMy7

ScreaMy7 commented Dec 8, 2025

Copy link
Copy Markdown
Collaborator Author

@cpholguera I have added new demos, a tool and the new technique also contain invoking and monitoring deeplinks. Please review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports MASTG-TEST-0028 (Testing Deep Links on Android) from the legacy format to MASTG V2 structure. It deprecates the old test and creates three new focused tests covering different deep link security aspects, along with comprehensive supporting documentation.

  • Creates three new deep link security tests (MASTG-TEST-XXXA, MASTG-TEST-XXXB, MASTG-TEST-0295) covering WebView URL validation, autoVerify attribute, and custom URL schemes
  • Adds new technique document (MASTG-TECH-XXXX) with detailed procedures for deep link testing including verification, monitoring, and invocation
  • Provides three complete demos with Semgrep rules, sample code, and expected outputs

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 26 comments.

Show a summary per file
File Description
tests/android/MASVS-PLATFORM/MASTG-TEST-0028.md Marks the legacy test as deprecated with references to new replacement tests
tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXA.md New test for detecting unvalidated deep link URLs loaded into WebViews
tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXB.md New test for detecting missing android:autoVerify attribute in intent filters
tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXC.md New test (ID: MASTG-TEST-0295) for detecting use of unverified custom URL schemes
techniques/android/MASTG-TECH-XXXX.md Comprehensive technique document covering deep link detection, validation, monitoring, and invocation
tools/android/MASTG-TOOL-014X.md Documents the App Link Verification command-line tool
rules/mastg-android-unvalidated-deeplink-data.yml Semgrep taint rule for detecting unvalidated deep link data flows to WebView
rules/mastg-android-custom-deeplink-scheme.yml Semgrep rule for detecting custom URL schemes in intent filters
rules/mastg-android-autoverify-missing.yml Semgrep rule for detecting missing autoVerify attribute
demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXA/* Complete demo for WebView deep link vulnerability with Kotlin source, reversed Java, manifest, and Semgrep output
demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXB/* Complete demo for missing autoVerify attribute with manifest and Semgrep output
demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXC/* Complete demo for custom URL scheme vulnerability with Kotlin source, reversed Java, manifest, and Semgrep output

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXB.md Outdated
Comment thread techniques/android/MASTG-TECH-XXXX.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXC/MASTG-DEMO-XXXC.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXB/MASTG-DEMO-XXXB.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXB/MASTG-DEMO-XXXB.md Outdated
Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXA.md Outdated
Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXA.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXC/MASTG-DEMO-XXXC.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXB/MASTG-DEMO-XXXB.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXA/MASTG-DEMO-XXXA.md Outdated

## Steps

1. Run a static analysis tool such as @MASTG-TOOL-0110 on the `AndroidManifest.xml` to list the `VIEW/BROWSABLE` intent-filters declaring non-HTTP(S) schemes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No tools in tests.

Correct words "intent filter".


## Evaluation

The test fails if the app relies on custom URL schemes for high-risk operations that should use verified App Links (HTTPS) with Digital Asset Links. Mitigations include migrating to App Links for exclusivity or implementing robust in-app validation and user confirmation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No mitigations in tests. Add best-practices in the metadata.

status: new
---

### Overview

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Demos don't have an Overview section

Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXC/MASTG-DEMO-XXXC.md Outdated
@cpholguera

Copy link
Copy Markdown
Collaborator

@ScreaMy7 please take a look. There are review comments from December and today.

@ScreaMy7
ScreaMy7 requested a review from cpholguera February 9, 2026 10:22
@ScreaMy7

ScreaMy7 commented Feb 9, 2026

Copy link
Copy Markdown
Collaborator Author

@cpholguera I have added the changes. Please review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 32 comments.

Comment thread tools/android/MASTG-TOOL-0x01.md
Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-0x01.md
Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXC.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-0x03/MASTG-DEMO-0x03.md
Comment thread rules/mastg-android-autoverify-missing.yml
Comment thread rules/mastg-android-custom-deeplink-scheme.yml
Comment thread techniques/android/MASTG-TECH-0x01.md
Comment thread tests-beta/android/MASVS-PLATFORM/MASTG-TEST-XXXC.md Outdated
Comment thread demos/android/MASVS-PLATFORM/MASTG-DEMO-XXXB/run.sh Outdated

@serek8 serek8 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for contributing! I have a couple of remarks:

  • Can you link MASTG-KNOW-0019 knowledge page and add some missing parts from the old test:
    • the change in Android 12 that impacts non-verifiable (We had it in the old test)
    • the reports from the hackerone, they are very illustrative
  • Can you add a Best Practise page and guide the user to use App Links and explain why

Additionally: Not a must for this PR. We can create a new issue for it. Currently we only test receiving the deep links in the app. I think we could also create some best practices on how to invoke app links. I didn't give it much thought yet but maybe the payload could be encrytpted so it can't leak sensitive data and only the legit app/website can decrypt it. Or maybe we can somehow else ensure that the URL won't be hijacked by another app and goes directly to the expected app or website?


The Android version the app runs on also influences the risk. Before Android 12 (API level 31), if the app has any [non-verifiable links](https://developer.android.com/training/app-links/verify-android-applinks#fix-errors) (e.g., missing `autoVerify`, invalid Digital Asset Links file, or custom URL schemes), the system may skip verification for all Android App Links declared by that app—leaving even correctly configured App Links unprotected. Starting with Android 12 (API level 31), a generic web intent resolves to the user's default browser unless the target app is approved for the specific domain, reducing but not eliminating the attack surface.

This vulnerability occurs when a deep link intent filter in `AndroidManifest.xml` lacks the `android:autoVerify="true"` attribute. Without verification, Android cannot confirm the app's ownership of the declared domain. A malicious app could register the same intent filter and intercept deep links, enabling phishing, credential theft, or hijacking of user actions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not an expert in App Links but this got me curious:

A malicious app could register the same intent filter and intercept deep links, enabling phishing, credential theft, or hijacking of user actions.

So on Android 11, if my legit app has autoVerify="true" but my server returns 404 for the verification, my app won't receive events for this link. But a malicious app with autoVerify="false" will receive these events instead? Or you mean that the system will open "Open with..." dialog and a user can choose a malicious app there? Or both scenarios are possible?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a legitimate app has autoVerify="true" but verification fails (404), that domain becomes "unverified" for your app. So it falls back to acting like a regular deep link handle. A malicious app with
autoVerify="false" can then intercept those links because both apps are now considered equally "unverified" for that domain. I tested this scenario on Android 12, I received the "Open with" dialog box.

@@ -0,0 +1,25 @@
---
title: Use of Unverified Custom URL Schemes

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't Custom URL Schemes always Unverified? Only AppLinks can be Verified / Non Verified, no? I believe we want to detect use of any Custom URL Schemes because they are fundamentally insecure?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then maybe we should name this test "Use of Custom URL Schemes"?

@@ -0,0 +1,25 @@
---
title: Use of Unverified Custom URL Schemes

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title: Use of Unverified Custom URL Schemes
title: Use of Custom URL Schemes

@ScreaMy7

Copy link
Copy Markdown
Collaborator Author

Hi, @serek8 is there any other blocker for this PR, I have added the title change as suggested.

@serek8 serek8 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I briefly had a look and found cosmetic some issues. I still need to run the DEMOs myself

<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also cover <data android:scheme="http" />?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, app Links apply to both http and https. I'll update the rule to catch both schemes.

@@ -0,0 +1,11 @@
rules:
- id: mastg-android-custom-deeplink-intent-filter

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ID doesn't match filename

Suggested change
- id: mastg-android-custom-deeplink-intent-filter
- id: mastg-android-custom-deeplink-scheme

└────────────────┘

AndroidManifest_reversed.xml
❯❱ android-custom-deeplink-intent-filter

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ID doesn't match

Suggested change
❯❱ android-custom-deeplink-intent-filter
❯❱ mastg-android-custom-deeplink-scheme

Comment on lines +14 to +20
- pattern: |
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="..." />
</intent-filter>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we worry about this one @ScreaMy7

@ScreaMy7

Copy link
Copy Markdown
Collaborator Author

Thanks @serek8 for review addressed all three changes, added http to demo and rule is also updated.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This demo doesn't work. Nothing happens when running the adb command.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me check.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Demos must be fully functional. In this case, the link should perform an action so that we can demonstrate how any app can trigger that sensitive action due to a lack of verification.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. The demo was manifest-only with no runtime action so I have added App Link and that performs a sensitive action.

ScreaMy7 added 2 commits June 21, 2026 21:31
The demo's vulnerable sink processDeepLinkAndLoad() was never invoked:
the vulnerable-app://deeplink VIEW filter sat on MainActivity, which
only reads intent data via the Start button and ignores the launch
intent, so `adb shell am start ... VIEW` did nothing.

Route the deep link to a dedicated exported DeepLinkActivity whose
onCreate reads intent.data and calls processDeepLinkAndLoad(), loading
the attacker-controlled url into the WebView. Verified on a physical
device: the adb command now renders the URL in the WebView.

Regenerated MastgTest_reversed.java and AndroidManifest_reversed.xml via
tools/extract-code-for-mastg-demo.sh. The getQueryParameter -> loadUrl
data flow is unchanged, so the semgrep finding in output.txt still holds.
…nverified App Link

Addresses review feedback (r3448625913): demos must be fully functional,
and the link should perform an action demonstrating how an unverified App
Link can be triggered by any app.

Previously DEMO-0x02 was manifest-only: it documented the missing
android:autoVerify but never demonstrated the consequence, and the filter
sat on MainActivity (which ignores the launch intent), so the link did
nothing at runtime.

Add MastgTest.kt with an exported DeepLinkActivity that handles the
http(s)://deeplink.example.com App Link (registered WITHOUT
android:autoVerify) and performs a sensitive action - disabling two-factor
authentication - with no verification or user confirmation. The App Link
filter is moved from MainActivity to DeepLinkActivity; MainActivity keeps
the LAUNCHER filter.

Regenerated AndroidManifest_reversed.xml and MastgTest_reversed.java via
tools/extract-code-for-mastg-demo.sh and refreshed output.txt by running
run.sh; the autoVerify-missing semgrep finding still holds. Documented the
adb trigger command in the Evaluation.

Verified on a physical device: opening the link stores
two_factor_enabled=false (set_by=deeplink), confirming the sensitive
action fires.
@ScreaMy7
ScreaMy7 force-pushed the Testing-deeplink-draft branch from d2b4d08 to cfda51e Compare June 21, 2026 16:06

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule appears to be too brittle for MASTG coverage. It assumes a specific child order inside the intent filter, VIEW, then DEFAULT, then BROWSABLE, then data. That means it can miss valid manifests where the same elements are present but ordered differently. It also requires DEFAULT, so any app that omits that category is excluded entirely.

Since MASTG rules are meant to work against arbitrary real world apps, the rule should not depend on manifest element ordering unless ordering is semantically required. In this case, the current pattern can produce false negatives for structurally equivalent intent filters, which goes against the intended coverage goals.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule is brittle because it relies on a raw regex over the manifest text rather than XML semantics. It only matches a literal <intent-filter> opening tag, so it can miss valid filters with attributes, whitespace, or formatting differences, such as <intent-filter android:autoVerify="true"> or <intent-filter >.

It also only matches double quoted android:scheme values, even though XML allows single quoted attributes. Since the rule is not XML aware, it can also match text in comments or otherwise behave unexpectedly across formatting edge cases.

@cpholguera

Copy link
Copy Markdown
Collaborator

@ScreaMy7 Thank you for the contribution and for the effort you’ve put into this PR.

Due to the complexity of the changes, including demos that do not work as expected or are not fully functional, a brittle Semgrep rule, a large number of unaddressed comments, and the fact that the actual risks are not properly represented in the tests and demos, we had to work on a separate branch and PR for this port. We will move forward with that PR, so we will close this one.

#3897

Thanks again for your work and for addressing some of the comments over the last couple of hours. However, in order to transition to MASTG v2 before the MAScon, our current goal, we need a fully compliant PR. Your feedback will be appreciated over there.

The OWASP MAS team.

@cpholguera cpholguera closed this Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MASTG v1->v2 MASTG-TEST-0028: Testing Deep Links (android)

4 participants