OpenHands / OpenHands/software-agent-sdk
OpenHands Fork Audit - HIGH: get_litellm_model_info makes unvalidated httpx.get call at LLM init
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 539
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 137
Description
FLEET AUDIT FINDING: OpenHands Zentra fork — egress completeness audit
Location: vendor/openhands-sdk/openhands/sdk/llm/utils/model_info.py:31, called from llm.py:2229
Severity: HIGH (P2) — Potential egress hole if policy not enforced before LLM init
The Issue:
model_info.py:31 makes an httpx.get call:
response = httpx.get(f"{base_url}/v1/model/info", headers=headers)
This is called from LLM._init_model_info_and_caps() (llm.py:619), which runs in post_init (during LLM object construction).
The call is gated on:
if model.startswith("litellm_proxy/") and base_url:
But the execution sequence matters:
- In the agent-server, enforce_agent_llm_policy() is called at conversation start
- This clamps the LLM model/base_url BEFORE an LLM object is constructed
- So by the time _init_model_info_and_caps runs, the policy should have already filtered off-box models
However:
- The SDK guard is the ONLY chokepoint if an LLM is constructed outside the agent-server (e.g., in unit tests, local SDK usage)
- If a model starts with "litellm_proxy/" but base_url points off-box, the call proceeds
- The _zentra_airgap.py guard in _prepare_transport_kwargs (line 2051) only fires on COMPLETION calls, not on post_init
Risk:
If the policy enforcement order changes or an LLM is constructed outside the agent-server path, an off-box base_url could trigger the httpx.get before the SDK call-boundary guard fires.
Code evidence:
# llm.py:619 (__post_init__)
self._init_model_info_and_caps()
# model_info.py:78-82
if model.startswith("litellm_proxy/") and base_url:
response = httpx.get(f"{base_url}/v1/model/info", headers=headers) # Unvalidated!
Fix guidance:
Add a call to assert_onbox_target() in _init_model_info_and_caps() BEFORE the httpx.get, OR gate the call on airgap_enforced(). Ensures the base_url is validated to the appliance endpoint before ANY HTTP call.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read vendor/openhands-sdk/openhands/sdk/llm/utils/model_info.py at the model-info request and llm.py at _init_model_info_and_caps() in post_init. Trace how enforce_agent_llm_policy() and the SDK transport guard currently apply. Done means the base_url is validated or the request is gated before httpx.get can run, including when an LLM is constructed outside the agent-server.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100