gastownhall/beads · error

invalid file path: directory traversal not allowed

Error message

invalid file path: directory traversal not allowed

What it means

validateMarkdownPath cleans the user-supplied file path and rejects it if the cleaned path still contains "..", since that indicates directory traversal. This guards the markdown import path (parseMarkdownFile) from reading files outside the intended workspace via paths like `../../etc/passwd`.

Source

Thrown at cmd/bd/markdown.go:113

		issue.AcceptanceCriteria = content
	case "assignee":
		issue.Assignee = strings.TrimSpace(content)
	case "labels":
		issue.Labels = parseLabels(content)
	case "dependencies", "deps":
		issue.Dependencies = parseDependencies(content)
	}
}

// validateMarkdownPath validates and cleans a markdown file path to prevent security issues.
// It checks for directory traversal attempts and ensures the file is a markdown file.
func validateMarkdownPath(path string) (string, error) {
	// Clean the path
	cleanPath := filepath.Clean(path)

	// Prevent directory traversal
	if strings.Contains(cleanPath, "..") {
		return "", fmt.Errorf("invalid file path: directory traversal not allowed")
	}

	// Ensure it's a markdown file
	ext := strings.ToLower(filepath.Ext(cleanPath))
	if ext != ".md" && ext != ".markdown" {
		return "", fmt.Errorf("invalid file type: only .md and .markdown files are supported")
	}

	// Check file exists and is not a directory
	info, err := os.Stat(cleanPath)
	if err != nil {
		return "", fmt.Errorf("cannot access file: %w", err)
	}
	if info.IsDir() {
		return "", fmt.Errorf("path is a directory, not a file")
	}

	return cleanPath, nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Pass a path without `..` — use a path relative to the current directory or an absolute path pointing directly at the file
  2. cd into the directory containing the markdown file and use a plain filename
  3. Resolve/symlink the file into the working directory first

Example fix

// before
parseMarkdownFile("../notes/tickets.md")
// after
parseMarkdownFile("/home/me/notes/tickets.md")   // or cd to the notes dir and use "tickets.md"
Defensive patterns

Strategy: validation

Validate before calling

func safePath(p string) error {
	c := filepath.Clean(p)
	if strings.Contains(c, "..") {
		return fmt.Errorf("traversal not allowed: %s", p)
	}
	return nil
}

Prevention

When it happens

Trigger: Calling bd's markdown import (e.g. `bd create -i file.md` style flows that call parseMarkdownFile) with a path containing `..`, such as `../notes.md`, `a/../../x.md`, or an absolute path whose cleaned form contains `..`.

Common situations: Scripting imports from sibling directories with relative paths; user-supplied file arguments interpolated into commands; tests passing traversal-style paths.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/f157af1f8c9cd152. Report an issue: GitHub.