fix(relay,osv): guard json.loads against JSONDecodeError - #54225
AlexFucuson9 wants to merge 1 commit into
Conversation
gateway/relay/descriptor.py: CapabilityDescriptor.from_json() calls json.loads() without catching JSONDecodeError, and raw.items() crashes with AttributeError if the JSON is not a dict (e.g. a list or string). Now raises ValueError with clear message on invalid input. tools/osv_check.py: _query_osv_batch() calls json.loads() on HTTP response without catching JSONDecodeError. If the OSV API returns a non-JSON response (rate limit HTML, 502 gateway error), the entire vulnerability check crashes. Now logs warning and returns empty list.
tonydwb
left a comment
There was a problem hiding this comment.
Defensive json.loads guards in relay descriptor and OSV check (12 additions, 2 files). Proper error handling for malformed JSON and type validation. Clean and minimal.
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing two real external-input crash paths. The current-main failures reproduce at gateway/relay/descriptor.py:74-76 and tools/osv_check.py:165-167.
Problems
- The OSV patch still permits a crash for valid but non-object JSON: after decoding
[], the unchangedresult.get("vulns", [])raisesAttributeErrorattools/osv_check.py:168. Please validate the decoded response is adictbefore using it. - Please add regressions for malformed/non-object descriptor JSON and malformed/non-object OSV response bodies. Current tests in
tests/gateway/relay/test_descriptor.pyandtests/tools/test_osv_check.pycover valid payloads but not these failure paths.
Suggested changes
- Fail open with a warning when the OSV response is not a JSON object (and validate the
vulnsshape before filtering). - Add targeted tests for HTML/malformed bytes and
[], then run the two affected test files throughscripts/run_tests.sh.
Automated hermes-sweeper review.
| raw = resp.read() | ||
| try: | ||
| result = json.loads(raw) | ||
| except (json.JSONDecodeError, UnicodeDecodeError): |
There was a problem hiding this comment.
A valid JSON but non-object response such as [] reaches this line and raises AttributeError, so the OSV check is still not fail-open for all malformed/unexpected response shapes. Please return [] when result is not a dict (and consider validating vulns is a list).
Problem
Two locations call
json.loads()on external input without catchingJSONDecodeError:gateway/relay/descriptor.py:74—CapabilityDescriptor.from_json()A malformed handshake message (e.g. JSON array, truncated JSON, or non-JSON payload) causes either
JSONDecodeErrororAttributeErroron.items().tools/osv_check.py:165—_query_osv_batch()The OSV API can return HTML error pages (rate limit, 502 gateway error), causing the entire vulnerability check to crash instead of gracefully returning no results.
Fix
descriptor.py: Wrapjson.loads()intry/except (json.JSONDecodeError, TypeError), raiseValueErrorwith clear message. Addisinstance(raw, dict)guard before.items().osv_check.py: Wrapjson.loads()intry/except (json.JSONDecodeError, UnicodeDecodeError), log warning, return empty list.Impact