{"record":{"id":"052f087cbdf47445","repo":"goharbor/harbor","slug":"file-should-readable-by-owner","errorCode":null,"errorMessage":"File {} should readable by owner","messagePattern":"File (.+?) should readable by owner","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"make/photon/prepare/models.py","lineNumber":86,"sourceCode":"        path = Path(os.path.join(internal_tls_dir, filename))\n\n        if not path.exists:\n            if filename == 'harbor_internal_ca.crt':\n                return\n            raise Exception('File {} not exist'.format(filename))\n\n        if not path.is_file:\n            raise Exception('invalid {}'.format(filename))\n\n        # check key file permission\n        if filename.endswith('.key') and not check_permission(path, mode=0o600):\n            raise Exception('key file {} permission is not 600'.format(filename))\n\n        # check certificate file\n        if filename.endswith('.crt'):\n            if not owner_can_read(path.stat().st_mode):\n                # check owner can read cert file\n                raise Exception('File {} should readable by owner'.format(filename))\n            if not san_existed(path):\n                # check SAN included\n                if filename == 'harbor_internal_ca.crt':\n                    return\n                raise Exception('cert file {} should include SAN'.format(filename))\n\n    def validate(self):\n        if not self.enabled:\n            # pass the validation if not enabled\n            return\n\n        if not internal_tls_dir.exists():\n            raise Exception('Internal dir for tls {} not exist'.format(internal_tls_dir))\n\n        for filename in self.required_filenames:\n            self._check(filename)\n\n    def prepare(self):","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/make/photon/prepare/models.py#L68-L104","documentation":"MergeNativeSummary in src/pkg/scan/report/summary.go merges two report summaries for mime types whose entries in SupportedSummaryMergers point at the native merger. It type-asserts each operand to *vuln.NativeReportSummary; this instance fires when the FIRST operand s1 is not that pointer type — nil, a different struct, or a value copy.","triggerScenarios":"Summary generation after a scan merges summaries resolved from report data where s1 decoded to another type, or a caller built the summary as a value (vuln.NativeReportSummary{}) instead of a pointer.","commonSituations":"Custom mime registrations that resolve summaries to a different model while the merger stays native; schema drift between adapter summary output and the vuln package; passing the report object instead of its summary.","solutions":["Ensure summaries are produced by the same GenerateNativeSummary path that yields *vuln.NativeReportSummary","Keep SupportedMimes / SupportedSummaryMergers mappings consistent for any custom mime type","Assert the concrete type before merging and report both operand types on failure"],"exampleFix":"// before\nsum, err := report.MergeNativeSummary(s1, s2) // s1 is `any`\n\n// after\nns1, ok1 := s1.(*vuln.NativeReportSummary)\nns2, ok2 := s2.(*vuln.NativeReportSummary)\nif !ok1 || !ok2 {\n    return nil, fmt.Errorf(\"cannot merge summaries: %T and %T, want *vuln.NativeReportSummary\", s1, s2)\n}\nsum, err := report.MergeNativeSummary(ns1, ns2)","handlingStrategy":"type-guard","validationCode":"if !isNativeSummary(s1) || !isNativeSummary(s2) {\n    return fmt.Errorf(\"summary operands must be native summaries, got %T and %T\", s1, s2)\n}","typeGuard":"func isNativeSummary(v any) bool {\n    _, ok := v.(*vuln.NativeReportSummary)\n    return ok\n}","tryCatchPattern":"if _, err := report.MergeNativeSummary(s1, s2); err != nil {\n    if strings.Contains(err.Error(), \"native report summary required\") {\n        log.Printf(\"summary mime/data mismatch: s1=%T s2=%T\", s1, s2)\n    }\n    return err\n}","preventionTips":["Generate summaries only through the registered SummaryGenerator for the mime type","Keep summary models and mergers versioned together with the adapter","Never hand-construct summary operands for merging"],"tags":["go","harbor","type-assertion","scan","summary"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}