Initial Thoughts on Code Transparency

Over nine months since I broached the uncomfortable questions about app signing, we have the official response. It is simultaneously more than I would have expected and less than what we need.

These materials have only been in my hand for a few hours, and I expect I’ll write more about the situation next week. But, let’s see what we got.

First, there is this FAQ entry from “The future of Android App Bundles is here”, the post where Google firmly declared that the App Bundle requirement is coming in a month:

When distributing apps on Google Play, how do I ensure my app is delivered to users the way I intend?

At any time, you can download and inspect artifacts from the Play Store, from the app bundle explorer in the Play Console, and via the Play Developer API to verify your app. In addition, code transparency for app bundles is a new, optional feature that can be used to inspect that code running on a device matches the code that was originally built and signed by the developer.

The first sentence is typical subterfuge. At best, all downloading those artifacts do is tell us the state of those specific artifacts. Google is perfectly capable of delivering different artifacts to different people. It is not significantly different than is serving different Web pages to different people, which Google has been doing since its inception. So, they can give unmodified artifacts to the developer and give tampered artifacts to other parties.

In terms of the second sentence, the passive tense in “can be used” is doing a lot of heavy lifting. As it turns out, “can” is somewhat theoretical at this time.

More of the details are in the “Code transparency for app bundles” page in the developer documentation.

(Google seems indecisive over whether or not App Bundle is a proper noun — I will give it The Capital Treatment here for consistency with past posts on this subject)

Code transparency creates a roster of SHA256 hashes for each DEX file and each .so file that is part of the App Bundle. If that file ships to a user as part of an app, somebody could use it to confirm that the DEX files and .so files in the app match their hashes. And, the code transparency file itself is signed, using a signing key private to the developer, so in principle we can determine if the code transparency file itself has been modified (e.g., to reflect hashes of tampered files rather than the original files).

That sounds good, and to an extent, it is.

However, all Google needs to do is remove the code transparency file from the apps that they deliver to users. After all:

  • They have full signing authority, so they can remove whatever they want

  • There is no legal or contractual requirement for them to ship this file

  • There is nothing in the operating system that is looking for this file, as they readily admit:

Important: The Android OS does not verify code transparency files at install time, and continues to rely on the APK signing schemes for verification of any installed APKs.

If there is no code transparency file, there is no code transparency.

Also, verifying that the code transparency file itself is the original implies that we can validate that its signature is intact and was from the developer’s signing key. There is no current infrastructure for this, as Google also admits:

Important: To verify that the signature comes from the original developer, the printed fingerprint from one of the following methods must be compared with the public key communicated by the developer through a trusted channel. For example, the developer can host their public certificate on a secure website that is known to belong to them. To ensure no other changes have been made to the app, checking the APK signature is also necessary and recommended.

In addition, the code transparency file conveniently omits some things:

  • It does not include the manifest (or resources, assets, etc.)

  • It does not seem to preclude there being *additional* DEX or `.so` files, beyond the ones in the code transparency file

(UPDATE 2021-07-02: The documentation has since been revised to clarify that the code transparency file is meant to be a complete snapshot of the DEX and .so files — if an app contains code that is not in the code transparency file, that should fail the transparency check)

There has been an app-resigning attack available since Android 8.0 that neatly fits those two omissions.

The upshot is that we, the developer ecosystem, will need to build a secure, reliable way for developers to advertise, for any given versionCode of an applicationId, that a code transparency file was included in the App Bundle, along with the certificate (or certificate hash) that was used to sign that code transparency file. Google, at least at present, is washing their hands of that mess. Without this, we have no way of knowing, for any given app, whether a missing code transparency file is a problem and whether an existing code transparency file is valid.

Then, we, the developer ecosystem, will need to create practical tooling around this stuff. What Google has given us is new commands for bundletool. As a reference implementation, that’s great. As a practical matter, that is very limited. For example, an anti-malware app running on Android itself is not going to be using bundletool directly via a shell command, if that’s even realistic. We are going to need a specification for the code transparency file, along with implementations that can be used in more flexible ways (e.g., a library). It is unclear to what extent Google will be interested in any of that.

In addition, we, the developer ecosystem, will need to experiment with extending this system to include other developer-chosen content, such as the manifest, and deal with the “what if there’s other stuff here than what’s listed?” issue.

Plus, we, the developer ecosystem, will need to get tools in the hands of users to actually validate the code transparency. It does us no good to have code transparency files if nothing checks for them and verifies that the app was not modified by Google. This will likely need to be some mix of existing security-related apps (e.g., the aforementioned anti-malware apps) and dedicated code transparency audit apps. Google is unlikely to help here, and frankly, we should view any such help as being suspect (“the fox guarding the henhouse”).


  • None of this affects APK-based uses of Play App Signing — official code transparency is only for App Bundles

  • None of this affects other distribution channels that employ equivalents to Play App Signing… such as the Amazon AppStore for Android, coming to a Windows 11 installation near you soon

We, the developer ecosystem, are going to need to figure out how to address those scenarios as well.

Worst of all, these are just the things that I have thought of. I am certain to be missing some problems or skipping over some scenarios, and those might add to the pile of work to be done.

Google’s implementation of code transparency is more than I expected, insofar as I really did not expect Google to do much of anything. I have no idea how robust the core elements of their solution are, and we will only find that out over time. But, the fact that this even exists is a positive step, incomplete as it may be.

That incompleteness is why this is less than what we need.

And all of this is just to avoid allowing developers to continue distributing APKs the way that they have for over a decade, if they so choose.

In essence, Google has slashed our car tires, and then has generously offered to pay for a lift home. While that is a nice gesture, it does not address the problem with the car, and it would have been nicer if Google had not slashed the tires in the first place.

Again, I expect to write more about this in the coming weeks and months. Suffice it to say: there’s a lot of work ahead for those of us concerned about the problem. If you are concerned about the problem, enough to perhaps help with that work, please reach out!