fix(core): add missing `get_serial_number` handler
What changed, and why it matters
This commit fixes a build configuration issue for the Trezor T3W1 hardware wallet. The device supports reading a unique serial number, but the build system was not correctly advertising that capability. As a result, the Python module that handles the 'get serial number' command was accidentally excluded from the firmware image, so the feature would not work at runtime. The patch adds the missing capability flag for the T3W1 (emulator and three hardware revisions) and fixes a related list-concatenation bug in the build script that could have caused other feature exclusions to behave incorrectly. There is no direct evidence in the commit of a security vulnerability; it reads as a functionality/availability fix.
Treat as a low-severity build fix. Verify that T3W1 firmware images now include get_serial_number.py and that the serial-number feature works on device and emulator. Review whether any shipped firmware builds were produced with the buggy SConscript.unix expression and, if so, confirm that sd_protect/authenticate_device exclusions were not unintentionally affected. No urgent security response is indicated by the diff alone.
Security signals we found
Build-system feature gating error caused a device-management command module to be omitted from firmware image.
SConscript.unix precedence bug in chained conditional list concatenation could have affected other feature exclusions.
No direct code-level security flaw (e.g., buffer overflow, authentication bypass) is present in the diff.
Missing serial-number handler is primarily a functional/availability issue, though serial number retrieval can be relevant to device identity/attestation workflows.
Evidence from the diff
The change adds ‘serial_number’ to features_available in four T3W1 model configuration files (emulator.py, revA/B/C) when ‘serial_number’ is in features_wanted. It also adds a ‘serial_number’ feature flag to core/embed/rust/Cargo.toml. The SConscript.unix change rewrites an exclude expression from a chain of conditional list literals joined by ‘+’ (which Python evaluates with surprising precedence) into explicit parenthesized tuple concatenations. The practical effect is that for T3W1 builds, apps/management/get_serial_number.py is now included in SOURCE_PY, and the exclusion logic for sd_protect.py and authenticate_device.py is grouped correctly. The commit message and changelog frame this as ‘add missing get_serial_number handler’.
Changed components
Trezor Core firmware build system (SConscript.unix)T3W1 model configuration scripts (emulator.py, trezor_t3w1_revA.py, revB.py, revC.py)core/embed/rust/Cargo.toml feature flagsapps/management/get_serial_number.py inclusion in firmware imageInspect captured patch +14 / −7
diff --git a/core/.changelog.d/6100.fixed b/core/.changelog.d/6100.fixed
new file mode 100644
index 000000000..ad4f22838
--- /dev/null
+++ b/core/.changelog.d/6100.fixed
@@ -0,0 +1 @@
+[T3W1] Add missing `get_serial_number` handler.
diff --git a/core/SConscript.unix b/core/SConscript.unix
index cfdb04bc1..814dbea04 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -726,13 +726,14 @@ if FROZEN:
] if TREZOR_MODEL != "T3W1" else [])
)
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py',
- exclude=[
- SOURCE_PY_DIR + 'apps/management/sd_protect.py',
- ] if "sd_card" not in FEATURES_AVAILABLE else [] + [
- SOURCE_PY_DIR + 'apps/management/authenticate_device.py',
- ] if "optiga" not in FEATURES_AVAILABLE else [] + [
- SOURCE_PY_DIR + 'apps/management/get_serial_number.py',
- ] if "serial_number" not in FEATURES_AVAILABLE else [])
+ exclude=(
+ [SOURCE_PY_DIR + 'apps/management/sd_protect.py'] if "sd_card" not in FEATURES_AVAILABLE else []
+ ) + (
+ [SOURCE_PY_DIR + 'apps/management/authenticate_device.py'] if "optiga" not in FEATURES_AVAILABLE else []
+ ) + (
+ [SOURCE_PY_DIR + 'apps/management/get_serial_number.py'] if "serial_number" not in FEATURES_AVAILABLE else []
+ )
+ )
)
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py',
exclude=(
diff --git a/core/embed/rust/Cargo.toml b/core/embed/rust/Cargo.toml
index 2d642c9ad..0730fad2f 100644
--- a/core/embed/rust/Cargo.toml
+++ b/core/embed/rust/Cargo.toml
@@ -52,6 +52,7 @@ ble = []
nrf = []
smp = []
tropic = []
+serial_number = []
storage = []
translations = ["crypto"]
secmon_layout = []
diff --git a/core/site_scons/models/T3W1/emulator.py b/core/site_scons/models/T3W1/emulator.py
index 674f6fe0f..d2950ec45 100644
--- a/core/site_scons/models/T3W1/emulator.py
+++ b/core/site_scons/models/T3W1/emulator.py
@@ -139,5 +139,6 @@ def configure(
if "serial_number" in features_wanted:
defines += [("USE_SERIAL_NUMBER", "1")]
+ features_available.append("serial_number")
return features_available
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revA.py b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
index 5eaf4d3b0..da7b385bc 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revA.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revA.py
@@ -309,6 +309,7 @@ def configure(
if "serial_number" in features_wanted:
defines += [("USE_SERIAL_NUMBER", "1")]
+ features_available.append("serial_number")
env.get("ENV")["LINKER_SCRIPT"] = linker_script
env.get("ENV")["MEMORY_LAYOUT"] = memory_layout
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
index d5ce2c505..ff8c02e70 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
@@ -316,6 +316,7 @@ def configure(
if "serial_number" in features_wanted:
defines += [("USE_SERIAL_NUMBER", "1")]
+ features_available.append("serial_number")
env.get("ENV")["LINKER_SCRIPT"] = linker_script
env.get("ENV")["MEMORY_LAYOUT"] = memory_layout
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revC.py b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
index 56559578e..4ba477d73 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revC.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revC.py
@@ -315,6 +315,7 @@ def configure(
if "serial_number" in features_wanted:
defines += [("USE_SERIAL_NUMBER", "1")]
+ features_available.append("serial_number")
env.get("ENV")["LINKER_SCRIPT"] = linker_script
env.get("ENV")["MEMORY_LAYOUT"] = memory_layout
Why this scored 16/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.