JuliusBrussee/caveman · error

githubapp: invalid base URL

Error message

githubapp: invalid base URL

What it means

SSRF guard in do(): the App's configured base URL fails re-validation — unparseable, missing scheme or host, or carrying embedded user info. Protects every GitHub egress from targeting a malformed or credential-leaking base URL.

Source

Thrown at shared/platform/githubapp/githubapp.go:354

	}
	return decoded, nil
}

// DoToken issues an authenticated GitHub REST call with an installation token and
// returns the status + raw body for the caller to parse. It is the reusable
// primitive the worker's PR opener builds the Git Data API flow on, so every
// GitHub egress goes through the one SSRF-guarded client + fixed base host.
func (a *App) DoToken(ctx context.Context, token, method, path string, body any) (int, []byte, error) {
	return a.do(ctx, "Bearer "+token, method, path, body)
}

func (a *App) do(ctx context.Context, authorization, method, path string, body any) (int, []byte, error) {
	if !strings.HasPrefix(path, "/") || strings.HasPrefix(path, "//") || strings.Contains(path, "\\") {
		return 0, nil, fmt.Errorf("githubapp: request path must be a single-host absolute path")
	}
	base, err := url.Parse(a.baseURL)
	if err != nil || base.Scheme == "" || base.Host == "" || base.User != nil {
		return 0, nil, fmt.Errorf("githubapp: invalid base URL")
	}
	relative, err := url.ParseRequestURI(path)
	if err != nil || relative.IsAbs() || relative.Host != "" || relative.User != nil {
		return 0, nil, fmt.Errorf("githubapp: invalid request path")
	}
	target, err := url.Parse(a.baseURL + path)
	if err != nil || target.Scheme != base.Scheme || !strings.EqualFold(target.Host, base.Host) || target.User != nil {
		return 0, nil, fmt.Errorf("githubapp: request path escaped configured host")
	}
	var reader io.Reader
	if body != nil {
		b, err := json.Marshal(body)
		if err != nil {
			return 0, nil, fmt.Errorf("githubapp: marshal request: %w", err)
		}
		reader = bytes.NewReader(b)
	}
	req, err := http.NewRequestWithContext(ctx, method, target.String(), reader)

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Fix the configured BaseURL to a clean https://host URL without userinfo
  2. Re-run githubapp.New() with a valid base URL; check config for stray characters
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at shared/platform/githubapp/githubapp.go:354 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/ae75ce1625e6cc63. Report an issue: GitHub.