Summary
This is not intended as a vulnerability report or an accusation. While packaging latest Arch AUR builds and working on sparrowwallet/lark#5 , I noticed a supply-chain hardening question around Maven artifacts containing native code.
I am opening this as a discussion/feedback issue to better understand the current guarantees and whether additional verification would be useful.
Observation
If I understand the build correctly, Sparrow/Lark currently depends on:
com.sparrowwallet:hid4java:0.8.1
which is resolved from the Sparrow Maven registry:
https://code.sparrowwallet.com/api/packages/sparrowwallet/maven/com/sparrowwallet/hid4java/0.8.1/hid4java-0.8.1.jar
This artifact contains prebuilt native libraries, for example:
linux-x86-64/libhidapi-libusb.so
As far as I can tell, the dependency is pinned by Maven version, but not by a committed artifact hash. I could not find Gradle dependency verification metadata, dependency lockfiles, or any equivalent hash pinning in the public Sparrow/Lark/Drongo source tree.
Why I think this matters
A fresh build appears to trust whatever the Maven repository serves for com.sparrowwallet:hid4java:0.8.1.
If an attacker ever managed to compromise code.sparrowwallet.com or the package registry and replace an existing JAR with a malicious one under the same version, a fresh source build would not detect this cryptographically. The native code from that JAR would then run inside the Sparrow process.
This reminded me, at a high level, of the broader lesson from the XZ Utils backdoor incident: native build artifacts deserve extra scrutiny, especially when they are consumed as prebuilt binaries.
Reproducibility angle
One thing I am unsure about is whether reproducible release checks fully cover this scenario.
For an already released version, replacing an existing Maven artifact would likely break reproducibility against the original release artifacts. That is good.
However, if I think like an attacker, the more attractive timing would be shortly before a new Sparrow release is built. If the Maven registry served a malicious hid4java-0.8.1.jar at that moment, and the official release was built from that input, then the new release could still be reproducible against the now-poisoned dependency set. The previous release might no longer be checked, and the new release would appear internally consistent.
So reproducibility helps detect after-the-fact changes to released inputs, but it may not by itself establish that the inputs used for a new release were the intended ones unless those inputs are also pinned or independently verified.
Possible hardening ideas
Some ideas that might reduce this risk:
- Commit Gradle dependency verification metadata, e.g.
gradle/verification-metadata.xml, with SHA256 hashes for all resolved Maven artifacts.
- Ensure Maven artifacts are immutable once published, or document that immutability guarantee if it already exists.
- Publish the exact build scripts, source revisions, and build environment used to produce the
com.sparrowwallet:* Maven artifacts, especially those containing native code.
- Consider building these artifacts in public CI, for example GitHub Actions, and publishing build logs/provenance alongside the artifacts.
- If older glibc compatibility is the reason for custom native builds, the public workflow could still build in an older Linux container or cross-build environment.
- Publish checksums or signatures for the Maven artifacts independently from the Maven repository itself.
- Prefer upstream artifacts such as
org.hid4java:hid4java where possible, or document why the Sparrow-republished artifact intentionally differs.
I may be overthinking this, and I would be interested in your perspective.
From a packaging and downstream review point of view, this looks like an area where additional supply-chain hardening could be useful, especially because the affected artifacts contain native code that is loaded into the Sparrow process.
Or do you think the existing release and reproducibility process already provides enough practical protection for this threat model?
Summary
This is not intended as a vulnerability report or an accusation. While packaging latest Arch AUR builds and working on sparrowwallet/lark#5 , I noticed a supply-chain hardening question around Maven artifacts containing native code.
I am opening this as a discussion/feedback issue to better understand the current guarantees and whether additional verification would be useful.
Observation
If I understand the build correctly, Sparrow/Lark currently depends on:
which is resolved from the Sparrow Maven registry:
https://code.sparrowwallet.com/api/packages/sparrowwallet/maven/com/sparrowwallet/hid4java/0.8.1/hid4java-0.8.1.jar
This artifact contains prebuilt native libraries, for example:
As far as I can tell, the dependency is pinned by Maven version, but not by a committed artifact hash. I could not find Gradle dependency verification metadata, dependency lockfiles, or any equivalent hash pinning in the public Sparrow/Lark/Drongo source tree.
Why I think this matters
A fresh build appears to trust whatever the Maven repository serves for
com.sparrowwallet:hid4java:0.8.1.If an attacker ever managed to compromise
code.sparrowwallet.comor the package registry and replace an existing JAR with a malicious one under the same version, a fresh source build would not detect this cryptographically. The native code from that JAR would then run inside the Sparrow process.This reminded me, at a high level, of the broader lesson from the XZ Utils backdoor incident: native build artifacts deserve extra scrutiny, especially when they are consumed as prebuilt binaries.
Reproducibility angle
One thing I am unsure about is whether reproducible release checks fully cover this scenario.
For an already released version, replacing an existing Maven artifact would likely break reproducibility against the original release artifacts. That is good.
However, if I think like an attacker, the more attractive timing would be shortly before a new Sparrow release is built. If the Maven registry served a malicious
hid4java-0.8.1.jarat that moment, and the official release was built from that input, then the new release could still be reproducible against the now-poisoned dependency set. The previous release might no longer be checked, and the new release would appear internally consistent.So reproducibility helps detect after-the-fact changes to released inputs, but it may not by itself establish that the inputs used for a new release were the intended ones unless those inputs are also pinned or independently verified.
Possible hardening ideas
Some ideas that might reduce this risk:
gradle/verification-metadata.xml, with SHA256 hashes for all resolved Maven artifacts.com.sparrowwallet:*Maven artifacts, especially those containing native code.org.hid4java:hid4javawhere possible, or document why the Sparrow-republished artifact intentionally differs.I may be overthinking this, and I would be interested in your perspective.
From a packaging and downstream review point of view, this looks like an area where additional supply-chain hardening could be useful, especially because the affected artifacts contain native code that is loaded into the Sparrow process.
Or do you think the existing release and reproducibility process already provides enough practical protection for this threat model?