Path traversal
-
What you'll see
AI code-review tools flag path traversal when Docly's filesystem functions (getFile, getJson, getFiles, getFolder, fileExists …) are called with paths derived from user input. Some of that advice is beside the point in Docly, and some of it is exactly right. -
What's actually happening
What Docly blocks. The filesystem functions reject any path containing
..or a backslash, and every path is absolute from the site root — there is no current directory. A payload like../../secretis refused, not resolved, so it cannot climb out of a folder.What it does not block. An absolute path can name any file in the site. That includes everything under
#/:#/Config,#/Services/oauth.json, your API scripts. The#/folder is not served to visitors, but a script that reads a path the visitor chose will read it for them.// #/API/doc.js — DANGEROUS: the caller picks any file in the site export default (path) => docly.getJson(path); // /API/doc?path=%23/Config → returns your secretsSo the risk is not traversal but an unrestricted path: user input used as the whole path, or as a path with its own slashes.
-
What to do
Build the path yourself from a fixed folder and a name, and validate the name before you use it:
// #/API/product.js export default (id) => { if (!docly.validateFilename(id)) return { error: "Invalid id" }; // rejects /, \, "." and ".." return docly.getJson("/Products/" + id); };- Never pass user input as the whole path, and never let it contain
/.docly.validateFilenamerejects slashes, backslashes,.and... - Where the set of valid values is known, check against an allowlist.
- Reading is not the end of it: check that the caller may see the document you found — see Check access on the document you write.
- Keep secrets under
#/anyway — it keeps them out of the published site — but do not rely on that alone when a script takes a path from the request.
When an AI tool reports classic
../traversal, the..part is handled by the platform. Check instead whether the input can choose the whole path. - Never pass user input as the whole path, and never let it contain
Last reviewed 22 Oct 2026