{"record":{"id":"774e0bad6d06888e","repo":"goharbor/harbor","slug":"cert-file-should-be-owned-by-user-with-uid-1000","errorCode":null,"errorMessage":"Cert File {} should be owned by user with uid 10000 or readable by others","messagePattern":"Cert File (.+?) should be owned by user with uid 10000 or readable by others","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/utils/configs.py","lineNumber":73,"sourceCode":"        if storage_provider_config == \"\":\n            raise Exception(\n                \"Error: no provider configurations are provided for provider %s\" % storage_provider_name)\n    # ca_bundle validate\n    if conf.get('registry_custom_ca_bundle_path'):\n        registry_custom_ca_bundle_path = conf.get('registry_custom_ca_bundle_path') or ''\n        if registry_custom_ca_bundle_path.startswith('/data/'):\n            ca_bundle_host_path = registry_custom_ca_bundle_path\n        else:\n            ca_bundle_host_path = os.path.join(host_root_dir, registry_custom_ca_bundle_path.lstrip('/'))\n        try:\n            uid = os.stat(ca_bundle_host_path).st_uid\n            st_mode = os.stat(ca_bundle_host_path).st_mode\n        except Exception as e:\n            logging.error(e)\n            raise Exception('Can not get file info')\n        err_msg = 'Cert File {} should be owned by user with uid 10000 or readable by others'.format(registry_custom_ca_bundle_path)\n        if uid == DEFAULT_UID and not owner_can_read(st_mode):\n            raise Exception(err_msg)\n        if uid != DEFAULT_UID and not other_can_read(st_mode):\n            raise Exception(err_msg)\n\n    # TODO:\n    # If user enable trust cert dir, need check if the files in this dir is readable.\n\n    if conf.get('trace'):\n        conf['trace'].validate()\n\n    if conf.get('purge_upload'):\n        conf['purge_upload'].validate()\n\n    if conf.get('cache'):\n        conf['cache'].validate()\n\n    if conf.get('core'):\n        conf['core'].validate()\n","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/utils/configs.py#L55-L91","documentation":"Thrown by validate() in make/photon/prepare/utils/configs.py when the registry custom CA bundle is owned by uid 10000 (DEFAULT_UID, Harbor's runtime user) but the owner-read permission bit is missing (owner_can_read(st_mode) is false). A file owned by the Harbor uid that it cannot read is treated as a misconfiguration and blocks prepare, since registry/core would fail to load it.","triggerScenarios":"harbor.yml sets storage_service.ca_bundle to a file whose stat shows st_uid == 10000 and whose mode lacks 0400 for the owner — e.g. mode 0200, 0000, or 0260 after restrictive chmods.","commonSituations":"Security hardening scripts that strip read bits; files restored from backups with odd modes; admins chowning to 10000 but not adjusting mode.","solutions":["Restore the owner-read bit: chmod u+r <ca_bundle> (or chmod 0400/0444)","Confirm with: stat -c '%u %a' <ca_bundle>  # expect 10000 and a mode with owner r","Re-run ./install.sh","If the file is deliberately root-owned, see the sibling check (error 30) and make it world-readable instead"],"exampleFix":"# on the Harbor host (before)\n$ stat -c '%u %a' /data/secret/root-ca.pem\n10000 200\n\n# after\n$ chmod 0400 /data/secret/root-ca.pem\n$ stat -c '%u %a' /data/secret/root-ca.pem\n10000 400","handlingStrategy":"validation","validationCode":"import os, stat as st\np = cfg.get('storage_service', {}).get('ca_bundle')\nif p and os.path.isfile(p):\n    s = os.stat(p)\n    if s.st_uid == 10000 and not (s.st_mode & st.S_IRUSR):\n        raise SystemExit('ca_bundle owned by 10000 lacks owner read: chmod u+r %s' % p)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After chowning cert files to 10000, always verify mode includes 0400","Use chmod 0400/0444 for CA bundles consumed by Harbor","Add a stat-based preflight to install runbooks for TLS material"],"tags":["harbor","storage","ca-certificate","file-permissions","security"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}