What changed, and why it matters
This commit adds a new disabled-by-default feature flag called 'ward' to the Trezor firmware build system. It does not change any production firmware behavior; it only wires up a placeholder MicroPython module and build options so that future WARD-related code can be developed safely behind the flag. There is no security vulnerability visible in this change.
No security action required. Treat as normal feature-flag scaffolding. If auditing future WARD functionality, verify that the `ward` feature remains disabled in production build configurations and that any newly added `trezorward` module functions are reviewed before being enabled.
Security signals we found
New feature flag is disabled by default and gated behind optional Cargo features
Commit message explicitly states intent to exclude WARD from production firmware builds
New MicroPython module is a stub with no exported functions beyond __name__
No changes to cryptographic, storage, authentication, or UI code paths
Evidence from the diff
The patch introduces an optional ward Cargo feature across the firmware workspace, a trezor-ward crate dependency, a minimal trezorward MicroPython module exposing only __name__, a USE_WARD C preprocessor define, and corresponding xtask CLI/TBench/manifest options. The feature is explicitly described as experimental and excluded from production builds. No cryptographic, storage, or UI logic is modified, and the new module contains no callable functionality.
Changed components
core/embed build system (Cargo.toml, xtask options)core/embed/rust/src/ward modulecore/embed/upymod MicroPython bindingscore/src/trezor/utils.py import listdocs/core/build/xtask.mdInspect captured patch +55 / −0
### core/embed/Cargo.lock
@@ -1004,6 +1004,10 @@ dependencies = [
name = "trezor-tjpgdec"
version = "0.1.0"
+[[package]]
+name = "trezor-ward"
+version = "0.1.0"
+
[[package]]
name = "trezor_lib"
version = "0.0.0"
@@ -1031,6 +1035,7 @@ dependencies = [
"sys",
"trezor-thp",
"trezor-tjpgdec",
+ "trezor-ward",
"ufmt",
"unsize",
"upymod",
### core/embed/Cargo.toml
@@ -79,6 +79,7 @@ spin = { version = "0.9.9", features = ["rwlock", "spin_mutex", "lazy"], default
static-alloc = "0.2.6"
trezor-thp = { path = "../../rust/trezor-thp" }
trezor-tjpgdec = { version = "0.1.0", path = "../../rust/trezor-tjpgdec" }
+trezor-ward = { path = "../../rust/trezor-ward" }
ufmt = "0.2.0"
unsize = "1.1.0"
without-alloc = "0.2.2"
### core/embed/projects/firmware/Cargo.toml
@@ -51,6 +51,7 @@ ui_debug_overlay = ["trezor_lib/ui_debug_overlay"]
ui_performance_overlay = ["trezor_lib/ui_performance_overlay"]
universal_fw = ["trezor_lib/universal_fw", "upymod/universal_fw"]
unsafe_fw = []
+ward = ["trezor_lib/ward", "upymod/ward"]
# --------------------------------------------------------------------------
# MCU selection - only enable one of these at a time
### core/embed/projects/firmware/project.toml
@@ -77,3 +77,4 @@ pyopt = { true = ["pyopt"], false = ["debug", "optiga_te
source-lines = { true = ["micropy_enable_source_lines"] }
storage-insecure-testing-mode = { true = ["storage_insecure_testing_mode"] }
unsafe-fw = { true = ["unsafe_fw"] }
+ward = { true = ["ward"] }
### core/embed/rust/Cargo.toml
@@ -32,6 +32,7 @@ spin.workspace = true
static-alloc.workspace = true
trezor-thp = { workspace = true, optional = true }
trezor-tjpgdec.workspace = true
+trezor-ward = { workspace = true, optional = true }
ufmt.workspace = true
unsize.workspace = true
without-alloc.workspace = true
@@ -109,6 +110,7 @@ ui_overlay = []
ui_performance_overlay = []
universal_fw = []
usb = []
+ward = ["dep:trezor-ward"]
# --------------------------------------------------------------------------
# Unit test configuration
### core/embed/rust/librust_qstr.h
@@ -938,6 +938,7 @@ static void _librust_qstrs(void) {
MP_QSTR_trezorproto;
MP_QSTR_trezorthp;
MP_QSTR_trezorui_api;
+ MP_QSTR_trezorward;
MP_QSTR_tutorial;
MP_QSTR_tutorial__continue;
MP_QSTR_tutorial__did_you_know;
### core/embed/rust/src/lib.rs
@@ -50,6 +50,8 @@ mod trace;
#[cfg(feature = "translations")]
mod translations;
mod trezorhal;
+#[cfg(feature = "ward")]
+mod ward;
// mod ui is `pub` because of the re-export pattern in individual models, which
// would trigger a brickload of "unused symbol" warnings otherwise.
### core/embed/rust/src/ward/micropython.rs
@@ -0,0 +1,8 @@
+use crate::micropython::macros::obj_module;
+use crate::micropython::module::Module;
+use crate::micropython::qstr::Qstr;
+
+#[no_mangle]
+pub static mp_module_trezorward: Module = obj_module! {
+ Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorward.to_obj()
+};
### core/embed/rust/src/ward/mod.rs
@@ -0,0 +1 @@
+pub mod micropython;
### core/embed/upymod/Cargo.toml
@@ -67,6 +67,7 @@ touch = ["io/touch"]
touch_wakeup = ["io/touch_wakeup"]
tropic = ["sec/tropic"]
universal_fw = ["crypto/universal_fw", "io/usb_iface_webauthn"]
+ward = []
# --------------------------------------------------------------------------
# Automatically derived features (do not enable from outside)
### core/embed/upymod/build.rs
@@ -80,6 +80,10 @@ fn main() -> Result<()> {
lib.add_define("USE_NFC", Some("1"));
}
+ if cfg!(feature = "ward") {
+ lib.add_define("USE_WARD", Some("1"));
+ }
+
lib.add_define(
"MICROPY_ENABLE_SOURCE_LINE",
Some(if cfg!(feature = "enable_source_lines") {
@@ -964,6 +968,7 @@ impl<'a> MpyBuilder<'a> {
let touch = py_bool(cfg!(feature = "touch"));
let touch_wakeup = py_bool(cfg!(feature = "touch_wakeup"));
let tropic = py_bool(cfg!(feature = "tropic"));
+ let ward = py_bool(cfg!(feature = "ward"));
let scm_revision_xor2 = self.scm_revision_xor2;
let nfc = py_bool(cfg!(feature = "nfc"));
@@ -990,6 +995,7 @@ impl<'a> MpyBuilder<'a> {
format!(r"s/utils\.USE_TOUCH_WAKEUP/{touch_wakeup}/g"), // must be before USE_TOUCH
format!(r"s/utils\.USE_TOUCH/{touch}/g"),
format!(r"s/utils\.USE_TROPIC/{tropic}/g"),
+ format!(r"s/utils\.USE_WARD/{ward}/g"),
format!(r"s/utils\.USE_NFC/{nfc}/g"),
format!(r"s/utils\.SCM_REVISION_XOR2/{scm_revision_xor2}/g"),
format!(r#"s/utils\.UI_LAYOUT == "BOLT"/{layout_bolt}/g"#),
### core/embed/upymod/modtrezorutils/modtrezorutils.c
@@ -882,6 +882,8 @@ static const mp_obj_tuple_t mod_trezorutils_version_obj = {
/// """Whether N1W1 is supported."""
/// USE_AES_GCM: bool
/// """Whether the AES-GCM is supported."""
+/// USE_WARD: bool
+/// """Whether WARD is supported."""
/// MODEL: str
/// """Model name."""
/// MODEL_FULL_NAME: str
@@ -1018,6 +1020,11 @@ static const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_USE_AES_GCM), mp_const_true},
#else
{MP_ROM_QSTR(MP_QSTR_USE_AES_GCM), mp_const_false},
+#endif
+#if USE_WARD
+ {MP_ROM_QSTR(MP_QSTR_USE_WARD), mp_const_true},
+#else
+ {MP_ROM_QSTR(MP_QSTR_USE_WARD), mp_const_false},
#endif
{MP_ROM_QSTR(MP_QSTR_zero_unused_stack),
MP_ROM_PTR(&mod_trezorutils_zero_unused_stack_obj)},
### core/embed/upymod/rustmods.c
@@ -55,3 +55,7 @@ MP_REGISTER_MODULE(MP_QSTR_trezorlog, mp_module_trezorlog);
#ifdef USE_MINISCRIPT
MP_REGISTER_MODULE(MP_QSTR_trezorminiscript, mp_module_trezorminiscript);
#endif
+
+#ifdef USE_WARD
+MP_REGISTER_MODULE(MP_QSTR_trezorward, mp_module_trezorward);
+#endif
### core/embed/xtask/src/options.rs
@@ -206,6 +206,10 @@ build_options! {
#[arg(long, num_args = 0..=1, default_missing_value = "true")]
map miniscript: bool,
+ /// Experimental WARD support.
+ #[arg(long, num_args = 0..=1, default_missing_value = "true")]
+ map ward: bool,
+
/// Disable UI animations
#[arg(long, num_args = 0..=1, default_missing_value = "true")]
map disable_animation: bool,
### core/embed/xtask/tbench/manifest.yaml
@@ -168,6 +168,13 @@ options:
when: component(firmware)
type: checkbox
+ - id: ward
+ name: WARD Support
+ description: Enables experimental WARD support.
+ group: Features
+ when: component(firmware)
+ type: checkbox
+
- id: debug
name: Debug Build
description: Enables debug symbols and disables some optimizations.
### core/mocks/generated/trezorutils.pyi
@@ -294,6 +294,8 @@ USE_N1W1: bool
"""Whether N1W1 is supported."""
USE_AES_GCM: bool
"""Whether the AES-GCM is supported."""
+USE_WARD: bool
+"""Whether WARD is supported."""
MODEL: str
"""Model name."""
MODEL_FULL_NAME: str
### core/src/trezor/utils.py
@@ -43,6 +43,7 @@
USE_TOUCH,
USE_TOUCH_WAKEUP,
USE_TROPIC,
+ USE_WARD,
VERSION,
bootloader_locked,
check_firmware_header,
### docs/core/build/xtask.md
@@ -95,6 +95,7 @@ cannot be used bare:
- `--apps` — enable external app loading.
- `--n1w1` — enable N1W1 support.
- `--miniscript` — enable experimental Miniscript support.
+- `--ward` — enable experimental WARD support.
- `--unsafe-fw` — enable unsafe firmware features.
- `--storage-insecure-testing-mode` — insecure storage test mode (forbidden with
`--production`).Why 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.