netsec

package
v0.40.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package netsec provides centralized network security primitives used by every HTTP-based provider in SpeechKit (STT, TTS, LLM, downloads).

It addresses the audit findings S1-S5 (2026-04-16):

  • SSRF via unvalidated user-supplied BaseURL configuration
  • Missing TLS hardening on HTTP clients
  • Bearer tokens leaking through default loggers

All HTTP provider constructors MUST route user-supplied URLs through ValidateProviderURL and MUST obtain their *http.Client via NewSafeHTTPClient.

Index

Constants

View Source
const RedactedHeadersKey ctxKey = 1

RedactedHeadersKey is the context key used to store redacted headers.

Variables

View Source
var (
	ErrEmptyURL          = errors.New("netsec: empty URL")
	ErrInvalidURL        = errors.New("netsec: URL could not be parsed")
	ErrMissingScheme     = errors.New("netsec: URL must have a scheme")
	ErrMissingHost       = errors.New("netsec: URL must have a host")
	ErrUnsupportedScheme = errors.New("netsec: scheme must be http or https")
	ErrInsecureHTTP      = errors.New("netsec: plain http:// not allowed for this host")
	ErrLoopbackBlocked   = errors.New("netsec: loopback addresses not allowed")
	ErrPrivateBlocked    = errors.New("netsec: private / link-local / ULA addresses not allowed")
	ErrInvalidHost       = errors.New("netsec: URL host could not be resolved as a literal IP or name")
	ErrUserInfoForbidden = errors.New("netsec: URL user-info (user:pass@) is not permitted")
)

Validation errors. Callers can match on these with errors.Is for UX.

Functions

func BuildEndpoint

func BuildEndpoint(baseURL, path string, opts ValidationOptions) (string, error)

BuildEndpoint validates baseURL and joins path safely. It prevents a malicious baseURL like "https://legit.example.com/.." from escaping the host, and normalises trailing slashes.

func NewSafeHTTPClient

func NewSafeHTTPClient(opts ClientOptions) *http.Client

NewSafeHTTPClient returns an *http.Client with explicit TLS 1.2+ minimum, sensible timeouts, optional dial-target validation, and a transport wrapper that stores redacted request headers in context for logging paths that opt in.

The client is safe to share across goroutines.

func ProviderStatusError added in v0.24.0

func ProviderStatusError(provider string, status int, body []byte) error

ProviderStatusError returns a user-safe upstream provider error. It keeps the provider name and HTTP status, but never includes the raw response body.

func RedactBearer

func RedactBearer(value string) string

RedactBearer returns a safe rendering of an "Authorization: Bearer xxx" header value for logs. It always returns "Bearer [REDACTED]" when the input is non-empty, and "" otherwise.

func RedactHeaders

func RedactHeaders(h http.Header) http.Header

RedactHeaders returns a copy of h where sensitive header values are replaced with the literal "[REDACTED]". Safe for logging.

func SafeProviderErrorReason added in v0.24.0

func SafeProviderErrorReason(status int, body []byte) string

SafeProviderErrorReason classifies a provider response body without exposing body contents to UI, logs, or higher-level error messages.

func ValidateProviderURL

func ValidateProviderURL(raw string, opts ValidationOptions) error

ValidateProviderURL parses raw and rejects URLs that would expose the caller to SSRF. It does not make network calls — hostnames that are not IP literals are checked by NewSafeHTTPClient when DialValidation is set. Provider, download and update clients should combine URL validation with resolve-time dial validation.

func ValidateResolvedIP added in v0.24.0

func ValidateResolvedIP(ip net.IP, opts ValidationOptions) error

ValidateResolvedIP applies SSRF range restrictions to a concrete IP address returned by DNS resolution or visible on a dial target.

Types

type ClientOptions

type ClientOptions struct {
	// Timeout is the per-request timeout. Zero disables it (discouraged).
	Timeout time.Duration

	// TLSMinVersion pins the minimum TLS version (default: tls.VersionTLS12).
	TLSMinVersion uint16

	// InnerTransport, if non-nil, is wrapped by the RedactingRoundTripper.
	// Normally nil — the function constructs a hardened *http.Transport.
	InnerTransport http.RoundTripper

	// DisableKeepAlives turns off connection reuse. Leave false for best perf.
	DisableKeepAlives bool

	// DialValidation, when non-nil, validates the actual resolved target IP
	// before opening a TCP connection. Use this for any client that might reach
	// user-configurable provider, model download, or update URLs.
	DialValidation *ValidationOptions
}

ClientOptions configures a SpeechKit HTTP client.

type RedactingRoundTripper

type RedactingRoundTripper struct {
	Base http.RoundTripper
}

RedactingRoundTripper is an http.RoundTripper that records redacted copies of the outgoing request header set on the *http.Request context so that downstream logging middleware can inspect non-sensitive headers only.

It does NOT rewrite the outgoing request — the real Authorization header is sent over TLS as expected. Redaction applies only to what observability paths can access via ctx.Value(RedactedHeadersKey).

func (*RedactingRoundTripper) RoundTrip

func (r *RedactingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper.

type ValidationOptions

type ValidationOptions struct {
	// AllowLoopback permits http:// and https:// URLs whose host is a
	// literal loopback address (127.0.0.0/8, ::1, or the name "localhost").
	// Enable for local whisper-server / Ollama / dev endpoints.
	AllowLoopback bool

	// AllowPrivate permits URLs whose host is in RFC1918 / RFC6598 /
	// link-local / unique-local IPv6 ranges. Enable only for self-hosted
	// VPS scenarios where the user explicitly opts in.
	AllowPrivate bool

	// AllowHTTP permits http:// for non-loopback hosts. Leave false unless
	// an operator has a documented reason (e.g. test harness).
	AllowHTTP bool
}

ValidationOptions controls how strict URL validation behaves. The zero value is the safe default: HTTPS-only, no loopback, no private IPs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL