I found a bug in the HTML filtering code in core/manipulate-dom.js
If a 301 redirect or a 401 unauthorized occurs, the response HTML is filtered multiple times, each time with the charset of each step.
So if a redirect has
content-type: text/html;charset=AAA and then the actual 200 response has
content-type: text/html;charset=BBB then the content is filtered twice and the HTML is interpreted as charset AAA in one filtering step and as BBB in the other.
How to fix: check that the
details.statusCode is 200 early on in