Validate slugs, version tags, and Content-Disposition at all boundaries (C-1, M-5, M-8) #96
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
qwc-open/asiakirjat!96
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/input-validation-boundaries"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Workstream item #1 from the local audit. Three findings, all involving attacker-controlled strings flowing into filesystem paths or response headers without validation. One PR because they share the same fix (a new
internal/validationpackage).r.FormValue("version")flowed directly intostorage.EnsureVersionDir/storage.VersionPath. An editor uploading withversion=../../<other-project>/<tag>could write extracted files outside the project's version directory, and on extraction failurestorage.DeleteVersionwouldos.RemoveAllthe traversed path — arbitrary directory write/delete.handleAdminCreateProject/handleAdminUpdateProjectdid not validate the formslug, while the API and auto-create paths did. Admin could create slugs containing/,.., whitespace, etc.fmt.Sprintfand a quoted attacker-controlled tag — CR/LF or"could inject header parameters.Changes
internal/validationpackage withIsValidSlugandIsValidVersionTag(strict regexes; unit tests cover path separators, CR/LF, leading dot, length).isValidSlugout ofinternal/handler/auto_create.go. All three callers (API auto-create, API create-project, web upload) now usevalidation.IsValidSlug.validation.IsValidVersionTagat both upload entry points (web + API) before any filesystem call.validation.IsValidSlugintohandleAdminCreateProjectandhandleAdminUpdateProject.fmt.SprintfContent-Disposition withmime.FormatMediaTypeplus a plain-ASCII fallback. The existing download test was updated to the RFC-correct unquoted form for token filenames.upload_validation_test.gocovering malicious inputs against both the API upload and admin-create endpoints.Test plan
go test ./...passesversion=../escape(and other malicious tags) is rejected with 400/, uppercase, whitespace, etc.attachment; filename=slug-tag.ext)🤖 Generated with Claude Code
Three findings from the local audit, all involving attacker-controlled strings flowing into filesystem paths or response headers without validation: C-1 (Critical): r.FormValue("version") flowed directly into the project's storage filesystem path via storage.EnsureVersionDir / storage.VersionPath. An editor uploading with version=../../<other-project>/<tag> could write extracted files outside the project's version directory, and on extraction failure storage.DeleteVersion would os.RemoveAll the traversed path. M-5 (Medium): handleAdminCreateProject / handleAdminUpdateProject did not validate the form's slug field, while the API and auto-create paths did via isValidSlug. An admin could create projects with slugs containing "/", "..", or whitespace, corrupting the storage tree. M-8 (Medium): the version download path built Content-Disposition with fmt.Sprintf and a quoted filename; the version tag was attacker-controlled and could contain CR/LF or " to inject header parameters. Changes: - New internal/validation package with IsValidSlug and IsValidVersionTag. Strict regexes; unit tests cover the dangerous inputs (path separators, CR/LF, leading dot, length bounds). - Move isValidSlug from internal/handler/auto_create.go to the new package; update its three callers in api.go and upload.go. - Wire IsValidVersionTag at both upload entry points (web form + API) before any filesystem call. - Wire IsValidSlug into handleAdminCreateProject and handleAdminUpdateProject. - Replace fmt.Sprintf Content-Disposition with mime.FormatMediaType, with a plain-ASCII fallback. Existing test updated to the RFC-correct unquoted form for token filenames. - Regression tests at internal/handler/upload_validation_test.go cover the malicious-input rejection on both the upload and admin-create endpoints. Audit findings: C-1, M-5, M-8 (workstream item #1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>