{"record":{"id":"b357caa82ef97c17","repo":"Tencent/WeKnora","slug":"storage-path-is-outside-kb-scoped-exports-namespac","errorCode":null,"errorMessage":"storage path is outside KB-scoped exports namespace","messagePattern":"storage path is outside KB-scoped exports namespace","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/presign.go","lineNumber":136,"sourceCode":"\t\treturn fmt.Errorf(\"storage path has no tenant segment\")\n\t}\n\tif pathTenant != tenantID {\n\t\treturn fmt.Errorf(\"storage path workspace mismatch\")\n\t}\n\treturn nil\n}\n\n// ValidateKBScopedStoragePath is used by GET /knowledge-bases/:id/files. It\n// requires the path to belong to the KB owner tenant and to live under the\n// exports/ namespace used for embedded images (SaveBytes / multimodal output).\n// This prevents borrowers with shared-KB read access from using the proxy to\n// fetch arbitrary owner-tenant objects such as raw knowledge uploads.\nfunc ValidateKBScopedStoragePath(filePath string, tenantID uint64) error {\n\tif err := ValidateStoragePathTenant(filePath, tenantID); err != nil {\n\t\treturn err\n\t}\n\tif !storagePathHasExportsScope(filePath, tenantID) {\n\t\treturn fmt.Errorf(\"storage path is outside KB-scoped exports namespace\")\n\t}\n\treturn nil\n}\n\n// storageBackendScheme wraps a provider:// path with the concrete instance id:\n// storage://<backendID>/<provider>://...  It is duplicated here (rather than\n// reusing types.ParseStorageBackendPath) because internal/types already imports\n// internal/utils, so a reverse import would create a cycle.\nconst storageBackendScheme = \"storage://\"\n\n// unwrapStorageBackendPath strips a leading storage://<backendID>/ wrapper and\n// returns the inner provider:// path. Non-wrapped paths are returned unchanged.\n// This keeps tenant/exports parsing anchored on the provider path instead of\n// relying on the backend id happening not to look like a tenant segment.\nfunc unwrapStorageBackendPath(filePath string) string {\n\tif !strings.HasPrefix(filePath, storageBackendScheme) {\n\t\treturn filePath\n\t}","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/utils/presign.go#L118-L154","documentation":"Authorization guard in ValidateKBScopedStoragePath (presign.go): the storage path passes tenant ownership checks but is not under the exports/ namespace used for KB-embedded images. This blocks borrowers with shared-KB read access from proxying arbitrary owner-tenant objects such as raw knowledge uploads.","triggerScenarios":"Thrown at internal/utils/presign.go:136 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Only presign paths under the KB exports/ namespace","Serve other object types through dedicated, permission-checked endpoints","Treat attempts to reach non-export paths as an access violation"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}