ci: hw: add script for debugging USB permissions
What changed, and why it matters
This commit adds a diagnostic script to help debug USB permission problems during automated hardware testing. It does not change any firmware code that runs on Trezor devices, nor does it alter how user funds or secrets are handled. It only collects system information (like USB device listings and library dependencies) and saves it as a log file for CI troubleshooting.
No security action required. This is a CI/debugging tooling change. Reviewers may optionally confirm that the uploaded logs do not contain secrets, though the commands used only expose system-level USB metadata.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change introduces core/tools/check-usb-permissions.py, a Python helper invoked in the core-hw GitHub Actions workflow. The script runs a series of non-destructive inspection commands (uname, id, lsusb, uhubctl, ldd, strace) and logs their output. It also adds strace and usbutils to the Nix shell environment so these tools are available. No firmware, bootloader, crypto, or application logic is modified.
Changed components
.github/workflows/core-hw.ymlcore/tools/check-usb-permissions.pyshell.nixInspect captured patch +47 / −3
### .github/workflows/core-hw.yml
@@ -92,7 +92,10 @@ jobs:
submodules: recursive
persist-credentials: false
- uses: ./.github/actions/environment
- - run: nix-shell --arg hardwareTest true --run uhubctl
+ - name: uhubctl
+ run: |
+ nix-shell --arg hardwareTest true --run uhubctl
+ nix-shell --arg hardwareTest true --run "uv run core/tools/check-usb-permissions.py" |& tee check-usb-permissions.log
- run: nix-shell --run "uv run make -C core build_firmware"
- run: nix-shell --arg hardwareTest true --run "uv run python ci/hardware_tests/bootstrap.py \"$TREZOR_MODEL\" core/build-xtask/artifacts/latest/firmware.bin"
- run: |
@@ -110,6 +113,7 @@ jobs:
path: |
trezor.log
pytest.log
+ check-usb-permissions.log
retention-days: 7
if: always()
@@ -185,13 +189,18 @@ jobs:
submodules: recursive
persist-credentials: false
- uses: ./.github/actions/environment
- - run: nix-shell --arg hardwareTest true --run uhubctl
+ - name: uhubctl
+ run: |
+ nix-shell --arg hardwareTest true --run uhubctl
+ nix-shell --arg hardwareTest true --run "uv run core/tools/check-usb-permissions.py" |& tee check-usb-permissions.log
- run: nix-shell --run "uv run legacy/script/setup"
- run: nix-shell --run "export PRODUCTION=0 && uv run legacy/script/cibuild"
- run: nix-shell --arg hardwareTest true --run "ci/hardware_tests/t1_hw_test.sh"
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # actions/upload-artifact@v7.0.0
with:
name: legacy-hardware-${{ matrix.coins }}
- path: ci/hardware_tests/*.mp4
+ path: |
+ ci/hardware_tests/*.mp4
+ check-usb-permissions.log
retention-days: 7
if: always()
### core/tools/check-usb-permissions.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+
+import subprocess
+from pathlib import Path
+
+
+def cmd(command: str) -> None:
+ try:
+ command = f"{command} 2>&1"
+ print(f"COMMAND: {command}")
+ completed = subprocess.run(command, shell=True, capture_output=True, text=True)
+ print(completed.stdout)
+ if completed.returncode != 0:
+ print(f"RETURNED: {completed.returncode}")
+ except FileNotFoundError as e:
+ print(f"ERROR: {e}")
+ print("")
+
+
+cmd("uname -a")
+cmd("uptime")
+cmd("id")
+dirs = " ".join(str(d) for d in Path("/dev/bus/usb").parents)
+cmd(f"ls -ld /dev/bus/usb/* {dirs}")
+cmd("ls -l /dev/bus/usb/*")
+cmd("ls -vl `find /sys/bus/usb/devices/usb*/ -name disable`")
+cmd(
+ 'for F in `find /sys/bus/usb/devices/usb*/ -name disable | sort -V`; do echo -n "$F "; cat $F; done'
+)
+cmd("lsusb --tree -v")
+cmd("uhubctl --version")
+cmd("ldd `which uhubctl`")
+cmd("strace --color=never -fZ uhubctl")
### shell.nix
@@ -126,6 +126,8 @@ stdenvNoCC.mkDerivation ({
socat
ffmpeg_7-headless
dejavu_fonts
+ strace
+ usbutils
] ++ lib.optionals devTools [
cmake
ninjaWhy this scored 15/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.