Skip to content

APKRadar 2026.45

Latest

Choose a tag to compare

@github-actions github-actions released this 10 Oct 09:20
· 3 commits to main since this release
v2026.45
64e757f

Fixed

  • A manifest component whose class is not in the DEX is no longer a tracker, nor a
    transfer.
    Fennec 157.0.0 as F-Droid builds it (org.mozilla.fennec_fdroid 1570020,
    SHA-256 04a5f4d3…47a9) declares com.adjust.sdk.AdjustPreinstallReferrerReceiver
    and holds no class under com.adjust in any of its three DEX files: the build is made
    without the Adjust SDK and the manifest keeps the receiver. The audit reported "Adjust"
    and a transfer to "Adjust GmbH (Germany) → USA", and the DPO letter would have put both
    in front of Mozilla — an allegation about code that is not in the file. Declared
    components are now confirmed against the DEX (Lcom/adjust/sdk/Adjust…Receiver;,
    the whole descriptor) before they count; an APK with no readable code is still read on
    the manifest's word, since "nothing to check against" is not "confirmed absent".
    tests/test_declared_without_code.py holds the manifest excerpt as a real APK.
  • --full no longer audits every deep-link host of an app that opens other sites'
    links.
    OsmAnd~ 5.4.9 (net.osmand.plus 540903) declares 427 deep-link hosts —
    maps.google.com and some 200 Google country domains, map.baidu.com, maps.yandex.ru,
    here.com, maps.apple.com — because it opens links to other maps; NewPipe 0.29.1 declares
    56 for YouTube, SoundCloud, Bandcamp and PeerTube instances. Each was taken as "SDK or
    deep-link domain found in the APK" and queued for MailRadar, a TLS handshake and a
    headless browser: on OsmAnd about three and a half hours, at the ~30 s per domain
    measured on Mastodon the same day, of traffic to Google, Baidu and Yandex about an app
    that talks to none of them. Above MAX_DEEP_LINK_DOMAINS (10; the most a publisher was
    seen declaring for itself is F-Droid's four) no deep-link host is audited, the report
    says how many were set aside and why, and the hosts stay in ScanResult.manifest_domains
    as data. tests/test_deep_links_cap.py holds 24 of OsmAnd's hosts as a real APK.
  • Namespace URIs and RFC 2606 names are references, not endpoints — and not vendors.
    Measured on 2026-10-09: ExoPlayer's PlayReady code carries
    http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense, the SOAPAction of a
    licence request, and the hosts block listed it under "a vendor this tool reports on" as
    Microsoft Corporation (USA) on Nextcloud 35.0.1, AntennaPod 3.12.2, NewPipe 0.29.1 and
    Fennec 157.0.0 alike — none of which talks to Microsoft, and a reader takes that table
    for a transfer. ns.adobe.com (the XMP namespace), xml.org and
    javax.xml.XMLConstants (parser feature names) and spdx.org (licence identifiers)
    join the reference list for the same reason. So do the names RFC 2606 reserves for
    documentation: F-Droid 2.0.1 carries https://mirror.example.com/fdroid/repo as a
    sample address, and example.com, example.net, example.org, three mirror.example.* and
    dummy.example were listed as endpoints the code can reach. They resolve to nothing and
    belong to nobody. All of them stay in the list, under "references", as the block has
    always done with a specification URI. tests/test_hosts_identifiers.py holds the
    literals as they appear in those DEX files.
  • A batch-excel row that was not analysed keeps its name and shows no counts.
    Measured on 2026-10-09 with a registry of eleven F-Droid APKs and one row naming an app
    whose file was not there: the report wrote that row as None | None | APK | … | N/A | 0 | 0 | 0. The name and package the registry gave it were gone — a scan that could not open
    the file knows neither, and the row was built from the result rather than from the
    registry — so the one line a reader most needs to identify was the one that could not
    be. "APK" was the dataclass default, not a reading of the file, and three zeros in the
    columns that get summed and charted said the file had been found to hold nothing, when
    it had not been found. The score cell was already blank for exactly that reason; the
    format and the counts now are too, in both the report and --augment mode, and the
    SKIPPED row (package name, no file) loses its zeros the same way.
    tests/test_excel_not_measured.py runs the command on a real registry.
  • audit --output refuses a target it cannot write before the scan, without a
    traceback.
    Measured on 2026-10-09 in the published image, docker run … -v apk:/data:ro … audit /data/fennec.apk --output /data/x.html ran the whole audit, printed
    it, and ended in a Rich traceback through console.save_html — OSError: [Errno 30] Read-only file system. The target was checked for its extension and for its parent
    directory existing, and a read-only directory exists. So does a directory that happens
    to carry the report's name. Both are now refused up front with exit code 2 and one line,
    which is the point of checking the target before the APK is opened.
    tests/test_report_target_writable.py.
  • Report tables fold long identifiers instead of cutting them. Measured on 2026-10-09:
    audit fennec.apk --output report.html through a pipe — how a report is saved from a
    script, and where Rich settles on 80 columns — wrote the tracker row as
    com.google.android.gms.ads.identifi…, and the saved HTML held identifi… and nowhere
    the string ads.identifier. Rich's default for a cell that does not fit is an ellipsis;
    the package column is the finding, and a report file does not know how wide the terminal
    was. The package, permission, prefix and host columns now fold onto the next line.
    tests/test_report_identifiers_whole.py renders at 80 and 56 columns.
  • The README's counts are the code's. It said "43 SDKs", "24 Android permissions" and,
    in Known limitations, "43 trackers, 23 permissions": the code recognises 44 SDK names
    over 46 signatures and 28 permissions, and the permissions table left out the four
    advertising identifiers (AD_ID and the three Privacy Sandbox permissions) added on
    2026-09-25. tests/test_readme_counts.py now reads the numbers and the table from the
    README and compares them with scanner.py, so the next addition fails a test instead of
    ageing the document. The limitation also names what the list does not have, measured
    against εxodus (432 trackers on 2026-10-09): Glean and ACRA are the two found in the
    F-Droid apps audited that day.

Changed

  • mailradar 2026.44 and cookieradar 2026.44 are now the floor. Both carry the fixes their own real-world runs found — GPG credited only when the keyserver verifies the address, all 33 DKIM selectors asked; TrustArc and Usercentrics refusals clicked, an error page in any session reported as NOT MEASURED — and apkradar's audit leans on those checks. pip install -U apkradar brings them along.