Guide

Path canonicalisation rules — the core keeps writes in bounds

What target_path you can pass to `upload.create_link` and `upload.write`. Why the rules are strict — no project can escape its own prefix — and how to work around them.

5/18/2026 · connect0 · 2 min

Every path is canonicalised at the core, so no write can escape the project prefix the system controls.

Every upload tool runs the target_path through the same canonicalisation function. The rules are deliberately narrow:

RuleWhy
Must be relative (no leading /).The projects/<id>/ prefix is server-controlled; you can't escape it.
No .. segments.Traversal would let one project write under another's prefix.
No segment starts with .Reserves .git, .env, .cache, etc. for our future use.
Characters in [A-Za-z0-9._-/] only.Easy to validate, easy to interpolate into shell, easy to log.
≤ 256 chars.R2 key length cap with headroom.

Examples

Accepted:

  • foo.txt
  • data/sales.csv
  • nested/deeper/and-deeper/file.json
  • 2026-Q1/report-final_v2.pdf

Rejected:

  • /foo — leading slash.
  • ../etc/passwd.. segment.
  • foo/../bar.. segment.
  • .git/HEAD — segment starts with ..
  • foo/.env — same.
  • My File.csv — space.
  • report?.pdf — query-string character.
  • foo/ — empty segment.

Filename sanitisation in the dashboard

The dashboard drag-drop UI doesn't reject files with bad characters — it sanitises them. Sales Q1 / 2026.csv becomes Sales_Q1___2026.csv automatically. The MCP tools don't sanitise; they reject. This is intentional: the dashboard is for humans who want it to "just work," MCP is for agents that should pass canonicalised paths in the first place.

What if I need a space in my filename?

You don't. Spaces in filenames have a long history of breaking things — shell escaping bugs, URL encoding bugs, audit-log parsing bugs. Use _ or -. Every tool that touches the filesystem will thank you.

What if my filename has Unicode?

Same answer — ASCII subset only. We're aware this is restrictive for non-Latin alphabets. If it becomes a real complaint we'll add a relaxed mode behind a flag, but the current [A-Za-z0-9._-/] is the defensible default.

How to work around the rules

  • Generated from a user-supplied name. Strip / replace before passing. Same logic the dashboard uses: name.replace(/[^A-Za-z0-9._-]/g, '_').
  • Need a hidden-config-style file. Drop the leading . and have the agent rename inside the sandbox via sh "mv /workspace/env /workspace/.env". The path inside the sandbox isn't subject to the canonicalisation rules — only the upload key is.

Next steps

Where this fits

This is the One system of record pillar of connect0 — the core that connects everything your company runs on. The core owns the projects/<id>/ prefix and canonicalises every path against it, so isolation between projects is enforced by the system, not left to the caller. Start building → · All guides →