Skip to content

make scanner look for API Key string identifiers in <meta-data> in AndroidManifest.xml

Lots of proprietary libraries require API Keys to work, and one common method for managing those is via <meta-data> items in the AndroidManifest.xml. It is also easy to extract the final, compiled AndroidManifest.xml from the APK, so fdroid scanner should look for these. And this approach works for any programming language, not only Java/Kotlin. For example, Unity, Xamarin, and React often use <meta-data> items. A specific example is fr.maxcom.libmedia.apiKey for this library: https://libeasy.alwaysdata.net/libmedia/apidocs/v2/fr/maxcom/libmedia/Licensing.html

Here are some other examples:

  • com.facebook.sdk.ApplicationId
  • com.prime31.FlurryPlugin
  • com.prime31.GoogleCloudMessagingPlugin
  • com.facebook.versioncontrol.branch
  • io.branch.sdk.BranchKey

This approach is also useful for detecting trackers: trackingthetrackers/wiki#6

There is a list of extracted <meta-data android:name="FOO"> strings under the name metaDataNames here: https://gitlab.com/trackingthetrackers/trackers-clean-feature-vectors/-/blob/master/search_space.json

This script can be hacked to make it easier to scan through all the results:

#!/usr/bin/env python3

import json, os

os.system('ls -l')

# TODO fetch from https://etip.exodus-privacy.eu.org/trackers/export
tracker_names = set()
with open('trackers.json') as fp:
    for tracker in json.load(fp)['trackers']:
        for name in tracker['name'].split():
            tracker_names.add(name.lower())

for k in [
        '-',
        'ad',
        'add',
        'ads',
        'app',
        'and',
        'in',
        'service',
        'channel',
        'platform',
        'sdk',
        'tr',
        'open',
]:
    tracker_names.remove(k)

with open('search_space.json') as fp:
    data = json.load(fp)

print(len(data['apks'][0]['metaDataNames']))
if os.path.exists('end'):
    with open('end') as fp:
        i = int(fp.read())
else:
    i = 0
end = i + 5
display = set()
for name in tracker_names:
    opened_etip = False
    i += 1
    for metadataname in data['apks'][0]['metaDataNames']:
        if name in metadataname.lower():
            display.add(metadataname)
            if not opened_etip:
                os.system('firejail --quiet firefox "https://etip.exodus-privacy.eu.org/admin/trackers/tracker/?q='
                          + name + '"')
                opened_etip = True
            os.system('firejail --quiet firefox "https://duckduckgo.com/?q=%22' + metadataname + '%22"')
    if i > end:
        break

with open('end', 'w') as fp:
    fp.write(str(i))
print(i, sorted(display))
Edited by Hans-Christoph Steiner
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information