{"record":{"id":"311e3064357f52bb","repo":"kubernetes/kops","slug":"root-certificate-pool-is-required","errorCode":null,"errorMessage":"root certificate pool is required","messagePattern":"root certificate pool is required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/attest.go","lineNumber":186,"sourceCode":"\treturn fetchIntermediateCertsFromBaseURL(a.client, microsoftIntermediateCertBaseURL, signer)\n}\n\n// verifyAttestedDocumentWithRootAndFetcher verifies a PKCS7 attested document using the supplied\n// root pool and intermediate fetcher.\n//\n// The trust progression is:\n//  1. parseAndValidatePKCS7Signer verifies the PKCS7 self-signature against the embedded leaf\n//     certificate. At this point the signed content is integrity-bound to the leaf, but the\n//     leaf itself is still untrusted — its chain to a root has not been built. The leaf's SAN\n//     is sanity-checked against the Azure metadata domains here too.\n//  2. parseAndValidateAttestedDocumentContent parses the now-integrity-checked signed content\n//     for cheap rejection-only checks (nonce binding, freshness) before paying for chain\n//     building or network fetches.\n//  3. verifySignerCertChain performs the actual cryptographic chain validation against\n//     rootCertPool. This is the call that establishes trust in the signer.\nfunc verifyAttestedDocumentWithRootAndFetcher(signature string, body []byte, rootCertPool *x509.CertPool, fetchIntermediates func(*x509.Certificate) (*x509.CertPool, error)) (*attestedData, error) {\n\tif rootCertPool == nil {\n\t\treturn nil, fmt.Errorf(\"root certificate pool is required\")\n\t}\n\n\tp7, signer, err := parseAndValidatePKCS7Signer(signature)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// The signature binds this content to the (still-untrusted) leaf, so it is safe to run\n\t// rejection-only checks (nonce, freshness) before paying for chain building or network fetches\n\t// below.\n\tdata, err := parseAndValidateAttestedDocumentContent(p7.Content, body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Verify using only the certificates embedded in the PKCS7 structure; if that succeeds, the signer\n\t// is trusted. If it fails but the PKCS7 already embeds a cert matching the signer's issuer, the\n\t// chain is genuinely broken (not just missing an intermediate), so fail fast instead of fetching.","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/attest.go#L168-L204","documentation":"Guard error: verifyAttestedDocumentWithRootAndFetcher was invoked with a nil root certificate pool, so there is no trust anchor to verify the attestation chain against. A programming/configuration error in the caller, not attacker-triggered input.","triggerScenarios":"Thrown at upup/pkg/fi/cloudup/azure/attest.go:186 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Ensure the verifier is built via newAttestationVerifier, which always supplies a root pool","Fix the caller to pass a non-nil *x509.CertPool of trusted Microsoft roots"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}