mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 12:37:20 +08:00
fix: ssrf, add internal ip filter when parse tool schema (#29548)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Yeuoly <45712896+Yeuoly@users.noreply.github.com>
This commit is contained in:
parent
2b3c55d95a
commit
2bf44057e9
@ -9,6 +9,7 @@ import httpx
|
|||||||
|
|
||||||
from configs import dify_config
|
from configs import dify_config
|
||||||
from core.helper.http_client_pooling import get_pooled_http_client
|
from core.helper.http_client_pooling import get_pooled_http_client
|
||||||
|
from core.tools.errors import ToolSSRFError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -93,6 +94,18 @@ def make_request(method, url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs):
|
|||||||
while retries <= max_retries:
|
while retries <= max_retries:
|
||||||
try:
|
try:
|
||||||
response = client.request(method=method, url=url, **kwargs)
|
response = client.request(method=method, url=url, **kwargs)
|
||||||
|
# Check for SSRF protection by Squid proxy
|
||||||
|
if response.status_code in (401, 403):
|
||||||
|
# Check if this is a Squid SSRF rejection
|
||||||
|
server_header = response.headers.get("server", "").lower()
|
||||||
|
via_header = response.headers.get("via", "").lower()
|
||||||
|
|
||||||
|
# Squid typically identifies itself in Server or Via headers
|
||||||
|
if "squid" in server_header or "squid" in via_header:
|
||||||
|
raise ToolSSRFError(
|
||||||
|
f"Access to '{url}' was blocked by SSRF protection. "
|
||||||
|
f"The URL may point to a private or local network address. "
|
||||||
|
)
|
||||||
|
|
||||||
if response.status_code not in STATUS_FORCELIST:
|
if response.status_code not in STATUS_FORCELIST:
|
||||||
return response
|
return response
|
||||||
|
|||||||
@ -29,6 +29,10 @@ class ToolApiSchemaError(ValueError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ToolSSRFError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ToolCredentialPolicyViolationError(ValueError):
|
class ToolCredentialPolicyViolationError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -425,7 +425,7 @@ class ApiBasedToolSchemaParser:
|
|||||||
except ToolApiSchemaError as e:
|
except ToolApiSchemaError as e:
|
||||||
openapi_error = e
|
openapi_error = e
|
||||||
|
|
||||||
# openai parse error, fallback to swagger
|
# openapi parse error, fallback to swagger
|
||||||
try:
|
try:
|
||||||
converted_swagger = ApiBasedToolSchemaParser.parse_swagger_to_openapi(
|
converted_swagger = ApiBasedToolSchemaParser.parse_swagger_to_openapi(
|
||||||
loaded_content, extra_info=extra_info, warning=warning
|
loaded_content, extra_info=extra_info, warning=warning
|
||||||
@ -436,7 +436,6 @@ class ApiBasedToolSchemaParser:
|
|||||||
), schema_type
|
), schema_type
|
||||||
except ToolApiSchemaError as e:
|
except ToolApiSchemaError as e:
|
||||||
swagger_error = e
|
swagger_error = e
|
||||||
|
|
||||||
# swagger parse error, fallback to openai plugin
|
# swagger parse error, fallback to openai plugin
|
||||||
try:
|
try:
|
||||||
openapi_plugin = ApiBasedToolSchemaParser.parse_openai_plugin_json_to_tool_bundle(
|
openapi_plugin = ApiBasedToolSchemaParser.parse_openai_plugin_json_to_tool_bundle(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user