android: pin hostpython3 PyProjectRecipe versions, pin android and pyjnius recipes Cython version
What changed, and why it matters
This commit tightens the Android build process for the Electrum Bitcoin wallet by pinning exact versions of build tools (like Cython, pip, setuptools) and their cryptographic hashes. It also updates the version of python-for-android used. There is no direct vulnerability fix in the application code; instead, it is a supply-chain hardening change to make the build more reproducible and prevent unexpected or malicious tool updates during compilation.
Treat as a routine build-hardening commit. Verify the pinned hashes and the new python-for-android commit against upstream release notes before merging. No urgent security response is warranted based solely on this diff.
Security signals we found
Pins build-time dependency versions and cryptographic hashes
Updates python-for-android pinned checkout commit
Adds new pinned recipe overrides for android and pyjnius Cython prerequisites
No changes to application runtime code, wallet logic, or network handling
Evidence from the diff
The commit pins transitive build dependencies for the Android build recipes (hostpython3, android, pyjnius) using HashPinnedDependency with SHA-256 hashes, and pins Cython to 3.1.8. It also bumps the python-for-android checkout commit in the Dockerfile. No runtime wallet logic, networking, or cryptography is changed. The change reduces supply-chain risk during the Android build but does not patch an exploitable bug in shipped Electrum code.
Changed components
contrib/android/Dockerfilecontrib/android/p4a_recipes/hostpython3/__init__.pycontrib/android/p4a_recipes/android/__init__.pycontrib/android/p4a_recipes/pyjnius/__init__.pyInspect captured patch +54 / −3
diff --git a/contrib/android/Dockerfile b/contrib/android/Dockerfile
index b2d704a..d396fbe 100644
--- a/contrib/android/Dockerfile
+++ b/contrib/android/Dockerfile
@@ -235,7 +235,7 @@ RUN cd /opt \
&& /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e .
# install python-for-android
-ENV P4A_CHECKOUT_COMMIT="ee6886ec3048670b182afb18237e0ae69fde1254"
+ENV P4A_CHECKOUT_COMMIT="3aa0db1ed9b7349625c5fdeff96df4e564403541"
# ^ from branch electrum_202602 (note: careful with force-pushing! see #8162)
RUN cd /opt \
&& git clone https://github.com/spesmilo/python-for-android \
diff --git a/contrib/android/p4a_recipes/android/__init__.py b/contrib/android/p4a_recipes/android/__init__.py
new file mode 100644
index 0000000..17bd29a
--- /dev/null
+++ b/contrib/android/p4a_recipes/android/__init__.py
@@ -0,0 +1,20 @@
+import os
+
+from pythonforandroid.recipes.android import AndroidRecipe
+from pythonforandroid.util import load_source, HashPinnedDependency
+
+util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
+
+
+assert AndroidRecipe.depends == [('sdl3', 'sdl2', 'genericndkbuild', 'qt6'), 'pyjnius', 'python3'], AndroidRecipe.depends
+assert AndroidRecipe.python_depends == []
+
+
+class AndroidRecipePinned(util.InheritedRecipeMixin, AndroidRecipe):
+ hostpython_prerequisites = [
+ HashPinnedDependency(package="Cython==3.1.8",
+ hashes=['sha256:282b3c8e6abc3fea421919e862e898ffdd86fc0796009bdb5ffdf8211413219f'])
+ ]
+
+
+recipe = AndroidRecipePinned()
diff --git a/contrib/android/p4a_recipes/hostpython3/__init__.py b/contrib/android/p4a_recipes/hostpython3/__init__.py
index 9d1dcb8..5d9f0d6 100644
--- a/contrib/android/p4a_recipes/hostpython3/__init__.py
+++ b/contrib/android/p4a_recipes/hostpython3/__init__.py
@@ -1,7 +1,7 @@
import os
from pythonforandroid.recipes.hostpython3 import HostPython3Recipe
-from pythonforandroid.util import load_source
+from pythonforandroid.util import load_source, HashPinnedDependency
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
@@ -15,5 +15,31 @@ class HostPython3RecipePinned(util.InheritedRecipeMixin, HostPython3Recipe):
version = "3.11.14"
sha512sum = "4642f6d59c76c6e5dbd827fdb28694376a9cc76e513146d092b49afb41513b3c9dff2339cfcebfb5b260f5cdc49a59a69906e284e5d478b2189d3374e9e24fd5"
+ # this property overrides the default hostpython dependencies for PyProjectRecipe recipies
+ pyproject_base_dependencies = [
+ HashPinnedDependency(package="build[virtualenv]==1.4.0",
+ hashes=['sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596']),
+ HashPinnedDependency(package="pip==24.0",
+ hashes=['sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc']),
+ HashPinnedDependency(package="setuptools==80.9.0",
+ hashes=['sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922']),
+
+ # pin deptree build[virtualenv]==1.4.0
+ HashPinnedDependency(package="packaging==26.0",
+ hashes=['sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529']),
+ HashPinnedDependency(package="pyproject_hooks==1.2.0",
+ hashes=['sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913']),
+ HashPinnedDependency(package="virtualenv==21.2.0",
+ hashes=['sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f']),
+ HashPinnedDependency(package="distlib==0.4.0",
+ hashes=['sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16']),
+ HashPinnedDependency(package="filelock==3.25.2",
+ hashes=['sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70']),
+ HashPinnedDependency(package="platformdirs==4.9.4",
+ hashes=['sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868']),
+ HashPinnedDependency(package="python_discovery==1.1.3",
+ hashes=['sha256:90e795f0121bc84572e737c9aa9966311b9fde44ffb88a5953b3ec9b31c6945e']),
+ ]
+
recipe = HostPython3RecipePinned()
diff --git a/contrib/android/p4a_recipes/pyjnius/__init__.py b/contrib/android/p4a_recipes/pyjnius/__init__.py
index 7e850c9..267f5d9 100644
--- a/contrib/android/p4a_recipes/pyjnius/__init__.py
+++ b/contrib/android/p4a_recipes/pyjnius/__init__.py
@@ -1,7 +1,7 @@
import os
from pythonforandroid.recipes.pyjnius import PyjniusRecipe
-from pythonforandroid.util import load_source
+from pythonforandroid.util import load_source, HashPinnedDependency
util = load_source('util', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'util.py'))
@@ -12,6 +12,11 @@ assert PyjniusRecipe.python_depends == []
class PyjniusRecipePinned(util.InheritedRecipeMixin, PyjniusRecipe):
+ hostpython_prerequisites = [
+ HashPinnedDependency(package="Cython==3.1.8",
+ hashes=['sha256:282b3c8e6abc3fea421919e862e898ffdd86fc0796009bdb5ffdf8211413219f'])
+ ]
+
sha512sum = "a192c30ef87ca9601455976feb49f03dfdb8e1bf2545744a7b771a6d0930a56b334c7a2a39d30fb8855c070f16e4673dc5ff6920b04a6155ab5f9247b271df76"
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.