{"record":{"id":"e807fd957c512132","repo":"toeverything/AFFiNE","slug":"invalid-mobile-payload-token-malformed-file-url","errorCode":null,"errorMessage":"Invalid mobile payload token: malformed file URL","messagePattern":"Invalid mobile payload token: malformed file URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/frontend/apps/mobile-shared/src/nbstore/payload.ts","lineNumber":33,"sourceCode":"  if (!trimmedPath) {\n    throw new Error('Invalid mobile payload token: empty file path');\n  }\n\n  return trimmedPath.startsWith('file://')\n    ? trimmedPath\n    : `file://${trimmedPath}`;\n}\n\nfunction assertMobileCachePath(fileUrl: string): void {\n  let pathname: string;\n  try {\n    const parsedUrl = new URL(fileUrl);\n    if (parsedUrl.protocol !== 'file:') {\n      throw new Error('unexpected protocol');\n    }\n    pathname = parsedUrl.pathname;\n  } catch {\n    throw new Error('Invalid mobile payload token: malformed file URL');\n  }\n\n  let decodedSegments: string[];\n  try {\n    decodedSegments = pathname\n      .split('/')\n      .filter(Boolean)\n      .map(segment => {\n        const decoded = decodeURIComponent(segment);\n        if (\n          !decoded ||\n          decoded === '.' ||\n          decoded === '..' ||\n          decoded.includes('/') ||\n          decoded.includes('\\\\')\n        ) {\n          throw new Error('path traversal');\n        }","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/frontend/apps/mobile-shared/src/nbstore/payload.ts#L15-L51","documentation":"assertMobileCachePath parses the file URL and throws 'malformed file URL' if URL parsing fails or the protocol is not file:, then validates the path resolves into the app's cache directories — an anti-tamper check on payload file references.","triggerScenarios":"Thrown in assertMobileCachePath when the token path cannot be parsed as a URL or does not use the file: protocol, so the payload location is rejected as malformed.","commonSituations":"Occurs when a blob token contains a hand-edited or non-file URL instead of a device cache path. The payload must be re-created from the original blob source.","solutions":["Verify the token encodes a valid file:// URL; re-encode the file URL with proper escaping before constructing the token.","Reject and regenerate malformed tokens at the source."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}