{"record":{"id":"e364334ae1c7306d","repo":"siyuan-note/siyuan","slug":"local-asset-path-is-not-allowed","errorCode":null,"errorMessage":"local asset path is not allowed","messagePattern":"local asset path is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/upload.go","lineNumber":174,"sourceCode":"\t\t\treturn\n\t\t}\n\t\tboxID = bt.BoxID\n\t\tdocDirLocalPath := filepath.Join(util.DataDir, boxID, path.Dir(bt.Path))\n\t\tassetsDirPath = getAssetsDir(filepath.Join(util.DataDir, boxID), docDirLocalPath)\n\t}\n\tif !gulu.File.IsExist(assetsDirPath) {\n\t\tif err = os.MkdirAll(assetsDirPath, 0755); err != nil {\n\t\t\treturn\n\t\t}\n\t}\n\n\tfor index, assetAbsPath := range assetAbsPaths {\n\t\tif strings.HasPrefix(strings.ToLower(assetAbsPath), \"file://\") {\n\t\t\tassetAbsPath = util.FileURLToLocalPath(assetAbsPath)\n\t\t}\n\t\tbaseName := filepath.Base(assetAbsPath)\n\t\tif validateHTMLPath && (util.IsSensitivePath(assetAbsPath) || EncryptedRawPathBoxID(assetAbsPath) != \"\") {\n\t\t\trecordAssetUploadFailure(&failedFiles, index, baseName, errors.New(\"local asset path is not allowed\"))\n\t\t\tcontinue\n\t\t}\n\t\tfName := baseName\n\t\tfName = util.FilterUploadFileName(fName)\n\t\text := filepath.Ext(fName)\n\t\tfName = strings.TrimSuffix(fName, ext)\n\t\text = strings.ToLower(ext)\n\t\tfName += ext\n\t\tif gulu.File.IsDir(assetAbsPath) || !isUpload {\n\t\t\tif !strings.HasPrefix(assetAbsPath, \"\\\\\\\\\") {\n\t\t\t\tassetAbsPath = \"file://\" + assetAbsPath\n\t\t\t}\n\t\t\trecordAssetUploadSuccess(succMap, &succFiles, index, baseName, assetAbsPath)\n\t\t\tcontinue\n\t\t}\n\n\t\tif gulu.File.IsSubPath(assetsDirPath, assetAbsPath) {\n\t\t\t// 已经位于 assets 目录下的资源文件不处理","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/upload.go#L156-L192","documentation":"When inserting assets from an HTML context (validateHTMLPath is true, i.e. InsertHTMLLocalAssets), each absolute path is screened with util.IsSensitivePath and EncryptedRawPathBoxID. Paths deemed sensitive (e.g. pointing into system/config locations) or located inside an encrypted notebook's raw storage are rejected with \"local asset path is not allowed\" and skipped as a per-file failure.","triggerScenarios":"Calling InsertHTMLLocalAssets with a file:// URL or absolute path that resolves to a sensitive path (per util.IsSensitivePath), or a path inside an encrypted notebook's raw data area; HTML paste/drop flows referencing such locations.","commonSituations":"Pasting HTML whose embedded images point at restricted local paths; browser-clipper or automation flows supplying paths under the workspace's protected directories; attempting to re-import a file that lives inside an encrypted box's raw storage.","solutions":["Copy the file to a normal, non-sensitive location (e.g. a temp directory) and insert from there.","Check the path with util.IsSensitivePath before calling; skip or relocate files inside encrypted notebook raw storage.","Use the standard Upload API (multipart form) instead of local-path insertion for files originating from protected locations."],"exampleFix":"// before\nmodel.InsertHTMLLocalAssets(docID, []string{\"/workspace/data/encrypted-box/raw/image.png\"})\n// after\ntmp := filepath.Join(os.TempDir(), \"image.png\")\ncopyFile(tmp, \"/workspace/data/encrypted-box/raw/image.png\")\nmodel.InsertHTMLLocalAssets(docID, []string{tmp})","handlingStrategy":"validation","validationCode":"func insertableHTMLAsset(p string) bool {\n    if strings.HasPrefix(strings.ToLower(p), \"file://\") {\n        p = util.FileURLToLocalPath(p)\n    }\n    return !util.IsSensitivePath(p) && model.EncryptedRawPathBoxID(p) == \"\"\n}","typeGuard":null,"tryCatchPattern":"_, _, failed, err := model.InsertHTMLLocalAssets(docID, paths)\nfor _, f := range failed {\n    if f.Error == \"local asset path is not allowed\" {\n        // copy to temp and retry that single file\n        tmp := copyToTemp(paths[f.Index])\n        model.InsertHTMLLocalAssets(docID, []string{tmp})\n    }\n}","preventionTips":["Never reference files inside the workspace's protected or encrypted raw directories in HTML.","Stage external files in a plain temp/user directory before inserting.","Screen every path with util.IsSensitivePath during development of paste/clipper flows."],"tags":["security","path-validation","assets"],"backgroundTag":"path-traversal-blocked","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}