Auto-build SeedSignerOS for PRs (pi0 + pi02w) and add "all" target for workflow_dispatch#349
Draft
Auto-build SeedSignerOS for PRs (pi0 + pi02w) and add "all" target for workflow_dispatch#349
Conversation
Apply "".join(word) pattern to all code paths that store words from bip39.mnemonic_from_bytes().split() or direct bip39.WORDLIST lookups. This ensures that wipe_list()/wipe_string() only operates on independent string copies, preventing corruption of the shared global wordlist. Protected paths: - mnemonic_generation: calculate_checksum, generate_mnemonic_from_bytes, generate_mnemonic_from_dice, generate_mnemonic_from_coin_flips, generate_mnemonic_from_image, get_partial_final_word - decode_qr: CompactSeedQR decoding path - bitbox02_backup: mnemonic from seed bytes - scan_views: two mnemonic_from_bytes call sites - seed_views: fake words in verification quiz - seed_storage: add_slip39_share_mnemonic Added regression tests for all newly protected mnemonic_generation paths. Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/ee028c01-f567-4d3f-9123-be91b06a8dc0 Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
Replace the synchronous save() (which blocks the UI thread with json.dump + flush + fsync) with a deferred background write: - save() now schedules a Timer that fires after 1 second - Rapid successive calls are coalesced into a single disk write - flush_save() forces an immediate synchronous write (called on restart/power-off to guarantee persistence) - Thread-safe via a lock protecting timer scheduling and file I/O - Data is snapshot before writing so mutations don't cause inconsistent JSON on disk RestartView and PowerOffView now call flush_save() before exiting. Added 3 tests: non-blocking behavior, coalescing, and flush. Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/d2bac2bf-107e-4d8e-86da-b0eb1e537ecc Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
…e_infra - Split _write_to_disk into _do_write_to_disk (no lock, called by caller holding the lock) and _write_to_disk (acquires lock, used as Timer callback) - flush_save now calls _do_write_to_disk while holding the lock, eliminating the race where a new timer could slip in between cancel and write - Add _reset_save_infra() for test isolation instead of directly manipulating internal state Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/d2bac2bf-107e-4d8e-86da-b0eb1e537ecc Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
…rd, comments - Assign self._save_timer before timer.start() to prevent race - flush_save() only writes if a timer was actually pending (no-op otherwise) - Add Singleton comment explaining class-level attributes are safe - Add test_flush_save_noop_when_no_pending test Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/d2bac2bf-107e-4d8e-86da-b0eb1e537ecc Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
A longer delay better handles the case where a user accidentally toggles a setting a few times — rapid changes are coalesced into a single disk write after 5 seconds of inactivity. Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/9ceca68d-955e-4cff-9222-4e9d4c7382a2 Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
…rtal strings Defense-in-depth: wipe_string() now checks the reference count of the string before zeroing its buffer. On CPython 3.12+ string literals (including BIP-39/SLIP-39 wordlist entries) are immortal objects with a pinned refcount (~4 billion). The new _is_shared() helper detects these and skips the wipe, preventing corruption of global wordlists even if a direct reference is accidentally stored in a list that is later passed to wipe_list(). For older CPython the threshold falls back to 50 — any string referenced that many times is almost certainly a global constant. A warning is logged whenever a shared string wipe is skipped, aiding diagnosis of the underlying "".join() omission. Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/8cc48865-e0ec-4233-9801-a73210f62798 Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/8cc48865-e0ec-4233-9801-a73210f62798 Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/a3890599-f607-4f2c-b619-de741baf85fb Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/ce11d21a-7728-41b0-a725-586a6d3d767e Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
3rdIteration
April 12, 2026 00:59
View session
Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/4f479aff-9e46-4928-87fa-9419fac706bf Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
…ix build to use PR head SHA Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/f6454f43-79f2-4447-a214-a940fbd02c1b Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
- secure_delete.py: add _WORDLIST_IDS frozenset to explicitly track BIP-39/SLIP-39
wordlist entry ids; _is_shared() checks id membership before refcount to prevent
wipe_string() from corrupting the global wordlist on Python < 3.12 (where words are
not immortal and refcount is below the 50 threshold)
- build.yml: replace 'unzip -o "${zip_files[@]}"' with a loop; unzip interprets
subsequent args as patterns within the first archive, causing exit code 11 when
multiple zip files are passed
Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/df29db58-1105-43de-873b-244edd211597
Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
…a leakage Agent-Logs-Url: https://github.com/3rdIteration/seedsigner/sessions/df29db58-1105-43de-873b-244edd211597 Co-authored-by: 3rdIteration <2230318+3rdIteration@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_is_shared()in secure_delete.py: add explicit wordlist-ID set to catch BIP39 entries on Python 3.10 (non-immortal, refcount ~9 < threshold 50)calculate sha256sumstep: loopunzipover each zip file separately instead of passing all as args (unzip treats 2nd arg as a pattern inside the 1st archive)