fix security: feat(resources): harden HTTP resource ingestion against private-network SSRF#1133
Open
13ernkastel wants to merge 3 commits intovolcengine:mainfrom
Open
Conversation
|
Failed to generate code suggestions for PR |
1 similar comment
|
Failed to generate code suggestions for PR |
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 change closes an authenticated SSRF path in the HTTP resource ingestion flow. Before this patch,
/api/v1/resourcesaccepted arbitrary remote URLs, the parser stack issued server-sideHEADandGETrequests with redirects enabled, and the fetched content could then be read back through normal content APIs. A low-privilege API caller could abuse that behavior to reach loopback, RFC1918, link-local, or metadata services reachable from the OpenViking host.CVSS v3.1: 8.8 High (
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L)Root Cause
What Changed
openviking/utils/network_guard.pyto extract destination hosts, resolve them, reject non-public addresses, and build per-requesthttpxvalidation hooks.openviking/server/local_input_guard.pyand enabled it for the HTTP/api/v1/resourcesroute.enforce_public_remote_targetsinopenviking/service/resource_service.pyso the service injects request validation into the parser chain and preserves the enforcement flag for watch-based reprocessing.openviking/utils/media_processor.pyintoopenviking/parse/parsers/html.pyso URL detection, HTML fetches, downloads, redirects, and proxy inheritance are all checked consistently.openviking/utils/resource_processor.pyto re-raiseOpenVikingErrorso blocked requests terminate as structured permission failures instead of degrading into parse warnings.tests/server/test_api_local_input_security.pyfor loopback HTTP targets, private git/SSH targets, and parser-level enforcement.Simple PoC (localhost-only, pre-patch behavior)
This is a controlled reproduction against a local test instance only. It demonstrates the SSRF primitive without targeting cloud metadata or real internal services.
root_urito inspect the imported tree and then read back the stored content.Before this patch, the content APIs can return
SSRF_PROOF_TOKEN_9f2d1b, proving that the server fetched a loopback-only resource and exposed the response through normal ingestion APIs. After this patch, the initialPOST /api/v1/resourcesrequest is rejected withPERMISSION_DENIED.Validation
uv run --no-project --python 3.12 python -m py_compile openviking/utils/network_guard.py openviking/server/local_input_guard.py openviking/server/routers/resources.py openviking/service/resource_service.py openviking/utils/media_processor.py openviking/utils/resource_processor.py openviking/parse/parsers/html.py tests/server/test_api_local_input_security.pyHEADandGETrequests to a loopback-only HTTP server and retrieve a unique response token.PERMISSION_DENIED, and the loopback server receives no requests.pytestrun was not completed in this workspace because the repository runtime environment is incomplete here (openvikingimport currently requires additional dependencies such asrequestsand bundled AGFS setup).Follow-up Hardening
httpxrepository fetchers such as the GitHub ZIP download path andgit clone, so repository ingestion gets equivalent redirect and proxy protections.Code Walkthrough
openviking/utils/network_guard.pyIntroduces the destination-host parser, DNS resolution checks, non-public address rejection, and reusable
httpxrequest hooks.openviking/server/local_input_guard.pyandopenviking/server/routers/resources.pyKeep the existing remote-input contract but now require public remote targets for server-side resource ingestion.
openviking/service/resource_service.pyAdds
enforce_public_remote_targets, re-validates remote sources, injects the request validator into parser kwargs, and preserves the boolean flag for watch-task reprocessing.openviking/utils/media_processor.pyandopenviking/parse/parsers/html.pyPropagate the validator into URL detection and fetch helpers so outbound
HEADandGETrequests, redirects, and proxy inheritance are checked consistently.openviking/utils/resource_processor.pyRe-raises framework security errors instead of flattening them into parse warnings.
tests/server/test_api_local_input_security.pyAdds regression tests that fail if loopback or private-network fetches become reachable again through the HTTP resource ingestion path.