Fix uncaught AttributeError on non-object JSON in parse_msg_sign_request
What changed, and why it matters
This commit fixes a bug where the COLDCARD firmware's message-signing feature would crash with an uncaught error if a user supplied valid JSON that wasn't a structured object (for example, a plain number, string, list, or null). The fix checks the parsed JSON type and raises a proper, handled error instead of letting an AttributeError propagate. There is no direct evidence in the commit that this is exploitable for security harm, but unhandled exceptions can sometimes cause unexpected device behavior or denial of service.
Treat as a hardening fix. Review whether parse_msg_sign_request is reachable from untrusted input paths (USB, NFC, QR, serial) and ensure callers handle ValueError gracefully. Consider adding unit tests for non-object JSON inputs. No immediate emergency response is indicated by the diff alone.
Security signals we found
uncaught exception in message parsing path
input validation gap on JSON type
potential denial-of-service via malformed request
no authentication boundary visible in diff
Evidence from the diff
In shared/msgsign.py, parse_msg_sign_request() parses incoming data with ujson.loads() and then calls .get() on the result, assuming it is a dict. If the input is valid JSON but not a JSON object (e.g., 123, “string”, null, [1,2,3]), the .get() call raises an uncaught AttributeError. The patch adds an isinstance(data_dict, dict) check immediately after parsing and raises a ValueError with a clear message if the input is not a JSON object. This converts a crash into a controlled validation failure.
Changed components
shared/msgsign.pyparse_msg_sign_request functionCOLDCARD message signing featureInspect captured patch +3 / −0
### shared/msgsign.py
@@ -312,6 +312,9 @@ def parse_msg_sign_request(data):
try:
data_dict = ujson.loads(data.strip())
+ if not isinstance(data_dict, dict):
+ # valid JSON, but not an object (e.g. 123, "str", null, [1,2])
+ raise ValueError("not a JSON object")
text = data_dict.get("msg", None)
if text is None:
raise AssertionError("MSG required")Why this scored 23/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.