kubernetes/kops · error

decoding PKCS7 signature: %w

Error message

decoding PKCS7 signature: %w

What it means

parseAndValidatePKCS7Signer wraps the base64 decoding failure of the PKCS7 signature bytes taken from an Azure attested document. The signature field must be a valid base64-encoded DER PKCS#7/CMS blob; when Go's encoding/base64 rejects it (invalid characters, wrong length, empty-adjacent garbage) this error is returned. It means the attested document's signature was not transport-decoded correctly, so parsing was never attempted.

Source

Thrown at upup/pkg/fi/cloudup/azure/attest.go:240

		return nil, fmt.Errorf("verifying PKCS7 certificate chain: %w", err)
	}
	klog.V(4).Infof("PKCS7 certificate chain verified after resolving intermediate certificates for signer issuer %q", signer.Issuer)

	return data, nil
}

// parseAndValidatePKCS7Signer decodes and parses a base64-encoded PKCS7 signature, verifies its
// self-signature, and validates that the signer certificate's SAN identifies an Azure metadata
// endpoint. All checks here are CPU-only; no network I/O is performed, so this is safe to call
// before triggering intermediate certificate fetches.
func parseAndValidatePKCS7Signer(signature string) (*pkcs7.PKCS7, *x509.Certificate, error) {
	if signature == "" {
		return nil, nil, fmt.Errorf("empty PKCS7 signature")
	}

	sigBytes, err := base64.StdEncoding.DecodeString(signature)
	if err != nil {
		return nil, nil, fmt.Errorf("decoding PKCS7 signature: %w", err)
	}
	klog.V(4).Infof("Decoded PKCS7 signature (%d bytes)", len(sigBytes))

	p7, err := pkcs7.Parse(sigBytes)
	if err != nil {
		return nil, nil, fmt.Errorf("parsing PKCS7 signature: %w", err)
	}
	klog.V(8).Infof("Parsed PKCS7 structure with %d embedded certificate(s)", len(p7.Certificates))

	// Verify the PKCS7 signature against the embedded leaf certificate.
	if err := p7.Verify(); err != nil {
		return nil, nil, fmt.Errorf("verifying PKCS7 signature: %w", err)
	}
	klog.V(4).Infof("PKCS7 self-signature verified")

	signer := p7.GetOnlySigner()
	if signer == nil {
		return nil, nil, fmt.Errorf("PKCS7 signer certificate not found")

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Log the raw signature string (klog.V(4) already logs decoded length on success; on failure log the first/last chars) and confirm it is standard base64 (RFC 4648, not base64url)
  2. Trim surrounding whitespace/newlines from the signature before decoding, or normalize with strings.Map removing CR/LF/spaces
  3. If using a custom attested-document fetcher, ensure it returns the IMDS JSON unmodified and that the 'signature' field is extracted as-is
  4. Check for middleware/proxies or tests injecting invalid placeholder signatures; use a real base64-encoded PKCS7 blob in fixtures

Example fix

// before
sig := rawSignature // may contain newlines from transport
p7, err := parseAndValidatePKCS7Signer(sig, ...)
// after
sig := strings.TrimSpace(rawSignature)
sig = strings.ReplaceAll(sig, "\n", "")
sig = strings.ReplaceAll(sig, "\r", "")
p7, err := parseAndValidatePKCS7Signer(sig, ...)
Defensive patterns

Strategy: validation

Validate before calling

sig := strings.TrimSpace(attestedDoc.Signature)
if sig == "" || strings.ContainsAny(sig, " \n\r\t") {
    return fmt.Errorf("signature is not contiguous standard base64")
}
if _, err := base64.StdEncoding.DecodeString(sig); err != nil {
    return fmt.Errorf("signature not valid standard base64: %w", err)
}

Type guard

func isStandardBase64(s string) bool {
    if s == "" {
        return false
    }
    _, err := base64.StdEncoding.DecodeString(s)
    return err == nil
}

Try / catch

sigBytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
    klog.V(4).Infof("base64 decode failed for signature (len=%d): %v", len(signature), err)
    return nil, nil, fmt.Errorf("decoding PKCS7 signature: %w", err)
}

Prevention

When it happens

Trigger: verifyAttestedDocumentWithRootAndFetcher calls parseAndValidatePKCS7Signer with the 'signature' field extracted from the IMDS attested document JSON; base64.StdEncoding.DecodeString fails because the field is empty of valid base64, contains whitespace/newlines, uses base64url alphabet characters (-, _), or is truncated.

Common situations: Mock/test IMDS servers returning signature fields that are plain text or URL-safe base64 instead of standard base64; a proxy or middleware mangling the JSON response; manually copying an attested document and corrupting the signature string; Azure changing response encoding expectations in a custom fetcher.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/856bc22d693a147d. Report an issue: GitHub.