{"record":{"id":"467babc46530b30a","repo":"crowdsecurity/crowdsec","slug":"could-not-parse-file-w","errorCode":null,"errorMessage":"could not parse file: %w","messagePattern":"could not parse file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiserver/middlewares/v1/crl.go","lineNumber":53,"sourceCode":"\n\treturn cc, nil\n}\n\nfunc (*CRLChecker) decodeCRLs(content []byte) ([]*x509.RevocationList, error) {\n\tvar crls []*x509.RevocationList\n\n\tfor {\n\t\tblock, rest := pem.Decode(content)\n\t\tif block == nil {\n\t\t\tbreak // no more PEM blocks\n\t\t}\n\n\t\tcontent = rest\n\n\t\tcrl, err := x509.ParseRevocationList(block.Bytes)\n\t\tif err != nil {\n\t\t\t// invalidate the whole CRL file so we can still use the previous version\n\t\t\treturn nil, fmt.Errorf(\"could not parse file: %w\", err)\n\t\t}\n\n\t\tcrls = append(crls, crl)\n\t}\n\n\treturn crls, nil\n}\n\n// refresh() reads the CRL file if new or changed since the last time\nfunc (cc *CRLChecker) refresh() error {\n\t// noop if lastLoad is less than 5 seconds ago\n\tif time.Since(cc.lastLoad) < 5*time.Second {\n\t\treturn nil\n\t}\n\n\tcc.mu.Lock()\n\tdefer cc.mu.Unlock()\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/middlewares/v1/crl.go#L35-L71","documentation":"decodeCRLs fails when a PEM block found in the CRL file is not a valid x509 revocation list (x509.ParseRevocationList errors). To avoid serving a truncated/corrupt CRL, the whole file is invalidated and the previous CRL version keeps being used.","triggerScenarios":"refresh() reads the CRL file (after detecting a modtime/size change), passes bytes to decodeCRLs; a PEM block's DER payload fails x509.ParseRevocationList -> 'could not parse file: %w'. Caused by corrupt downloads, wrong PEM type (e.g. a certificate pasted in the CRL file), or an old CRL format.","commonSituations":"CA renewal scripts write partial/empty CRL files; user concatenates cert+CRL; TLS CRL generated with an outdated tool producing a v1 list; file truncated mid-download.","solutions":["Regenerate/redownload the CRL file from the CA in a valid PEM DER format (openssl ca -gencrl / openssl crl -in crl.der -out crl.pem)","Check the file contains only PEM 'X509 CRL' blocks: openssl crl -in <file> -noout -text","Fix the process writing the CRL so it writes atomically (write temp file + rename) instead of truncating in place","Verify the LAPI api.crl_path configuration points to the actual CRL file, not a certificate"],"exampleFix":"// before: non-atomic CRL update by cron\nwget -O /etc/crowdsec/ssl/crl.pem http://ca/crl.pem\n// after: atomic replace\necho 'X509 CRL' >/dev/null; wget -O /etc/crowdsec/ssl/crl.pem.tmp http://ca/crl.pem && mv /etc/crowdsec/ssl/crl.pem.tmp /etc/crowdsec/ssl/crl.pem","handlingStrategy":"fallback","validationCode":"// validate the CRL PEM before pointing crowdsec at it\nb, _ := os.ReadFile(crlPath)\nblock, _ := pem.Decode(b)\nif block == nil || _, err := x509.ParseRevocationList(block.Bytes); err != nil {\n    return fmt.Errorf(\"invalid CRL file %s: %w\", crlPath, err)\n}","typeGuard":"func isValidPEMCRL(data []byte) bool {\n    block, _ := pem.Decode(data)\n    if block == nil {\n        return false\n    }\n    _, err := x509.ParseRevocationList(block.Bytes)\n    return err == nil\n}","tryCatchPattern":"if err := checker.Refresh(); err != nil {\n    if strings.Contains(err.Error(), \"could not parse file\") {\n        log.Warnf(\"CRL file invalid, keeping previous version: %v\", err)\n    }\n}","preventionTips":["Always publish CRLs as PEM 'X509 CRL' blocks only, never mixed with certificates","Write CRL files atomically (temp file + rename) in CA rotation scripts","Validate the CRL with 'openssl crl -in crl.pem -noout -text' after every regeneration","Monitor CRL file contents after CA upgrades or tooling changes"],"tags":["tls","x509","crl","pem","go"],"backgroundTag":"x509-parse-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}