#928037 mailcap(5): please document security considerations about %-escapes

#928037#5
Date:
2019-04-26 14:40:52 UTC
From:
To:
Dear Maintainer,

Please clarify how %-escapes in mailcap rules should be handled, because RFC-1524 is unclear about it, and this is leading to differences in implementations and security problems.

For example in gnu mailutils, you can do shell command injection form email headers (bug #927836[1]):

# mailcap rule (shipped with debian):
text/html; /usr/bin/w3m -I %{charset} -dump -T text/html %s

# malicious header:
Content-Type: text/html; charset="$(rm -rf ~/*)"

In s-nail, they are planning[2] to pre-quote %-escapes expansions (kind of like bash printf %q), and they are telling users not to add quotes around %-escapes in mailcap rules because they would interfere with the automatic quotes in the expansion.
This is a good solution, but quoted %-escapes in debian mailcap rules are common, and they would break, for example:

text/plain; less '%s'; needsterminal

Please note that no amount of quotes in a mailcap rule can prevent command injection (for example -I '%{charset}' could be exploited with charset="' & rm -rf ~/* '").

RFC-1524 is unclear:

The command is run by the bourne shell, which takes it as a single lump of code, therefore the only way to fulfill that last condition ("The entire parameter should appear as a single command line argument") is to pre-quote the replacement (as s-nail is planning to do).
But that doesn't seem to be the common practice (well, my knowledge of the common practice is limited because I managed to avoid mailcap since now).

Perhaps a less breaking solution would be to require implementers to filter out *any* shell-special punctuation from the replacement of any mailcap %-escape.

Anyway, I think having a better definition here would provide a needed guideline for programs using mailcap.

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=927836
[2] https://manpages.debian.org/unstable/s-nail/s-nail.1.en.html#The_Mailcap_files

#928037#10
Date:
2019-04-27 13:07:30 UTC
From:
To:
I've looked into some other program for how they handle mailcap rules.
The RFC deliberately doesn't discuss security, and not all projects seems to be aware of the problem.
If mailcap is supposed to be standard and interoperable (and not a security nightmare), we need a central place for such considerations, be it the mailcap(5) man page or somewhere else.

Here's what I would recommend to do:

1) Document that users must keep %-escapes in mailcap rules out of single/double/back-quotes because it cannot be done safely and it is the job of the program parsing mailcap rules.

Command substitution containing %-escapes must be done with $(...), and not with `...`.
If (for some reason I can't imagine) users want to put a %-escape inside double or back quotes, they should assign it to a variable (without quotes) and than reference the variable inside the quotes.

2) Document that mailcap parsers must quote %-escapes expansions if necessary (see bash printf %q), to make sure that they are not split in the wrong places, and that *any* shell-special punctuation is treated literally by the shell.

3) File bugs for every debian package not following rule #1 and #2.

4) Recommend mailcap parsers to provide an option to replace shell-special punctuation with a safe replacement character. This would prevent command injections even if rule #1 is not observed.

Please note that without either #1+2 or #4 in place, there is *no way* to avoid command injection (if you have any doubts about this let me know).
And even enforcing #4, we cannot ensure compatibility unless we prescribe a specific policy about quotations.

See also the section about mailcap security in the mutt manual:
http://www.mutt.org/doc/manual/#secure-mailcap

Slightly off-topic, I'm also seeing different ways to specify a path search of mailcap files via environment variable:
- RFC-1524 prescribes MAILCAPS
- mailcap(5) doesn't mention it
- gnu mailutils uses MAILCAP (no final S)
- s-nail uses MAILCAPS
- mutt doesn't mention it

Maybe it would be useful to document the "debian" way about this too, in mailcap(5).

#928037#15
Date:
2019-04-27 15:03:06 UTC
From:
To:

#928037#22
Date:
2020-11-09 11:39:00 UTC
From:
To:
Hi,

