Shamir Mnemonic Reconstruction Accepts Invalid Share Sets → Silent Wrong Secret (Loss of Funds)
Components: jsbtc (shamir_secret_sharing.js, bip39_mnemonic.js) / pybtc (shamir.py, bip39.py)
Date: April 2026
Summary
The reconstruction API accepts share sets that are syntactically valid but semantically invalid (sub-threshold or mixed-instance) and returns a deterministic but incorrect secret without any error.
Reconstruction appears successful to the user, but produces the wrong mnemonic/seed.
This can lead to irreversible loss of funds under realistic usage.
Impact
- Permanent loss of funds
- No error or warning signal
- Failure is indistinguishable from success
- Occurs under normal user workflows (share loss + re-splitting)
Root Cause
The implementation only validates:
- Distinct x-coordinates
- Syntactic share structure
It does not validate:
- Threshold completeness (
|S| ≥ t)
- Single split-instance origin
As a result, reconstruction executes outside the valid Shamir domain and returns an arbitrary but deterministic result.
Vulnerability
Reconstruction should reject invalid share sets. Instead, it computes and returns a wrong secret.
This occurs via two practical paths.
Path A — Sub-threshold Share Injection (pybtc)
Component: create_mnemonic_additional_share
Issue
The function accepts fewer shares than required and still calls restore_secret.
entropy = restore_secret(s, x=q)
No threshold validation is performed. The only guard is an assert, which is disabled under python -O.
Reproduction
3-of-5 split (threshold = 3):
Input: 2 valid shares
Output: new share mnemonic (no error)
Reconstruction:
Expected : 4a3f92117eb305cc881d762af94e6031
Recovered: 2687db46eeffe7ac558f9983f8f52c49
Error : none
All 2-share combinations produce incorrect results.
Result
- Generates a valid-looking but invalid share
- Corrupts future recovery
- No detection mechanism
Realistic Scenario
User loses one share and attempts to regenerate it using remaining shares → receives incorrect share → recovery later fails silently.
Path B — Cross-Instance Share Mixing (jsbtc + pybtc)
Issue
Reconstruction does not verify that shares come from the same split.
if (s[i] !== undefined)
throw new Error("Non unique or invalid shares")
Only duplicate indices are checked.
Reproduction
Two independent splits of the same secret:
- Split A: {3, 7, 11}
- Split B: {5, 9, 13}
Same-instance subsets : 2/2 correct
Mixed subsets : 0/18 correct (all wrong, no error)
Result
- Reconstruction succeeds syntactically
- Returns wrong secret deterministically
- No error raised
Realistic Scenario
User re-splits after partial loss and later mixes shares → recovery produces wrong mnemonic → funds lost.
Additional Issue — Ambiguous Error Handling
The error "Non unique or invalid shares" is returned for:
- Duplicate shares
- Index collisions across mnemonics
- Malformed input
Users cannot distinguish failure causes, making recovery troubleshooting unreliable.
Supporting Issue — Incomplete Validation (pybtc)
__combinations uses:
total = len(a) ** 2 # wrong
instead of:
total = 2 ** len(a) # correct
This causes most subsets to be skipped during validation (e.g. 2/10 tested in a 3-of-5 split).
This does not directly cause the vulnerability but shows that correctness checks are incomplete.
Fix
1. Enforce threshold:
if len(shares) < threshold:
raise ValueError("insufficient shares")
2. Enforce same instance — bind at split time:
instance_id = H(secret || salt || split_counter)
Validate before reconstruction:
if len({get_instance_id(s) for s in shares}) != 1:
raise ValueError("shares from different splits")
3. Replace assert with runtime check:
if index_max <= len(shares):
raise ValueError("invalid index space")
4. Improve error messages — differentiate:
- Insufficient shares
- Duplicate index
- Cross-instance mixing
- Malformed share
Severity
High.
This vulnerability allows the system to return incorrect secrets without any error, under realistic user behavior, leading to irreversible loss of funds. The failure is silent and indistinguishable from success, making it particularly dangerous in a backup/recovery system.
Conclusion
The implementation does not enforce that reconstruction inputs are valid.
Successful execution of reconstruction does not imply correctness.
This violates a core safety requirement of secret backup systems and can result in permanent loss of access to funds.
BTC adress: bc1qk4lwexcrmrm64memntyemf6rvemhtu8uj4xwhd
Shamir Mnemonic Reconstruction Accepts Invalid Share Sets → Silent Wrong Secret (Loss of Funds)
Components: jsbtc (
shamir_secret_sharing.js,bip39_mnemonic.js) / pybtc (shamir.py,bip39.py)Date: April 2026
Summary
The reconstruction API accepts share sets that are syntactically valid but semantically invalid (sub-threshold or mixed-instance) and returns a deterministic but incorrect secret without any error.
Reconstruction appears successful to the user, but produces the wrong mnemonic/seed.
This can lead to irreversible loss of funds under realistic usage.
Impact
Root Cause
The implementation only validates:
It does not validate:
|S| ≥ t)As a result, reconstruction executes outside the valid Shamir domain and returns an arbitrary but deterministic result.
Vulnerability
Reconstruction should reject invalid share sets. Instead, it computes and returns a wrong secret.
This occurs via two practical paths.
Path A — Sub-threshold Share Injection (pybtc)
Component:
create_mnemonic_additional_shareIssue
The function accepts fewer shares than required and still calls
restore_secret.No threshold validation is performed. The only guard is an
assert, which is disabled underpython -O.Reproduction
3-of-5 split (threshold = 3):
All 2-share combinations produce incorrect results.
Result
Realistic Scenario
User loses one share and attempts to regenerate it using remaining shares → receives incorrect share → recovery later fails silently.
Path B — Cross-Instance Share Mixing (jsbtc + pybtc)
Issue
Reconstruction does not verify that shares come from the same split.
Only duplicate indices are checked.
Reproduction
Two independent splits of the same secret:
Result
Realistic Scenario
User re-splits after partial loss and later mixes shares → recovery produces wrong mnemonic → funds lost.
Additional Issue — Ambiguous Error Handling
The error
"Non unique or invalid shares"is returned for:Users cannot distinguish failure causes, making recovery troubleshooting unreliable.
Supporting Issue — Incomplete Validation (pybtc)
__combinationsuses:instead of:
This causes most subsets to be skipped during validation (e.g. 2/10 tested in a 3-of-5 split).
This does not directly cause the vulnerability but shows that correctness checks are incomplete.
Fix
1. Enforce threshold:
2. Enforce same instance — bind at split time:
Validate before reconstruction:
3. Replace
assertwith runtime check:4. Improve error messages — differentiate:
Severity
High.
This vulnerability allows the system to return incorrect secrets without any error, under realistic user behavior, leading to irreversible loss of funds. The failure is silent and indistinguishable from success, making it particularly dangerous in a backup/recovery system.
Conclusion
The implementation does not enforce that reconstruction inputs are valid.
Successful execution of reconstruction does not imply correctness.
This violates a core safety requirement of secret backup systems and can result in permanent loss of access to funds.
BTC adress: bc1qk4lwexcrmrm64memntyemf6rvemhtu8uj4xwhd