{"record":{"id":"02fe3a14048bc9f9","repo":"siyuan-note/siyuan","slug":"w-selected-vault-path-is-sensitive-wrapped-obsidian-vault","errorCode":null,"errorMessage":"%w: selected Vault path is sensitive (wrapped: Obsidian Vault path is unsafe)","messagePattern":"%w: selected Vault path is sensitive \\(wrapped: Obsidian Vault path is unsafe\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import_obsidian.go","lineNumber":577,"sourceCode":"\tif strings.TrimSpace(localPath) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"%w: path is empty\", errObsidianVaultUnreadable)\n\t}\n\tabs, err := filepath.Abs(filepath.Clean(localPath))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%w: normalize Vault path: %v\", errObsidianVaultUnreadable, err)\n\t}\n\tinfo, err := os.Lstat(abs)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%w: read Vault root: %v\", errObsidianVaultUnreadable, err)\n\t}\n\tif !info.IsDir() {\n\t\treturn \"\", errObsidianVaultNotDirectory\n\t}\n\tif info.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(abs) {\n\t\treturn \"\", fmt.Errorf(\"%w: Vault root is a symbolic link or reparse point\", errObsidianVaultUnsafePath)\n\t}\n\tif util.IsSensitivePath(abs) {\n\t\treturn \"\", fmt.Errorf(\"%w: selected Vault path is sensitive\", errObsidianVaultUnsafePath)\n\t}\n\tworkspace, _ := filepath.Abs(filepath.Clean(util.WorkspaceDir))\n\tif sameObsidianPath(abs, workspace) || gulu.File.IsSubPath(workspace, abs) || gulu.File.IsSubPath(abs, workspace) {\n\t\treturn \"\", fmt.Errorf(\"%w: Vault root and SiYuan workspace contain each other\", errObsidianVaultUnsafePath)\n\t}\n\tconfigPath := filepath.Join(abs, \".obsidian\")\n\tconfigInfo, statErr := os.Lstat(configPath)\n\tif statErr != nil {\n\t\tif os.IsNotExist(statErr) {\n\t\t\treturn \"\", errObsidianVaultConfigMissing\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"%w: read Vault config directory: %v\", errObsidianVaultUnreadable, statErr)\n\t}\n\tif !configInfo.IsDir() || configInfo.Mode()&os.ModeSymlink != 0 || isObsidianResolvedLink(configPath) {\n\t\treturn \"\", errObsidianVaultConfigMissing\n\t}\n\treturn abs, nil\n}","sourceCodeStart":559,"sourceCodeEnd":595,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/import_obsidian.go#L559-L595","documentation":"validateObsidianVaultRoot wraps errObsidianVaultUnsafePath with 'selected Vault path is sensitive' when util.IsSensitivePath(abs) matches — the chosen path is a system-critical location SiYuan refuses to touch (e.g. root, /etc, /usr, Windows system dirs). This protects users from importing from or writing near OS infrastructure.","triggerScenarios":"Calling the analyze/import API with localPath pointing at a sensitive system directory such as '/', '/etc', 'C:\\Windows', or the user's home root, depending on IsSensitivePath rules.","commonSituations":"Misconfigured automation defaulting to '/'; user mistakenly picking a drive root in the folder dialog; a bug in path resolution that collapses the path to a system root.","solutions":["Choose the actual Obsidian vault folder (one containing a .obsidian directory), not a drive/system root","Fix the code or config that resolves to the sensitive path (log the abs path to inspect it)","Move the vault to a normal user directory such as Documents and select that"],"exampleFix":"// before\nanalyzeVault({ localPath: '/' }); // sensitive\n// after\nanalyzeVault({ localPath: '/home/user/Documents/MyVault' });","handlingStrategy":"validation","validationCode":"const real = await fs.promises.realpath(vaultPath);\nif (isSensitiveSystemPath(real)) throw new Error('Choose the vault folder, not a system directory');\nif (!fs.existsSync(path.join(real, '.obsidian'))) warn('Folder does not look like an Obsidian vault');","typeGuard":null,"tryCatchPattern":"try { await analyzeVault(opts); } catch (e) { if (isVaultUnsafe(e) && /sensitive/.test(String(e))) showFolderPickerAgain(); else throw e; }","preventionTips":["Always pick the vault folder through the folder picker, never type drive roots","Verify the folder contains a .obsidian subfolder before importing","Log the resolved absolute path to catch resolution bugs that collapse to system roots"],"tags":["obsidian","security","sensitive-path","validation"],"backgroundTag":"path-traversal-blocked","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}