{"record":{"id":"a8c78f2549115793","repo":"larksuite/cli","slug":"invalid-s-q-must-be-an-absolute-path-to-a-pem-f","errorCode":null,"errorMessage":"invalid %s %q: must be an absolute path to a PEM file","messagePattern":"invalid (.+?) %q: must be an absolute path to a PEM file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/transport/tls_ca.go","lineNumber":27,"sourceCode":"\t\"fmt\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/larksuite/cli/internal/binding\"\n\t\"github.com/larksuite/cli/internal/envvars\"\n\t\"github.com/larksuite/cli/internal/vfs\"\n)\n\n// applyExtraRootCA augments t with an additional PEM bundle used for configured proxy\n// TLS interception.\nfunc applyExtraRootCA(t *http.Transport, caPath string) error {\n\tcaPath = strings.TrimSpace(caPath)\n\tif caPath == \"\" {\n\t\treturn nil\n\t}\n\tif !filepath.IsAbs(caPath) {\n\t\treturn fmt.Errorf(\"invalid %s %q: must be an absolute path to a PEM file\", envvars.CliCAPath, caPath)\n\t}\n\tsafeCAPath, err := binding.AssertSecurePath(binding.AuditParams{\n\t\tTargetPath:            caPath,\n\t\tLabel:                 envvars.CliCAPath,\n\t\tAllowReadableByOthers: true,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unsafe %s %q: %w\", envvars.CliCAPath, caPath, err)\n\t}\n\tpemBytes, err := vfs.ReadFile(safeCAPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read %s %q: %w\", envvars.CliCAPath, caPath, err)\n\t}\n\n\t// Augment the system trust store. Do NOT silently discard a SystemCertPool\n\t// error: falling back to an empty pool would make this transport trust ONLY\n\t// the extra CA (dropping all system roots), which narrows trust unexpectedly\n\t// and could break TLS to legitimate endpoints. Fail closed instead.","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/transport/tls_ca.go#L9-L45","documentation":"The extra root CA path (CLI_CA_PATH) is empty after trimming or is a relative path. For security, the CLI only accepts an absolute path to a PEM file so the trust anchor cannot be resolved ambiguously relative to the working directory. applyExtraRootCA rejects anything that is not absolute.","triggerScenarios":"Setting CLI_CA_PATH to something like 'certs/ca.pem' or './ca.pem' and starting the CLI; ApplyToTransport -> applyExtraRootCA performs filepath.IsAbs and fails.","commonSituations":"Relative path from internal docs or a colleague's setup where the working directory differed; CI runners executing from an unexpected cwd; value pointing to a directory or non-PEM file instead of the CA bundle.","solutions":["Set CLI_CA_PATH to an absolute path, e.g. /etc/ssl/certs/corp-ca.pem.","Convert a relative path with an absolute prefix: use \"$(pwd)/ca.pem\" or realpath.","Ensure the target is an actual PEM-encoded certificate file readable by the CLI user."],"exampleFix":"// before\nexport LARKSUITE_CLI_CA_PATH=\"./certs/ca.pem\"\n// after\nexport LARKSUITE_CLI_CA_PATH=\"/etc/lark-cli/certs/ca.pem\"","handlingStrategy":"validation","validationCode":"p := strings.TrimSpace(os.Getenv(\"LARKSUITE_CLI_CA_PATH\"))\nif p != \"\" && !filepath.IsAbs(p) {\n\treturn fmt.Errorf(\"CA path must be absolute: %s\", p)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always store the CA bundle at a fixed absolute location (e.g. /etc/lark-cli/ca.pem).","Use $(realpath ca.pem) when generating config from relative paths.","Pin the path in provisioning tooling rather than ad-hoc shell exports."],"tags":["tls","configuration","certificate"],"backgroundTag":"invalid-ca-path","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}