tsenart/vegeta · error

bad certificate

Error message

bad certificate

What it means

errBadCert is returned by tlsConfig when the provided TLS certificate material cannot be loaded or parsed. It signals that the attacker's client TLS configuration is invalid, typically due to a malformed PEM file or mismatched key/cert pair.

Source

Thrown at attack.go:76

	fs.Var(&opts.proxyHeaders, "proxy-header", "Proxy CONNECT header")
	fs.Var(&opts.laddr, "laddr", "Local IP address")
	fs.BoolVar(&opts.keepalive, "keepalive", true, "Use persistent connections")
	fs.StringVar(&opts.unixSocket, "unix-socket", "", "Connect over a unix socket. This overrides the host address in target URLs")
	fs.StringVar(&opts.promAddr, "prometheus-addr", "", "Prometheus exporter listen address [empty = disabled]. Example: 0.0.0.0:8880")
	fs.Var(&dnsTTLFlag{&opts.dnsTTL}, "dns-ttl", "Cache DNS lookups for the given duration [-1 = disabled, 0 = forever]")
	fs.BoolVar(&opts.sessionTickets, "session-tickets", false, "Enable TLS session resumption using session tickets")
	fs.Var(&connectToFlag{&opts.connectTo}, "connect-to", "A mapping of (ip|host):port to use instead of a target URL's (ip|host):port. Can be repeated multiple times.\nIdentical src:port with different dst:port will round-robin over the different dst:port pairs.\nExample: google.com:80:localhost:6060")
	systemSpecificFlags(fs, opts)

	return command{fs, func(args []string) error {
		fs.Parse(args)
		return attack(opts)
	}}
}

var (
	errZeroRate = errors.New("rate frequency and time unit must be bigger than zero")
	errBadCert  = errors.New("bad certificate")
)

// attackOpts aggregates the attack function command options
type attackOpts struct {
	name           string
	targetsf       string
	format         string
	outputf        string
	bodyf          string
	certf          string
	keyf           string
	rootCerts      csl
	http2          bool
	h2c            bool
	insecure       bool
	lazy           bool
	chunked        bool
	duration       time.Duration

View on GitHub (pinned to cf58112690)

Solutions

  1. Verify the cert and key files exist, are valid PEM, and form a matching pair (compare moduli or use `openssl x509`/`openssl rsa` checks).
  2. Regenerate or re-export the certificate/key pair from your CA.
  3. Test with `openssl x509 -in cert.pem -noout` and `openssl rsa -in key.pem -check` before running the attack.

Example fix

// before
vegeta attack -cert wrong.pem -key wrong.key ...
// after
vegeta attack -cert cert.pem -key key.pem ...
Defensive patterns

Strategy: validation

Validate before calling

if _, err := tls.LoadX509KeyPair(certFile, keyFile); err != nil {
    return fmt.Errorf("bad TLS material: %w", err)
}

Prevention

When it happens

Trigger: Passing a bad certificate/key path or content to vegeta attack's TLS options (e.g. -cert/-key flags), causing tlsConfig in attack.go to fail loading the X.509 keypair.

Common situations: Expired or corrupt certificate files, wrong file paths, a key that doesn't match the certificate, or passing a public cert where a keypair (cert+key) is required.

Understand the failure class

Related errors


AI-assisted analysis of tsenart/vegeta@cf58112690 (2026-08-31). Data as JSON: /api/errors/fd9a7bcaaf4e37a6. Report an issue: GitHub.