You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
create_or_update_file writes to the wrong file when the path contains # or ? #3427
create_or_update_file with path: "docs/C#/intro.md" commits the content to a file named docs/C and reports success. A ? does the same (notes/what?.md is written as notes/what).
The path goes into the request URL unescaped: go-github's RepositoriesService.CreateFile builds repos/{owner}/{repo}/contents/{path} with no escaping, so everything from # on becomes a URL fragment and everything from ? on becomes a query string. The checks that run first (the existing-file / SHA lookup and the symlink check) go through GetContents, which does escape the path, so they look at the right file while the write goes to another.
Affected version
v1.14.0 and main at 71ef826 (pkg/github/repositories.go, the CreateFile call in CreateOrUpdateFile).
Expected: a file at docs/C#/intro.md (the request goes to PUT /repos/<you>/<test repo>/contents/docs/C%23/intro.md).
Actual: the request goes to PUT /repos/<you>/<test repo>/contents/docs/C, the commit creates a file named docs/C, and the tool result reports success with "path": "docs/C". If docs/C already exists as a file, it is overwritten.
Logs
Request seen by a mock server for the call above:
GET /repos/owner/repo/contents/docs/C%23/intro.md -> 404 (existence check, escaped)
PUT /repos/owner/repo/contents/docs/C (the write, unescaped)
I have a small fix with a regression test ready and can open a PR: escape each path segment before calling CreateFile, the same way escapeGitTreeish already does for tree lookups.
Activity