Problem: We have HTML source code and want to deliver it to the user as plaintext.
It should not be interpreted as HTML! (e.g. containing <script> tags and such).
Also it should be possible to save the link as a file, so the solution to deliver it as HTML and just
escape everything is not usable. Typical use case: web forum or bugticket system where code or HTML samples
can be downloaded so you don't have to copy&paste to save some sample.
The purpose of this page is to show that it can be dangerous to just deliver plaintext with untrusted
content, and to show how different browsers/versions react.
Solution:
There are several possibilities to influence what the browser does.
ok | as expected |
maybe ok | not really as expected, but at least safe |
wrong | just wrong, possibly open to scripting attacks (XSS, CSRF) |
link | Content- Type | Link- Suffix | Content- Disposition filename |
Opera 10 Linux |
Opera 11.0 Win 7 Ult. x64 |
Opera 11.50 Linux |
FF 3.5.16 Linux |
FF 3.6.13 Gentoo |
FF 5.0 Linux |
Epiphany 2.30.6 Debian |
Safari 5.03 Win 7 Ult. x64 |
Chrome 8.0 Win 7 Ult. x64 |
IE 6 Win 7 Ult. x64 |
IE 7 Win 7 Ult. x64 |
IE 8 Win 7 Ult. x64 |
IE 9 Win7 Home Premium |
Chromium 6 Debian |
ELinks 0.12pre5 | Konqueror 4.4.5 KUbuntu 10 |
Lynx 2.6.8rel5 win32 |
Lynx 2.8.5rel1.1 CentOS 5.5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1. ctttext |
text/plain | bar | - | inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline HTML |
inline HTML |
inline HTML |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
2. ctttextsf |
text/plain | bar.txt | - | inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline HTML |
inline HTML |
inline HTML |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
3. ctttextdispo |
text/plain | bar.txt | inline (bar.txt) |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline HTML |
inline HTML |
inline HTML |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
inline TEXT |
4. ctttextattach |
text/plain | bar.txt | attachment (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
? | download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
inline TEXT |
download (bar.txt) |
inline TEXT |
inline TEXT |
5. ctoctet |
application/ octet-stream |
bar | - | inline HTML |
inline HTML |
download (bar) |
download (bar) |
download (bar) |
download (bar) |
download (bar) |
inline HTML |
download (bar) |
inline HTML |
inline HTML |
inline HTML |
inline HTML |
download (bar) |
download (bar) |
download ? |
download ? |
download ? |
6. ctoctetsf |
application/ octet-stream |
bar.txt | - | inline TEXT |
inline TEXT |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
inline HTML |
download (bar.txt) |
inline HTML |
inline HTML |
inline HTML |
inline HTML |
download (bar.txt) |
download (bar.txt) |
download ? |
download ? |
download ? |
7. ctoctetdispo |
application/ octet-stream |
bar.txt | inline (bar.txt) |
inline TEXT |
inline TEXT |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
inline HTML |
download (bar.txt) |
inline HTML |
inline HTML |
inline HTML |
inline HTML |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
8. ctoctetattach |
application/ octet-stream |
bar.txt | attachment (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
? | download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
9. cttoctetsfdat |
application/ octet-stream |
bar.dat | - | inline HTML |
inline HTML |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
inline HTML |
download (bar.txt) |
inline HTML |
inline HTML |
inline HTML |
inline HTML |
download (bar.dat) |
download (bar.dat) |
download ? |
download ? |
download ? |
10. cttoctetdispodat |
application/ octet-stream |
bar.dat | inline (bar.dat) |
inline HTML |
inline HTML |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
inline HTML |
download (bar.dat) |
inline HTML |
inline HTML |
inline HTML |
inline HTML |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
11. cttoctetattachdat |
application/ octet-stream |
bar.dat | attachment (bar.dat) |
download (bar.htm) |
download (bar.htm) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
? | download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
download (bar.dat) |
12. ctttextattachnosuffix |
text/plain | bar | attachment (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
download (bar.txt) |
inline TEXT |
|||||||
13. nosniffplain |
text/plain | bar.html | inline (bar.html) |
inline TEXT |
inline TEXT |
inline TEXT |
|||||||||||||||
14. nosniffhtml |
text/html | bar.html | inline - |
inline HTML |
inline HTML |
inline HTML |
Conclusion:
The "correct" solution (this is also how I understand the specs) would be to set text/plain
and give a filename by adding file.txt to the link or putting it into the Content-Disposition.
If you want to be safe and support IE you should switch to forcing a download (if possible,
by checking the User-Agent for IE and only switch to download in this case).
Links:
2011-02-23 - added hint about X-Content-Type-Options header, described problem more detailed
2011-08-19 - added Opera 11.50 Linux, FF 5.0 Linux and IE 9 Win7
The tests were run bei several diligent helpers (thanks to all), discussed in the (german) perl forum HTML als plaintext