can I please ping to get this resolved one way or another? At the
moment, you either have one group of programs being insecure or another
when both use the same mailcap entries, and both are pointing their
fingers at the other (see blocked bug #950319), and arguments like
"larger user base" start to appear in a security discussion.

thanks,

Frank Löffler

#928037#27
Date:
2020-11-13 01:02:22 UTC
From:
To:
Thanks for your interest in the issue, Frank.

I've looked into the run-mailcap(1) script (the reference parser, included in this package), and I found it also vulnerable to shell command injection.

(Test with --norun, at your own risk.)
-- rule
text/*; /usr/bin/w3m -T %t %s
-- exploit
$ type='text/$(rm -fr *)' # e.g. from a malicious mail header
$ run-mailcap --action=view "$type":filename

#928037#32
Date:
2020-11-13 08:53:55 UTC
From:
To:
Hi,

Thanks for your interest, too.

It very possibly might. Would you be interested in opening one? The
information you have given here might be enough.

Again, it would be nice to report that.

I do agree that there are problems but I don't have the time or energy
to implement a replacement. However, at least there must be a documented
way how things should be implemented to be safe. Only then can we start
to successfully file actual security-bugs against packages that don't
follow that rule, and with that, open security leaks in their packages,
but also others. We tried without documentation, and failed. This is
what this bug here is about.

Frank

#928037#37
Date:
2020-11-13 23:47:53 UTC
From:
To:
Hi all,

Le Fri, Nov 13, 2020 at 02:02:22AM +0100, Marriott NZ a écrit :

Rejoice !  I just split the package into two:

 - media-types provides /etc/mime-types, which is what most packages
   depend on mime-support.
 - mailcap provides the mailcap system.
 - mime-support becomes a transition package.

So you should be able to remove mailcap easily.

Conversely, others interested in extending mailcap should be able to fork it easily.

And of couse the mailcap package can be constantly improved.

It will take me a bit of time to comment on the bug itself, as I am
going on business trip next week...

Have a nice week-end,

#928037#46
Date:
2020-11-16 22:16:10 UTC
From:
To:
Can do, but I'll wait for Charles comments.

Agreed, but I'm unfamiliar with Thunderbird and I don't use it, so I think I'll pass.
I just tried to look up some information as requested in #950319.

That was my intention, and I still want to do it.
Sorry for going a little off topic about disabling mailcap, but while we plan for better things I need to find a way to "fix" my boxes right now, and I can't think of another place to ask.

#928037#51
Date:
2020-11-16 22:31:05 UTC
From:
To:
I didn't know you were considering this back in 2019, I just saw the message on debian-devel, and I'm glad you decided to split.

In the mean time, is there a way to deactivate automatic generation of /etc/mailcap on stable? Is /etc/update-mime.conf intended for things like that?
Even in the future, if I could do that I wouldn't be barred from installing packages depending on "mailcap".

I was not aware of the discussion taking place in #964723 about moving away from mailcap which may also be relevant here.
Personally my only concern is the ability to permanently deactivate all default rules, be it mailcap or xdg-open or whatever.
Neither my file manager nor my mail user agent has a notion of type/program associations whatsoever, so I generally don't care. But sometimes I'm forced to use some program that digs up and runs a mailcap rule I didn't write, which annoys me to no end (security aside).

I look forward to hearing your view on the main issue (documenting unspecified things about mailcap).

Thanks.

#928037#56
Date:
2021-04-28 20:38:20 UTC
From:
To:
Hello,
this is an update on the situation of quoted %-escapes in mailcap rules:

Of the 86 packages that are affected in buster:

- 39 have been fixed by the maintainers independently (presumably thanks to the lintian tag):

audacity cgoban clustalx debian-edu-config djview4 drumkv1 feh geeqie ginkgocadx gpa graphicsmagick hatari html2text inkscape ivtools-bin juce-tools ktikz less ngraph-gtk njplot odt2txt okular okular-extra-backends padthv1 puredata-gui pyxplot qgis qtikz rhythmbox samplv1 sweethome3d sxiv synthv1 tkinfo valentina xarchiver xchm xli xmedcon

- 4 have been removed:

smpeg-gtv writetype xcftools xchat

- 6 have been fixed as a result of #950319, reported by Frank Loeffler:

libreoffice-base libreoffice-calc libreoffice-draw libreoffice-impress libreoffice-math libreoffice-writer

- 9 have been fixed (or pending upload) as a result of my own bug reports:

docx2txt emboss flowblade info katarakt man-db mutt stopmotion tar

- 28 (the remaining) have open bug reports reported by me:

alsaplayer-daemon(#987421) alsaplayer-gtk(#987421) alsaplayer-text(#987421) alsaplayer-xosd(#987421) caca-utils(#987422) carmetal(#987401) congruity(#985593) dia(#987402) fbi(#987403) freeplane(#985597) gnumeric(#985598) gthumb(#985599) imagemagick-6.q16(#987691) imagemagick-6.q16hdri(#987691) k4dirstat(#987694) latexdraw(#985601) libgsm-tools(#987404) mgetty-viewfax(#987424) most(#987405) mysql-workbench(#987693) neomutt(#982681) openshot-qt(#982953) planner(#987406) qgo(#987414) smpeg-plaympeg(#987692) tenace(#987416) ttyrec(#987407) vorbis-tools(#982951)

As of now, all but one (#987405) are without reply.

I've made an effort to speed up the adoption of the lintian policy, but I still think it is vital to have the policy written in the man page.

Two years ago this issue was blocking my work, so I carefully read all the documentation provided by the mime-support package, but found no useful information at all. At that time I was not aware of archived bug #90483 which is basically a duplicate of this one. I would have saved so many hours if the outcome of #90483 had been documented.
In my opinion, no divergence with other platforms has been avoided, just hidden. Only if the divergence is visible, it can be fixed. Only if there is a clear way to assign responsibility for security problems, they can be fixed. Even within Debian there are different mailcap components incompatible with each other.
My response to the "wait and see" argument is that 20+ years of bad security and inconvenience is enough. My response to the "mailcap is dead" argument is "I wish!".
The lintian tag is a big improvement, but some people still think it's not official enough, for example the libreoffice maintainer was reluctant to follow it.
Possibly, the Debian Policy Manual is also a good place to reach maintainers:
https://www.debian.org/doc/debian-policy/ch-opersys.html#registration-of-media-type-handlers-with-mailcap-entries

Thanks,
MNZ