shadow1ng/fscan · error

%s %s: %w (webscan_request_parse_error, poc name)

Error message

%s %s: %w (webscan_request_parse_error, poc name)

What it means

This error is returned by executePoc in webscan/lib/poc_executor.go when ParseRequest fails to convert the incoming *http.Request into the scanner's internal Request representation. The wrapper prefixes the localized 'request parse error' message and the POC name, and wraps the underlying parse error with %w. It means the original target request could not be interpreted (bad URL/method form) before any POC rule runs.

Source

Thrown at webscan/lib/poc_executor.go:153

	return decls
}

// executePoc 执行单个POC检测
func executePoc(oReq *http.Request, p *Poc, pocCtx *POCContext) (bool, string, error) {
	// 收集POC变量声明
	varDecls := collectVarDeclarations(p)

	// 从基础环境扩展(复用缓存的基础环境,仅添加变量声明)
	env, err := ExtendEnvWithVars(varDecls)
	if err != nil {
		return false, "", fmt.Errorf("%s %s: %w", i18n.GetText("webscan_exec_env_error"), p.Name, err)
	}

	// 解析请求
	req, err := ParseRequest(oReq)
	if err != nil {
		return false, "", fmt.Errorf("%s %s: %w", i18n.GetText("webscan_request_parse_error"), p.Name, err)
	}

	// 初始化变量映射
	variableMap := make(map[string]interface{})
	defer func() { variableMap = nil }()
	variableMap["request"] = req

	// 处理设置项
	for _, item := range p.Set {
		key, expression := item.Key, item.Value
		if expression == "newReverse()" {
			if !pocCtx.DNSLog {
				return false, "", nil
			}
			variableMap[key] = newReverse(pocCtx.DNSLog)
			continue
		}
		if _, err = evalset(env, variableMap, key, expression); err != nil {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Inspect the wrapped inner error to see exactly which field ParseRequest rejected (URL, host, port, method).
  2. Validate/normalize the target URL before invoking the scan (scheme prefix, valid host, numeric port 1-65535).
  3. URL-encode spaces and special characters in the target path before passing the request to the scanner.
  4. Reproduce with url.Parse on the same URL locally to confirm it is the failing component.

Example fix

// before
executePoc(badReq, poc, ctx) // errors: webscan_request_parse_error
// after
u, err := url.Parse(target.URL)
if err != nil || u.Hostname() == "" {
    return fmt.Errorf("invalid target URL %q: %w", target.URL, err)
}
executePoc(badReq, poc, ctx)
Defensive patterns

Strategy: validation

Validate before calling

func validTarget(req *http.Request) error {
    if req == nil || req.URL == nil || req.URL.Host == "" {
        return fmt.Errorf("request has no parseable URL/host")
    }
    if _, err := url.Parse(req.URL.String()); err != nil {
        return fmt.Errorf("unparsable target URL: %w", err)
    }
    return nil
}

Type guard

func hasParseableURL(req *http.Request) bool {
    return req != nil && req.URL != nil && req.URL.Host != ""
}

Try / catch

ok, _, err := executePoc(req, poc, ctx)
if err != nil {
    var parseErr error
    if errors.As(err, &parseErr) && strings.Contains(err.Error(), i18n.GetText("webscan_request_parse_error")) {
        log.Printf("skipping %s: unparseable request: %v", poc.Name, err)
        return
    }
    return err
}

Prevention

When it happens

Trigger: executePoc is called with an *http.Request whose URL, method, or headers cannot be parsed by ParseRequest — e.g. a malformed target URL with invalid characters or an unparsable host, so ParseRequest returns a non-nil err.

Common situations: Scanning a target whose URL was assembled from raw user input with spaces, control characters, or a schemeless/malformed authority; feeding HostInfo data with an invalid port or host into the web scanner; proxy-replayed requests with corrupted request lines.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/846b134aaa246a6f. Report an issue: GitHub.