[security] fix(action): block unsafe OpenAPI action URLs#106
Open
Hinotoi-agent wants to merge 1 commit into
Open
[security] fix(action): block unsafe OpenAPI action URLs#106Hinotoi-agent wants to merge 1 commit into
Hinotoi-agent wants to merge 1 commit into
Conversation
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.
Summary
This PR hardens OpenAPI-backed actions against server-side request forgery (SSRF). Action schemas currently accept an arbitrary
servers[0].url, store the derived action URL, and later pass it directly torequests.request()when the action is run.The patch adds action URL validation at both important layers:
Security issues covered
Before this PR
validate_openapi_schema()checked OpenAPI structure, path metadata, and operation IDs, but not whetherservers[0].urlwas safe for server-side fetching.extract_params()built the action URL fromservers[0].urland the path.call_action_api()sent the URL torequests.request()with default redirect behavior and no private-address denylist.After this PR
httpandhttps.localhost,.localhost, loopback, private, link-local, multicast, reserved, and unspecified destinations are rejected.allow_redirects=False; eachLocationtarget is resolved and revalidated before another request is made.ACTION_HTTP_TIMEOUTand defaulting to 10 seconds.Why this matters
OpenAPI actions are a server-side network primitive. If untrusted users can create or run actions, an attacker can use the API server's network position to reach services that are not reachable from the public Internet, including loopback-only admin endpoints, container/service-network hosts, and cloud metadata endpoints.
Because the action response is returned to the caller, this is not only blind SSRF; it can disclose internal HTTP responses and can interact with internal endpoints using multiple HTTP methods.
Attack flow
servers[0].urlpoints at an internal destination, such ashttp://127.0.0.1:8080or a link-local metadata endpoint.A redirect variant is also possible without this patch:
Affected code
app/schemas/tool/action.pyapp/services/tool/openapi_call.pyapp/services/tool/openapi_utils.pyservers[0].urland the OpenAPI path.Root cause
requestsdefault redirect handling, so redirect destinations were not revalidated before the next request.CVSS assessment
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:LSafe reproduction steps
On the vulnerable code path, a narrow harness can demonstrate the issue without contacting real internal services:
servers[0].urlset tohttp://127.0.0.1:59999and a path such as/secret.requests.requestand callcall_action_api()with the extracted URL.http://127.0.0.1:59999/secretand returns the mocked response body to the caller.This PR adds regression coverage for the blocked behavior instead of relying on a live internal service.
Expected vulnerable behavior
Before this PR, the action execution sink accepts an action URL targeting loopback/private destinations or follows redirects to those destinations, then returns the upstream response status/body to the action caller.
Changes in this PR
app/services/tool/url_security.pyfor action egress URL validation.servers[0].urlbefore accepting the schema.Files changed
app/services/tool/url_security.pyapp/schemas/tool/action.pyapp/services/tool/openapi_call.pytests/unit/test_action_url_security.pyMaintainer impact
httpandhttpshosts continue to work.Fix rationale
The safest boundary is the outbound action request itself. Validating only when the schema is submitted is not enough because runtime redirects can change the destination. This PR therefore validates both at persistence time and at the actual network sink, with redirect targets checked before the next request is sent.
Type of change
Test plan
Commands run locally:
python3 -m pytest tests/unit/test_action_url_security.py -qpython3 -m py_compile app/services/tool/url_security.py app/services/tool/openapi_call.py app/schemas/tool/action.py tests/unit/test_action_url_security.pygit diff --checkpython3 -m ruff check app/services/tool/url_security.py tests/unit/test_action_url_security.pypython3 -m ruff format --check app/services/tool/url_security.py app/services/tool/openapi_call.py app/schemas/tool/action.py tests/unit/test_action_url_security.pyNotes:
python3 -m ruff check app/schemas/tool/action.pystill reports pre-existing issues unrelated to this patch: twoN805validator naming findings and oneF811duplicateActionRunRequestdefinition. The new helper and new test file pass Ruff, and the touched files pass Ruff format check.python3 -m black --check ...could not be run in this local environment because Black is not installed and Poetry is not available on PATH here.Disclosure notes
This PR is intentionally scoped to OpenAPI action egress hardening. It does not claim to redesign action authorization or define a deployment-specific allowlist policy. The security impact is highest when action creation or action execution is reachable by untrusted users; if a deployment restricts action management to trusted operators only, this remains useful defense-in-depth against accidental internal egress exposure.