Skip to content

fix(security): prevent credential leak via external compose intent - #3089

Merged
tevincent merged 6 commits into
mainfrom
fix-intent-credential-leak
Oct 2, 2026
Merged

tevincent merged 6 commits into
mainfrom
fix-intent-credential-leak

Conversation

@FabianDevel

@FabianDevel FabianDevel commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

An external webpage or app could craft a browsable or external intent: launching NewMessageActivity with arrivedFromExistingDraft=true and a malicious draftResource (such as @attacker.example/capture). When fetchDraft() was invoked, raw URL concatenation in ApiRoutes.resource() caused OkHttp to resolve the effective host to the attacker endpoint while attaching the user's Authorization: Bearer token.

Changes

  • Exported Trampoline Isolation: Made NewMessageActivity non-exported (android:exported="false"), preventing external apps and browsers from directly targeting it or injecting internal navigation extras. Moved external compose intent filters (VIEW/SENDTO for mailto:, SEND/SEND_MULTIPLE) to a dedicated exported ExternalComposeActivity trampoline that forwards only safe, allowlisted compose data (EXTRA_EMAIL, EXTRA_SUBJECT, EXTRA_TEXT, EXTRA_STREAM, etc.).
  • ViewModel Defense: In NewMessageViewModel.fetchDraft(), validate that draftResource is a relative path starting with / before querying the repository.
  • Origin Validation: In ApiRoutes.resource() and rescheduleDraft(), enforce relative paths starting with / (disallowing // and /\\) and verify that the resolved URL matches the Infomaniak Mail API host, scheme, and has no userinfo.
  • Unit Tests: Added ApiRoutesTest covering valid relative paths, userinfo injection attempts, scheme-relative URLs, and absolute URLs.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Exported activity callers can bypass action-based external-intent detection using an arbitrary or null action.

Review effort: Balanced
Findings: 2 High severity · 1 Low severity

Open (3)
What changed in this PR

Hardens compose-intent handling and API resource URL construction against credential leakage.

Changes:

  • Sanitizes external compose intents and forces new-message mode.
  • Validates API resource URLs against the Mail API origin.
  • Adds malicious URL regression tests.
File Description
ApiRoutes.kt Validates resource URLs and draft scheduling routes.
NewMessageActivity.kt Removes internal extras from recognized external intents.
NewMessageViewModel.kt Adds intent and draft-resource safeguards.
ApiRoutesTest.kt Tests accepted and rejected resource paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageActivity.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The security-critical trampoline lacks regression coverage for its allowlist and URI forwarding.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (3)

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/ExternalComposeActivity.kt Outdated
@FabianDevel
FabianDevel force-pushed the fix-intent-credential-leak branch 2 times, most recently from 60d1ca0 to 04df191 Compare October 1, 2026 13:13
@FabianDevel
FabianDevel marked this pull request as ready for review October 1, 2026 13:14
Comment thread app/src/main/java/com/infomaniak/mail/data/api/ApiRoutes.kt Outdated
@FabianDevel
FabianDevel force-pushed the fix-intent-credential-leak branch from 04df191 to de49e32 Compare October 2, 2026 06:38
@FabianDevel
FabianDevel force-pushed the fix-intent-credential-leak branch from de49e32 to 1cd7846 Compare October 2, 2026 06:39
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@tevincent
tevincent merged commit ff85e45 into main Oct 2, 2026
10 checks passed
@tevincent
tevincent deleted the fix-intent-credential-leak branch October 2, 2026 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants