{"record":{"id":"1746ac7a2ba9adb0","repo":"HeyPuter/puter","slug":"forbidden-1746ac","errorCode":"forbidden","errorMessage":"kv: `${method}` is not available on another app's data","messagePattern":"kv: `(.+?)` is not available on another app's data","errorType":"http","errorClass":"HttpError","httpStatus":403,"severity":"error","filePath":"src/backend/drivers/kv/KVStoreDriver.ts","lineNumber":205,"sourceCode":"                { legacyCode: 'bad_request' },\n            );\n        }\n\n        await this.#assertCrossAppKvAccess(actor!, appUuid, method, args);\n        return { actor, namespaceAppUuid: appUuid };\n    }\n\n    async #assertCrossAppKvAccess(\n        actor: Actor,\n        targetAppUid: string,\n        method: string,\n        args: KvCallArgs,\n    ): Promise<void> {\n        // `null` = no scope reaches it (`flush` is namespace-wide, not an\n        // entry op); `undefined` = unmapped method. Both fail closed.\n        const op = APP_DATA_KV_METHOD_OPS[method];\n        if (!op) {\n            throw new HttpError(\n                403,\n                `kv: \\`${method}\\` is not available on another app's data`,\n                { legacyCode: 'forbidden' },\n            );\n        }\n\n        const target = await this.stores.app.getByUid(targetAppUid);\n        if (!target) {\n            throw new HttpError(404, `entity_not_found: app:${targetAppUid}`, {\n                legacyCode: 'subject_does_not_exist',\n            });\n        }\n        if (!appDataSharingAllowed(target)) {\n            throw new HttpError(\n                403,\n                'kv: this app does not share its data with other apps',\n                { legacyCode: 'forbidden' },\n            );","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/kv/KVStoreDriver.ts#L187-L223","documentation":"Thrown by `#assertCrossAppKvAccess` when a KV method is invoked against another app's namespace but the method has no mapped cross-app operation in `APP_DATA_KV_METHOD_OPS` (value is `null` or `undefined`). `flush` maps to `null` (namespace-wide, not an entry op), so it can never run cross-app; any unmapped method also fails closed. Returns HTTP 403 with legacyCode `forbidden`.","triggerScenarios":"Calling `kv.flush({ appUuid: otherApp })` (the canonical case), or any future/unmapped method, while targeting another app's namespace. The map defines which ops are even eligible for cross-app access.","commonSituations":"Admin/tooling trying to flush another app's namespace; a generic KV wrapper that forwards arbitrary method names plus an appUuid; assuming flush is permitted because get/set are.","solutions":["Do not flush another app's namespace; flush is own-namespace only.","For cross-app data, restrict to mapped entry ops (get/set/list/del/incr/decr/update/expire/expireAt/add/batchPut).","Remove the `appUuid` override to operate on your own namespace."],"exampleFix":"// before\nkv.flush({ appUuid: otherAppUid }); // 403\n\n// after\n// flush only your own namespace\nkv.flush();\n// or target specific keys cross-app\nawait kv.del('k', { appUuid: otherAppUid });","handlingStrategy":"validation","validationCode":"const CROSS_APP_OK = new Set(['get','set','list','del','remove','incr','decr','add','update','batchPut','expire','expireAt']);\nif (appUuid && appUuid !== ownAppUid && !CROSS_APP_OK.has(method)) {\n  throw new Error(`${method} is not available on another app's data`);\n}","typeGuard":"/** @param {string} method @param {string|undefined} appUuid @param {string} ownUid @returns {boolean} */\nfunction isAllowedCrossAppMethod(method, appUuid, ownUid) {\n  if (!appUuid || appUuid === ownUid) return true;\n  return new Set(['get','set','list','del','remove','incr','decr','add','update','batchPut','expire','expireAt']).has(method);\n}","tryCatchPattern":"try {\n  await kv.flush({ appUuid });\n} catch (e) {\n  if (e.code === 'forbidden' && e.message.includes('not available on another app')) { /* flush own namespace only */ await kv.flush(); return; }\n  throw e;\n}","preventionTips":["Never flush another app's namespace; flush is own-namespace only.","Restrict cross-app KV calls to mapped entry ops.","Drop the appUuid override when operating on your own data."],"tags":["kv","cross-app","forbidden","permissions","driver"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}