Skip to content

Fix path traversal in FileDirectory.getDataColumn (CVE-2026-58460) - #192

Open
actuator wants to merge 1 commit into
ajith-ab:masterfrom
actuator:fix/cve-2026-58460-path-traversal
Open

Fix path traversal in FileDirectory.getDataColumn (CVE-2026-58460)#192
actuator wants to merge 1 commit into
ajith-ab:masterfrom
actuator:fix/cve-2026-58460-path-traversal

Conversation

@actuator

@actuator actuator commented Jul 2, 2026

Copy link
Copy Markdown

_display_name from a shared content:// URI was used verbatim as the destination filename under cacheDir, letting a co-resident app write attacker-controlled bytes outside cache/ (e.g. "../evil.txt"). Route it through sanitizedCacheFile(): basename strip + canonical-path containment in cacheDir; empty/traversal-only names fall back to a generated name.

CVE-2026-58460
VulnCheck: 63ff6452-8dbb-4088-ba4f-681412401c4f

_display_name from a shared content:// URI was used verbatim as the
destination filename under cacheDir, letting a co-resident app write
attacker-controlled bytes outside cache/ (e.g. "../evil.txt"). Route it
through sanitizedCacheFile(): basename strip + canonical-path containment
in cacheDir; empty/traversal-only names fall back to a generated name.

CVE-2026-58460
VulnCheck: 63ff6452-8dbb-4088-ba4f-681412401c4f
@actuator

actuator commented Jul 2, 2026

Copy link
Copy Markdown
Author

Path Traversal in FileDirectory.getDataColumn Leading to Arbitrary File Write

Package: ajith-ab/react-native-receive-sharing-intent (npm: react-native-receive-sharing-intent)
Tested Versions: 2.0.0 (latest npm release, unpatched); vulnerable code introduced in commit 9a7cd4e (2021-05-17), present in current main


Affected Files

  • android/src/main/java/com/reactnativereceivesharingintent/FileDirectory.kt line 104

Root Cause

In FileDirectory.getDataColumn, the library reads the _display_name column from an incoming shared content:// URI and uses it verbatim as the destination filename with no basename strip, canonical-path containment check, or .. rejection:

val fileName = cursor.getString(columnIndex)
targetFile = File(context.cacheDir, fileName)

The taint path is: ReceiveSharingIntentModule.onNewIntent captures the delivered intent; getFileNames reads it and calls FileDirectory.INSTANCE.getAbsolutePath(context, contentUri), which routes content:// and document URIs into getDataColumn; getDataColumn performs the unsanitized write. The library's documented integration requires the consumer to declare an exported activity with ACTION_SEND / SEND_MULTIPLE / VIEW intent filters, making the entry point reachable by any installed app.


PoC

  1. Malicious app exports a ContentProvider whose query() for the _display_name projection returns ../actuator_dirtystream_poc.txt, and whose openFile() returns attacker payload bytes:
<provider android:name=".EvilProvider"
          android:authorities="com.attacker.evil"
          android:exported="true"
          android:grantUriPermissions="true"/>
  1. Malicious app fires an explicit ACTION_SEND at the consumer's exported share-receiver activity, bypassing the chooser:
Intent(Intent.ACTION_SEND).apply {
    setClassName("<consumer.pkg>", "<consumer.activity>")
    type = "*/*"
    putExtra(Intent.EXTRA_STREAM, Uri.parse("content://com.attacker.evil/payload"))
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
  1. The consumer resolves the URI via getDataColumn and copies the payload to File(cacheDir, "../actuator_dirtystream_poc.txt"), landing outside cache/ in the app's private storage.

  2. Verify:

adb shell run-as <consumer.pkg> ls -la /data/user/0/<consumer.pkg>/

Marker file present outside cache/.


Impact

A co-resident app with no permissions and no user interaction can write attacker-controlled bytes to an attacker-chosen path inside the consuming app's private storage, defeating Android inter-app isolation. Consumer-dependent escalation includes integrity compromise (overwriting databases, shared preferences, cached HTML or config), stored XSS if a written file is later rendered in a WebView, DoS by corrupting required files, and code execution on consumers that load executable content from a reachable writable path. The library-level defect is the unsanitized write primitive, making every consuming app independently vulnerable.


Suggested Remediation

Strip to basename before constructing the path (File(fileName).name) and/or enforce canonical-path containment within cacheDir; reject names that reduce to traversal-only.

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.

1 participant