mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-17 19:27:11 +08:00
web_fetch fetched any http/https URL a model emitted, checking only the scheme. It performed requests.get(..., allow_redirects=True) with no hostname resolution check and no private/loopback/link-local/cloud-metadata filtering, and never re-validated redirect targets. A model (including one under prompt injection) could make CowAgent fetch 127.0.0.1, RFC1918, 169.254.169.254 or other internal endpoints and return their bodies into the conversation; a public URL could also 302-bounce into a private target. The repo already shipped an SSRF validator for the vision tool (Vision._validate_url_safe). Extract that logic into a shared helper (agent/tools/utils/url_safety.py) and reuse it: - execute() now validates the URL before dispatching to either fetch path. - A new _safe_get() helper disables auto-redirect and follows redirects manually, re-validating every hop so a public URL cannot bounce into an internal address. Both the webpage and document fetch paths use it. - Vision._validate_url_safe now delegates to the shared helper (public API unchanged), so both URL-consuming tools share one guard. Stdlib only (ipaddress, socket, urllib.parse); no new dependency. Adds tests/test_security_ssrf_web_fetch.py covering loopback, cloud-metadata, RFC1918 and a public->loopback redirect. Sink: agent/tools/web_fetch/web_fetch.py (_fetch_webpage / _fetch_document). Signed-off-by: christop <825583681@qq.com>
48 lines
923 B
Python
48 lines
923 B
Python
from .truncate import (
|
|
truncate_head,
|
|
truncate_tail,
|
|
truncate_line,
|
|
format_size,
|
|
TruncationResult,
|
|
DEFAULT_MAX_LINES,
|
|
DEFAULT_MAX_BYTES,
|
|
GREP_MAX_LINE_LENGTH
|
|
)
|
|
|
|
from .diff import (
|
|
strip_bom,
|
|
detect_line_ending,
|
|
normalize_to_lf,
|
|
restore_line_endings,
|
|
normalize_for_fuzzy_match,
|
|
fuzzy_find_text,
|
|
generate_diff_string,
|
|
FuzzyMatchResult
|
|
)
|
|
|
|
from .url_safety import (
|
|
validate_url_safe,
|
|
assert_public_ip
|
|
)
|
|
|
|
__all__ = [
|
|
'truncate_head',
|
|
'truncate_tail',
|
|
'truncate_line',
|
|
'format_size',
|
|
'TruncationResult',
|
|
'DEFAULT_MAX_LINES',
|
|
'DEFAULT_MAX_BYTES',
|
|
'GREP_MAX_LINE_LENGTH',
|
|
'strip_bom',
|
|
'detect_line_ending',
|
|
'normalize_to_lf',
|
|
'restore_line_endings',
|
|
'normalize_for_fuzzy_match',
|
|
'fuzzy_find_text',
|
|
'generate_diff_string',
|
|
'FuzzyMatchResult',
|
|
'validate_url_safe',
|
|
'assert_public_ip'
|
|
]
|