Skip to content

Sanitize HTML in error responses to prevent reflected XSS#7849

Merged
nicholaspcr merged 2 commits intov3.36from
backport/potential-cross-site-scripting
Mar 6, 2026
Merged

Sanitize HTML in error responses to prevent reflected XSS#7849
nicholaspcr merged 2 commits intov3.36from
backport/potential-cross-site-scripting

Conversation

@nicholaspcr
Copy link
Contributor

@nicholaspcr nicholaspcr commented Mar 5, 2026

Summary

Backport of https://github.com/TheThingsIndustries/lorawan-stack/pull/4828.

Sanitize error responses to prevent reflected XSS from user-supplied input that flows into gRPC error messages and error detail attributes.

Changes

  • Add sanitizingHTTPErrorHandler in pkg/rpcserver that HTML-escapes gRPC status messages before they are serialized to JSON, replacing runtime.DefaultHTTPErrorHandler.
  • Add sanitizeAttributes and sanitizeAttributeValue in pkg/ttnpb/errors.go to HTML-escape string values in error detail attributes within ErrorDetailsToProto.
  • Add tests for XSS sanitization in pkg/rpcserver, pkg/ttnpb, and pkg/webhandlers.

Testing

Steps
  1. Run the new unit tests:
    go test ./pkg/rpcserver/ -run TestSanitizingHTTPErrorHandler -v
    go test ./pkg/ttnpb/ -run TestErrorDetailsToProtoXSSSanitization -v
    go test ./pkg/webhandlers/ -run TestNotFoundXSSSanitization -v
  2. Start a local stack and send a request with an XSS payload in a field mask parameter:
    curl -s 'http://localhost:1885/api/v3/applications/test-app/devices?page=1&limit=10&field_mask=%3Cscript%3Ealert(1)%3C/script%3E' \
      -H 'Authorization: Bearer <token>' | jq .
  3. Verify the response JSON contains &lt;script&gt; instead of <script>.
Results

All three tests pass. The error response body contains HTML-escaped entities and no raw <script> tags.

Regressions
  • Error message formatting: the top-level message field in JSON error responses is now HTML-escaped, which may affect clients that display error messages as plain text (escaped entities like &lt; would appear literally). This is the same behavior as the enterprise PR.
  • Error detail attributes: string attribute values are now HTML-escaped in the protobuf conversion, which similarly may surface escaped entities in API consumers.

Notes for Reviewers

Checklist

  • Scope: The referenced issue is addressed, there are no unrelated changes.
  • Compatibility: The changes are backwards compatible with existing API, storage, configuration and CLI, according to the compatibility commitments in README.md for the chosen target branch.
  • Documentation: Relevant documentation is added or updated.
  • Testing: The steps/process to test this feature are clearly explained including testing for regressions.
  • Infrastructure: If infrastructural changes (e.g., new RPC, configuration) are needed, a separate issue is created in the infrastructural repositories.
  • Changelog: Significant features, behavior changes, deprecations and fixes are added to CHANGELOG.md.
  • Commits: Commit messages follow guidelines in CONTRIBUTING.md, there are no fixup commits left.

@nicholaspcr nicholaspcr self-assigned this Mar 5, 2026
@nicholaspcr nicholaspcr requested a review from a team as a code owner March 5, 2026 18:40
@nicholaspcr nicholaspcr requested a review from halimi March 5, 2026 18:40
@nicholaspcr nicholaspcr merged commit 9a5cf4b into v3.36 Mar 6, 2026
9 of 10 checks passed
@nicholaspcr nicholaspcr deleted the backport/potential-cross-site-scripting branch March 6, 2026 13:07
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