shadow1ng/fscan · error · ErrInvalidURL
%w: %w (ErrInvalidURL)
Error message
%w: %w (ErrInvalidURL)
What it means
buildTargetURL in webscan/web_scan.go normalizes a HostInfo into a canonical scheme://host URL and returns ErrInvalidURL wrapped around the underlying cause when url.Parse rejects the input. It also returns ErrInvalidURL for an empty host or an invalid/out-of-range port. The sentinel wrapping lets callers use errors.Is(err, ErrInvalidURL) to detect bad targets.
Source
Thrown at webscan/web_scan.go:112
}
// buildTargetURL 构建规范的目标URL
func buildTargetURL(info *common.HostInfo) (string, error) {
// 自动构建URL
if info.URL == "" {
protocol := protocolHTTP
if isTLSPort(info.Port) {
protocol = protocolHTTPS
}
info.URL = protocol + net.JoinHostPort(info.Host, fmt.Sprint(info.Port))
} else if !hasProtocolPrefix(info.URL) {
info.URL = protocolHTTP + normalizeSchemelessWebTarget(info.URL)
}
// 解析URL以提取基础部分
parsedURL, err := url.Parse(info.URL)
if err != nil {
return "", fmt.Errorf("%w: %w", ErrInvalidURL, err)
}
if parsedURL.Hostname() == "" {
return "", fmt.Errorf("%w: empty host", ErrInvalidURL)
}
portStr := parsedURL.Port()
if portStr == "" {
if hasMalformedWebURLPort(parsedURL.Host) {
return "", fmt.Errorf("%w: invalid port", ErrInvalidURL)
}
} else {
port, err := strconv.Atoi(portStr)
if err != nil || port < 1 || port > 65535 {
return "", fmt.Errorf("%w: invalid port %q", ErrInvalidURL, portStr)
}
}
parsedURL.Host = normalizeWebURLHost(parsedURL.Host)
return fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host), nilView on GitHub (pinned to 95cc12e753)
Solutions
- Run url.Parse on the offending URL locally to see the exact parse failure in the wrapped cause.
- Ensure the target includes a valid scheme (http:// or https://) and a resolvable hostname with no spaces or control characters.
- Use a numeric port between 1 and 65535, or omit the port; for TLS targets on 443/8443/4443/9443 omit the URL and let the scanner pick https by port.
- Validate targets in a pre-scan pass (url.Parse + hostname/port checks) and skip or fix invalid entries instead of failing the run.
Example fix
// before info.URL = "http://host:99999" // ErrInvalidURL: invalid port // after info.URL = "https://host" // or http://host:8443, port within 1-65535
Defensive patterns
Strategy: validation
Validate before calling
func validateTargetURL(raw string) error {
if !strings.HasPrefix(strings.ToLower(raw), "http://") && !strings.HasPrefix(strings.ToLower(raw), "https://") {
raw = "http://" + raw
}
u, err := url.Parse(raw)
if err != nil {
return fmt.Errorf("unparsable: %w", err)
}
if u.Hostname() == "" {
return fmt.Errorf("empty host")
}
if p := u.Port(); p != "" {
n, err := strconv.Atoi(p)
if err != nil || n < 1 || n > 65535 {
return fmt.Errorf("invalid port %q", p)
}
}
return nil
} Type guard
func isWellFormedWebTarget(raw string) bool {
return validateTargetURL(raw) == nil
} Try / catch
base, err := buildTargetURL(info)
if err != nil {
if errors.Is(err, ErrInvalidURL) {
log.Printf("skipping invalid target %q: %v", info.URL, err)
return
}
return err
} Prevention
- Validate every target with url.Parse plus hostname/port checks before adding to scan lists
- Always include an explicit scheme and a numeric port within 1-65535
- Strip spaces and control characters from targets at ingestion time
- Use errors.Is(err, ErrInvalidURL) to branch on invalid targets instead of string matching
When it happens
Trigger: info.URL (after auto-prefixing http:// if schemeless) cannot be parsed by url.Parse; or the parsed URL has no hostname; or its port fails strconv.Atoi or is outside 1-65535.
Common situations: Targets supplied from CLI or asset lists like "http://exa mple.com" (space), "http://host:99999" (port out of range), "http://host:abc" (non-numeric port), or URLs with stray control characters; HostInfo populated with a host:port string pasted including a path or credentials that break parsing.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- ms17010_invalid_shellcode
- ms17010_shellcode_decode_failed: %w
- webscan_poc_convert_failed
- webscan_poc_file_read_failed
- webscan_cel_env_not_initialized
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/d953e631c1ca23d3.
Report an issue: GitHub.