Skip to content

fix(security): prevent content injection via URL query param flash messages#153

Merged
appleboy merged 4 commits intomainfrom
worktree-message
Apr 3, 2026
Merged

fix(security): prevent content injection via URL query param flash messages#153
appleboy merged 4 commits intomainfrom
worktree-message

Conversation

@appleboy
Copy link
Copy Markdown
Member

@appleboy appleboy commented Apr 3, 2026

Summary

  • Replace direct c.Query() pass-through with map-based lookups in login, authorization, and device handlers to prevent content injection via crafted URLs
  • Remove default: errorMsg = errorParam in login handler that allowed arbitrary user-controlled text to be rendered as an official error message (e.g., /login?error=Your+account+is+locked.+Call+1-800-SCAM)
  • Add authzSuccessMessages / authzErrorMessages maps for authorization page, following the same safe pattern as token_admin.go
  • Remove unused error query param pass-through in device page (no code ever redirects to /device?error=...)

Audit of all 7 query param flash message locations

# File Status
1 handlers/client.go Already safe (switch, no default pass-through)
2 handlers/token_admin.go Already safe (map lookup)
3 handlers/user_client.go Already safe (exact comparison)
4 handlers/auth.go Fixed — removed default case
5 handlers/authorization.go Fixed — replaced direct pass-through with map
6 handlers/device.go Fixed — replaced direct pass-through with empty string
7 handlers/audit.go N/A — filter param, not flash message

Test plan

  • make lint passes with 0 issues
  • make test passes all tests
  • Verify /login?error=injected_text shows no error message
  • Verify /login?error=session_timeout shows the expected expiry message
  • Verify /account/authorizations?success=revoked shows success message
  • Verify /account/authorizations?error=crafted_text shows no error message

🤖 Generated with Claude Code

…ssages

- Replace direct c.Query() pass-through with map-based lookups in login,
  authorization, and device handlers
- Remove default case in login error handler that rendered arbitrary
  user-supplied text as an official error message
- Add authzSuccessMessages and authzErrorMessages maps for authorization page
- Remove unused error query param pass-through in device page
Copilot AI review requested due to automatic review settings April 3, 2026 02:48
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

❌ Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/handlers/authorization.go 0.00% 2 Missing ⚠️
internal/handlers/auth.go 0.00% 1 Missing ⚠️
internal/handlers/device.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens handler “flash message” rendering by preventing user-controlled URL query parameters from being displayed verbatim as official-looking success/error banners, reducing phishing/content-injection risk across login, authorization, and device pages.

Changes:

  • Replace raw c.Query() pass-through for login/authorization flash messages with allowlist map lookups.
  • Remove the login handler’s default switch branch that previously echoed arbitrary error query text.
  • Stop surfacing the (apparently unused) error query param on the device page by always setting Error to an empty string.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
internal/handlers/auth.go Introduces loginErrorMessages allowlist and removes raw query-param error echoing on the login page.
internal/handlers/authorization.go Adds allowlisted success/error message maps and uses them when rendering the authorizations list page.
internal/handlers/device.go Removes query-param error pass-through by always rendering an empty error message on the device page.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

appleboy added 2 commits April 3, 2026 10:53
- Add auth_test.go with tests for loginErrorMessages known keys
  and unknown key rejection (content injection prevention)
- Add authorization_test.go tests for authzSuccessMessages and
  authzErrorMessages known keys and unknown key rejection
- Verify all device code error types map to correct user-facing messages
- Cover unknown error fallback to generic message
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Replace services.ErrDeviceCodeNotFound with errors.New() in the
  unknown error test case to properly exercise the default branch
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@appleboy appleboy merged commit 1e272e7 into main Apr 3, 2026
19 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants