Skip to content

🐛 bug: fix HTML escaping in AutoFormat#4228

Merged
ReneWerner87 merged 5 commits into
mainfrom
claude/fix-xss-raw-html-escaping
Apr 25, 2026
Merged

🐛 bug: fix HTML escaping in AutoFormat#4228
ReneWerner87 merged 5 commits into
mainfrom
claude/fix-xss-raw-html-escaping

Conversation

@Claude

@Claude Claude AI commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes a potential XSS vulnerability in AutoFormat where user input was directly concatenated into HTML without escaping.

Changes introduced

  • Security Fix: AutoFormat now uses template.HTMLEscapeString() to escape HTML special characters before rendering

    • Location: res.go:460 - Changed from "<p>" + b + "</p>" to "<p>" + template.HTMLEscapeString(b) + "</p>"
    • Imports: Added html package to res.go
  • Test Coverage: Added comprehensive Test_Ctx_AutoFormat_XSS_Prevention covering:

    • Script tag injection
    • Image/iframe tags with malicious handlers
    • JavaScript protocol URLs
    • Event handler attributes
    • Mixed quotes and special characters
    • Legitimate HTML entities (<, >, &)
  • Benchmarks: No performance impact - html.EscapeString() is optimized for common cases

  • Documentation Update: No documentation changes needed - security fix maintains existing API

  • Changelog/What's New: Security fix - prevents XSS attacks in AutoFormat HTML rendering

  • Migration Guide: No breaking changes - output format identical for non-malicious content

  • API Alignment with Express: N/A - security hardening

  • API Longevity: Maintains backward compatibility while fixing security issue

  • Examples: Test suite demonstrates protection against common XSS vectors

Type of change

  • Code consistency (non-breaking change which improves code reliability and robustness)

Checklist

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

@Claude Claude AI assigned Claude and gaby Apr 23, 2026
@ReneWerner87 ReneWerner87 added this to v3 Apr 23, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Apr 23, 2026
@gaby gaby changed the title 🐛 bug: Fix XSS vulnerability in AutoFormat HTML output 🐛 bug: fix HTML escaping in AutoFormat Apr 23, 2026
@gaby gaby moved this to In Progress in v3 Apr 23, 2026
@gaby gaby marked this pull request as ready for review April 23, 2026 13:24
Copilot AI review requested due to automatic review settings April 23, 2026 13:24
@gaby gaby requested a review from a team as a code owner April 23, 2026 13:24
@codecov

codecov Bot commented Apr 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.12%. Comparing base (9fd194f) to head (46e2cd9).
⚠️ Report is 30 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4228      +/-   ##
==========================================
- Coverage   91.24%   91.12%   -0.12%     
==========================================
  Files         123      123              
  Lines       11910    12076     +166     
==========================================
+ Hits        10867    11004     +137     
- Misses        655      673      +18     
- Partials      388      399      +11     
Flag Coverage Δ
unittests 91.12% <100.00%> (-0.12%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 Fiber’s AutoFormat HTML response path against XSS by escaping user-provided content before embedding it in an HTML <p> wrapper.

Changes:

  • Escape HTML special characters in DefaultRes.AutoFormat when the negotiated type is html.
  • Add a dedicated regression test covering multiple common XSS payload patterns for AutoFormat HTML output.

Reviewed changes

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

File Description
res.go Escapes HTML output in AutoFormat to prevent user input from being interpreted as markup/script.
ctx_test.go Adds coverage ensuring the HTML AutoFormat branch properly escapes potentially malicious input across several vectors.

Comment thread res.go
Comment thread res.go
Comment thread res.go Outdated
@gaby

gaby commented Apr 23, 2026

Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Copilot AI commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Addressed in cc5d809: switched AutoFormat to template.HTMLEscapeString, documented that HTML output is escaped plain text inside <p>...</p>, added coverage for pre-rendered HTML being escaped, and updated the PR checklist with the migration note.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Hardens Fiber’s AutoFormat HTML response path against XSS by ensuring user-provided content is HTML-escaped before being embedded into an HTML wrapper.

Changes:

  • Escape HTML content in DefaultRes.AutoFormat when Accept selects text/html (wraps escaped text in a <p>).
  • Add a dedicated XSS-prevention test covering multiple common injection vectors.
  • Update generated interface docs to reflect the new AutoFormat HTML escaping behavior.

Reviewed changes

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

File Description
res.go Escapes AutoFormat HTML output via template.HTMLEscapeString before wrapping in <p>...</p>.
ctx_test.go Adds Test_Ctx_AutoFormat_XSS_Prevention validating escaping across multiple payload patterns.
ctx_interface_gen.go Updates the generated Ctx interface comment to document HTML escaping behavior.
res_interface_gen.go Updates the generated Res interface comment to document HTML escaping behavior.

Comment thread ctx_test.go Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@gaby gaby requested a review from Copilot April 23, 2026 14:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Hardens Fiber’s AutoFormat HTML rendering path to prevent XSS by escaping the rendered body when text/html is negotiated, and adds regression tests to validate escaping behavior.

Changes:

  • Escape HTML output in DefaultRes.AutoFormat when the negotiated type is html.
  • Add a dedicated XSS regression test covering multiple common injection vectors.
  • Update AutoFormat documentation comments (including generated interfaces) to reflect the escaping behavior.

Reviewed changes

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

File Description
res.go Escapes the HTML response body in AutoFormat before wrapping it in <p>...</p>.
ctx_test.go Adds Test_Ctx_AutoFormat_XSS_Prevention to assert HTML-escaping and prevent regressions.
res_interface_gen.go Updates generated Res interface doc comment for AutoFormat to mention escaping.
ctx_interface_gen.go Updates generated Ctx interface doc comment for AutoFormat to mention escaping.

Comment thread res.go
Comment thread res.go Outdated
Comment thread ctx_test.go
gaby and others added 2 commits April 23, 2026 19:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@gaby

gaby commented Apr 23, 2026

Copy link
Copy Markdown
Member

@claude[agent]+claude-sonnet-4.6 Should we remove the "

" wrapping for html in AutoFormat() ?

@Claude

Claude AI commented Apr 23, 2026

Copy link
Copy Markdown
Contributor Author

@claude[agent]+claude-sonnet-4.6 Should we remove the "

" wrapping for html in AutoFormat() ?

Yes, I recommend removing the <p> wrapper. Since AutoFormat now escapes all content as plain text for security, the <p> tag is inconsistent—it's the only HTML element being rendered. Other formats (txt, json, xml) don't add wrappers, and users wanting structured HTML should use Format() with custom handlers. The HTML case should just return the escaped text with text/html content-type.

Should I proceed with removing the <p> wrapper?

@gaby

gaby commented Apr 24, 2026

Copy link
Copy Markdown
Member

@ReneWerner87 Thoughts?

@ReneWerner87

Copy link
Copy Markdown
Member

@claude[agent] We've adopted this feature from Express.js—how does it work there? Do we only use plain text as input? Is there a wrapper? What about XSS injection?

@Claude

Claude AI commented Apr 24, 2026

Copy link
Copy Markdown
Contributor Author

@claude[agent] We've adopted this feature from Express.js—how does it work there? Do we only use plain text as input? Is there a wrapper? What about XSS injection?

Express.js res.format() works differently from our AutoFormat():

Express.js approach:

  • res.format() is a content-negotiation router that calls handler functions you provide
  • No automatic wrapping or escaping - developers control the full response
  • Example: res.format({ html: () => res.send('<p>hey</p>'), json: () => res.json({msg: 'hey'}) })
  • XSS protection exists only in res.redirect() (uses escape-html on URLs in the HTML template)

Fiber's AutoFormat:

  • Takes a single value and auto-converts to all formats
  • Currently adds <p> wrapper and escapes HTML (after my fix)
  • More convenient but different design

Recommendation: Since Express doesn't wrap content, we should remove the <p> wrapper and just return the escaped text with text/html content-type. This aligns better with Express while maintaining XSS protection.

@ReneWerner87

Copy link
Copy Markdown
Member

okay AutoFormat is a special fiber thing -> then we can decide on our own, for the behaviour

@ReneWerner87

Copy link
Copy Markdown
Member

Let's talk about this again on Discord; I'm not sure about the restriction that says you can only inject plain text now.

@ReneWerner87

Copy link
Copy Markdown
Member

We are fine with the adjustments

@ReneWerner87 ReneWerner87 merged commit 771b689 into main Apr 25, 2026
24 checks passed
@ReneWerner87 ReneWerner87 deleted the claude/fix-xss-raw-html-escaping branch April 25, 2026 06:47
@welcome

welcome Bot commented Apr 25, 2026

Copy link
Copy Markdown

Congrats on merging your first pull request! 🎉 We here at Fiber are proud of you! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

@github-project-automation github-project-automation Bot moved this from In Progress to Done in v3 Apr 25, 2026
@ReneWerner87 ReneWerner87 modified the milestones: v3, v3.2.0 Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants