{"record":{"id":"2d3dc345a6a0ee03","repo":"flipped-aurora/gin-vue-admin","slug":"ssrf","errorCode":null,"errorMessage":"目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启\"允许内网\"豁免)","messagePattern":"目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝\\(可在任务上开启\"允许内网\"豁免\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/service/system/sys_timed_task_http.go","lineNumber":14,"sourceCode":"// server/service/system/sys_timed_task_http.go\npackage system\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"syscall\"\n\t\"time\"\n)\n\n// errPrivateAddr SSRF 防护拒绝(错误信息含\"SSRF\"关键字, 供日志/测试识别)\nvar errPrivateAddr = errors.New(\"目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启\\\"允许内网\\\"豁免)\")\n\n// isDisallowedIP 内网/环回/链路本地/未指定地址判定\nfunc isDisallowedIP(ip net.IP) bool {\n\treturn ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified()\n}\n\n// ssrfControl 在拨号阶段(DNS 解析后、连接建立前)校验目标 IP:\n// 每次连接都过检, 天然覆盖重定向与 DNS rebinding(TOCTOU 安全)。\nfunc ssrfControl(allowPrivate bool) func(network, address string, c syscall.RawConn) error {\n\treturn func(_ string, address string, _ syscall.RawConn) error {\n\t\tif allowPrivate {\n\t\t\treturn nil\n\t\t}\n\t\thost, _, err := net.SplitHostPort(address)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"解析拨号地址失败: %w\", err)\n\t\t}\n\t\tip := net.ParseIP(host)","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_timed_task_http.go#L1-L32","documentation":"errPrivateAddr is the sentinel returned by the HTTP task executor's SSRF protection when the target URL resolves to a loopback, private (RFC1918), link-local, multicast link-local, or unspecified IP. It prevents server-side request forgery against internal networks; tasks can opt out via an \"allow intranet\" flag.","triggerScenarios":"Running/creating an HTTP-executor timed task whose URL host is 127.0.0.1, ::1, 10.x, 172.16-31.x, 192.168.x, 169.254.x, 0.0.0.0, or a DNS name resolving to any of these, without the allow-intranet exemption enabled on the task.","commonSituations":"Pointing tasks at internal microservices (http://localhost:8080/...) in dev configs; docker-compose service names resolving to private IPs; staging tasks moved from public to private endpoints; corporate DNS resolving to internal ranges.","solutions":["If the target is intentionally internal, enable the task's \"允许内网\" (allow intranet) exemption flag.","Use a publicly reachable https:// endpoint for the task target.","Check DNS resolution of the hostname; if it resolves to a private IP unexpectedly, fix DNS or use the public address.","Avoid loopback/unspecified addresses like localhost or 0.0.0.0 unless exempted."],"exampleFix":"// before\nHttpUrl: \"http://127.0.0.1:8080/health\" // rejected by SSRF guard\n\n// after\ntask.AllowIntranet = true\nHttpUrl: \"http://127.0.0.1:8080/health\" // allowed with explicit exemption\n// or\nHttpUrl: \"https://api.example.com/health\"","handlingStrategy":"try-catch","validationCode":"ips, err := net.LookupIP(u.Hostname())\nif err == nil {\n    for _, ip := range ips {\n        if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() {\n            if !task.AllowIntranet {\n                return errors.New(\"target resolves to a private address; enable allow-intranet or use a public endpoint\")\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := runner.RunTask(ctx, task); err != nil {\n    if strings.Contains(err.Error(), \"SSRF\") {\n        log.Warnf(\"task %s blocked by SSRF guard; target is internal\", task.Name)\n        return\n    }\n    log.Errorf(\"task %s failed: %v\", task.Name, err)\n}","preventionTips":["Use public endpoints for scheduled HTTP tasks","Enable the allow-intranet exemption only for intentionally internal targets","Check what hostnames resolve to before configuring tasks","Avoid localhost/0.0.0.0 targets in shared environments"],"tags":["ssrf","security","network","go"],"backgroundTag":"ssrf-private-address-blocked","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}