multica-ai/multica · error

--%s path %q resolves outside the current working directory;

Error message

--%s path %q resolves outside the current working directory; write agent temp files inside the task workdir (e.g. ./%s.md) rather than machine-shared paths like /tmp, where another run's stale file can be read by mistake. Pass --allow-external-file to override.

What it means

A file-content flag (--description-file, --content-file, etc.) points to a path that resolves outside the process working directory. The CLI enforces this to prevent a stale-file content leak: an earlier incident had one run silently read a /tmp file written by a different run. The check is symlink-aware on both sides, so aliasing a path into the workdir via symlink does not bypass it.

Source

Thrown at server/cmd/multica/cmd_issue.go:112

//
// Agent task workdirs are isolated per profile and per task; machine-shared
// scratch paths like /tmp are not. MUL-4252 traced a cross-environment context
// leak to exactly this gap: a quick-create run wrote its description to a fixed
// /tmp/desc.md, the write silently failed because a *different* environment's
// run had left a stale file there minutes earlier, and --description-file then
// fed that stale content into the new issue. Requiring the file to live under
// the workdir turns "silently read another run's file" into a loud command
// failure — an "incorrect content" bug becomes a "command errored" bug.
func ensureFileFlagWithinWorkdir(cmd *cobra.Command, fileFlag, flagName, filePath string) error {
	if allow, _ := cmd.Flags().GetBool("allow-external-file"); allow {
		return nil
	}
	within, err := fileWithinWorkingDir(filePath)
	if err != nil {
		return fmt.Errorf("resolve --%s path %q: %w", fileFlag, filePath, err)
	}
	if !within {
		return fmt.Errorf(
			"--%s path %q resolves outside the current working directory; "+
				"write agent temp files inside the task workdir (e.g. ./%s.md) rather than machine-shared "+
				"paths like /tmp, where another run's stale file can be read by mistake. "+
				"Pass --allow-external-file to override.",
			fileFlag, filePath, flagName)
	}
	return nil
}

// fileWithinWorkingDir reports whether filePath resolves to a location inside
// the process working directory. Both sides are symlink-resolved so aliased
// roots (e.g. macOS /tmp -> /private/tmp) and symlinks planted inside the
// workdir fail closed. A path that does not exist yet is judged on its cleaned
// absolute form so the caller's os.ReadFile still surfaces the real not-found
// error afterwards.
func fileWithinWorkingDir(filePath string) (bool, error) {
	cwd, err := os.Getwd()
	if err != nil {

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Write the temp file inside the current working directory (e.g. ./desc.md) as the error message suggests, then re-run.
  2. If the outside location is intentional and you accept the stale-file risk, add --allow-external-file to the command.
  3. If you expected the path to be inside the workdir, check for symlinks (realpath <path>) — the guard resolves them, so the physical location is what counts.
  4. Verify the process is running from the directory you think (pwd), since the boundary is the CWD, not the repo root.

Example fix

# before
printf 'content' > /tmp/desc.md
multica issue create --title T --description-file /tmp/desc.md
# after
printf 'content' > ./desc.md
multica issue create --title T --description-file ./desc.md
Defensive patterns

Strategy: validation

Validate before calling

# ensure the file is physically inside the CWD (symlinks resolved)
case "$(realpath "$DESC_FILE")" in "$(realpath .)"/*) ;; *) echo "file outside workdir" >&2; exit 1;; esac

Prevention

When it happens

Trigger: Passing an absolute path like /tmp/desc.md, a relative path that climbs out of the workdir (../../shared/desc.md), or a workdir symlink pointing to an outside location — unless --allow-external-file is set. fileWithinWorkingDir resolves symlinks on both the file and the working directory, so macOS /tmp -> /private/tmp style aliases are still detected.

Common situations: Agents/scripts writing scratch files to /tmp or other machine-shared dirs and feeding them to the CLI; CI jobs sharing a temp dir between parallel runs; a symlink inside the repo pointing at a home-directory file.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/9793e1c78d3e571f. Report an issue: GitHub.