Security Advisories (10)
CVE-2026-116264 (2026-10-28)

MIME::Field::ParamVal versions before 5.521 for Perl allow one invalid Content-Type parameter to hide the parameters after it, including the multipart boundary. Parameter parsing stops at the first parameter whose name it cannot read, such as x:y=1 or a name containing an 8-bit byte, and drops every parameter after it. When the boundary is among them, MIME::Parser keeps the multipart body as a single undecoded part without marking the parse as ambiguous. Mail readers that skip the invalid parameter still find the boundary. A remote sender can hide an attachment from a filter that relies on ambiguous_content() while the recipient's mail client shows it.

CVE-2026-116265 (2026-10-28)

MIME::Field::ParamVal versions before 5.521 for Perl do not flag an ambiguous multipart boundary written as RFC 2231 continuations. The boundary ambiguity checks look only at a plain boundary= parameter, and a boundary split into RFC 2231 sections (boundary*0=, boundary*1= and so on) is joined after they have run. A repeated section number is concatenated rather than reported as a duplicate. From version 5.518, an encoded word or trailing whitespace in such a boundary also goes unflagged, although multipart_boundary() decodes or strips it. A remote sender can make MIME::Parser split a message on a different boundary than other mail readers, hiding an attachment from a filter that relies on ambiguous_content() while the recipient's mail client shows it.

CVE-2026-116266 (2026-10-28)

MIME::Head versions from 5.518 before 5.521 for Perl decode a partly encoded multipart boundary without flagging the parse as ambiguous. The multipart_boundary() method decodes RFC 2047 encoded words anywhere in the boundary, but the ambiguity check only fires when the whole value is one encoded word. A boundary such as abc=?us-ascii?Q?def?= is used as abcdef, and ambiguous_content() returns false. Encoded words are not allowed in parameters, so other mail readers split the message on the literal value. A remote sender can hide an attachment from a filter that relies on ambiguous_content() while the recipient's mail client shows it.

CVE-2026-116267 (2026-10-28)

MIME::Parser versions before 5.521 for Perl allow memory exhaustion via indented error messages from a truncated, deeply nested message. Each stored parser diagnostic is indented by three spaces per nesting level. When a message nested N levels deep ends without its closing boundaries, every level logs an error at its own depth, so the stored diagnostics grow with the square of N. The defaults place no limit on nesting depth.

CVE-2026-116268 (2026-10-28)

MIME::Field::ParamVal versions before 5.521 for Perl allow CPU exhaustion via unclosed comments in header parameters. The comment pattern used to parse Content-Type and Content-Disposition parameters scans from each "(" to the next ")". In a field with no ")", every "(" scans to the end of the header and fails, so parsing takes time quadratic in the header length. The field is parsed again on each attribute lookup, several times per MIME entity. A 40 KB header takes about 7 seconds to parse once.

CVE-2026-116269 (2026-10-28)

MIME::Field::ParamVal versions before 5.521 for Perl turn an RFC 2231 filename with a hyphenated language tag into an empty recommended filename. A parameter such as filename*=utf-8'en-US'payload.exe is converted to an encoded word with the language tag appended to the charset. The decoder strips the language suffix only when it is a single word, so it cannot resolve the charset UTF-8*EN-US and returns an empty string. The recommended_filename() method returns that empty string rather than falling back to the name parameter. Other mail readers return payload.exe. A remote sender can get an attachment past a policy that checks file extensions on the recommended filename.

CVE-2026-116270 (2026-10-28)

MIME::Words versions before 5.521 for Perl allow memory exhaustion via repeated "=?" sequences in decode_mimewords. For each "=?" that does not start a complete encoded word, decode_mimewords appends an error message containing the whole input string to $@. A boundary of 8,000 "=?" pairs (16,000 bytes) adds 8,000 copies of itself to $@, about 128 MB. From version 5.518, MIME::Parser decodes every multipart boundary this way, so a remote sender can exhaust the memory of the parsing process with one Content-Type header.

CVE-2026-116271 (2026-10-28)

MIME::Parser::FileUnder versions before 5.521 for Perl reuse a pre-created output directory and follow symlinks in it, letting local users redirect attachment writes. Each message is written to a directory named msg-<time>-<pid>-<n> under the output base, and an existing directory of that name is used as is. A file name counts as unused when nothing exists at that path, which holds for a dangling symlink, and the body file is then opened in a way that follows the link. When the output base is writable by other users, as with output_under("/tmp"), a local user can pre-create the directory with a symlink named like an attachment. The parser then writes the attachment to the link target with the privileges of the parsing process.

CVE-2026-116272 (2026-10-28)

MIME::Field::ParamVal versions before 5.521 for Perl do not flag a duplicate boundary parameter whose name contains a nested comment. A parameter written boundary((c))="A" or boundary(\))="A" is stored under that literal name rather than as boundary. A second boundary parameter is then not reported as a duplicate, and MIME::Parser splits the message on it. Readers that skip comments as RFC 5322 allows take the first boundary instead. A remote sender can hide an attachment from a filter that relies on ambiguous_content() while the recipient's mail client shows it.

CVE-2026-116273 (2026-10-28)

MIME::Parser versions before 5.521 for Perl set no limit on the number of message parts by default, allowing memory exhaustion. The max_parts option defaulted to -1, which disables the limit, so a parser created with default settings builds an entity for every part however many a message has. Version 5.521 sets max_parts to 1000 and max_depth to 64 by default. Setting either to -1 still removes the limit.

NAME

MIME::Decoder - an object for decoding the body part of a MIME stream

SYNOPSIS

Before reading further, you should see MIME::Tools to make sure that you understand where this module fits into the grand scheme of things. Go on, do it now. I'll wait.

Ready? Ok...

Decoding a data stream

Here's a simple filter program to read quoted-printable data from STDIN (until EOF) and write the decoded data to STDOUT:

use MIME::Decoder;

$decoder = new MIME::Decoder 'quoted-printable' or die "unsupported";
$decoder->decode(\*STDIN, \*STDOUT);

Encoding a data stream

Here's a simple filter program to read binary data from STDIN (until EOF) and write base64-encoded data to STDOUT:

use MIME::Decoder;

$decoder = new MIME::Decoder 'base64' or die "unsupported";
$decoder->encode(\*STDIN, \*STDOUT);

Non-standard encodings

You can write and install your own decoders so that MIME::Decoder will know about them:

use MyBase64Decoder;

install MyBase64Decoder 'base64';

You can also test if a given encoding is supported:

    if (supported MIME::Decoder 'x-uuencode') {
	### we can uuencode!
    }

DESCRIPTION

This abstract class, and its private concrete subclasses (see below) provide an OO front end to the actions of...

  • Decoding a MIME-encoded stream

  • Encoding a raw data stream into a MIME-encoded stream.

The constructor for MIME::Decoder takes the name of an encoding (base64, 7bit, etc.), and returns an instance of a subclass of MIME::Decoder whose decode() method will perform the appropriate decoding action, and whose encode() method will perform the appropriate encoding action.

PUBLIC INTERFACE

Standard interface

If all you are doing is using this class, here's all you'll need...

new ENCODING

Class method, constructor. Create and return a new decoder object which can handle the given ENCODING.

my $decoder = new MIME::Decoder "7bit";

Returns the undefined value if no known decoders are appropriate.

best ENCODING

Class method, constructor. Exactly like new(), except that this defaults any unsupported encoding to "binary", after raising a suitable warning (it's a fatal error if there's no binary decoder).

my $decoder = best MIME::Decoder "x-gzip64";

Will either return a decoder, or a raise a fatal exception.

decode INSTREAM,OUTSTREAM

Instance method. Decode the document waiting in the input handle INSTREAM, writing the decoded information to the output handle OUTSTREAM.

Read the section in this document on I/O handles for more information about the arguments. Note that you can still supply old-style unblessed filehandles for INSTREAM and OUTSTREAM.

Returns true on success, throws exception on failure.

encode INSTREAM,OUTSTREAM

Instance method. Encode the document waiting in the input filehandle INSTREAM, writing the encoded information to the output stream OUTSTREAM.

Read the section in this document on I/O handles for more information about the arguments. Note that you can still supply old-style unblessed filehandles for INSTREAM and OUTSTREAM.

Returns true on success, throws exception on failure.

encoding

Instance method. Return the encoding that this object was created to handle, coerced to all lowercase (e.g., "base64").

head [HEAD]

Instance method. Completely optional: some decoders need to know a little about the file they are encoding/decoding; e.g., x-uu likes to have the filename. The HEAD is any object which responds to messages like:

$head->mime_attr('content-disposition.filename');
supported [ENCODING]

Class method. With one arg (an ENCODING name), returns truth if that encoding is currently handled, and falsity otherwise. The ENCODING will be automatically coerced to lowercase:

    if (supported MIME::Decoder '7BIT') {
	### yes, we can handle it...
    }
    else {
	### drop back six and punt...
    }

With no args, returns a reference to a hash of all available decoders, where the key is the encoding name (all lowercase, like '7bit'), and the value is true (it happens to be the name of the class that handles the decoding, but you probably shouldn't rely on that). You may safely modify this hash; it will not change the way the module performs its lookups. Only install can do that.

Thanks to Achim Bohnet for suggesting this method.

Subclass interface

If you are writing (or installing) a new decoder subclass, there are some other methods you'll need to know about:

decode_it INSTREAM,OUTSTREAM

Abstract instance method. The back-end of the decode method. It takes an input handle opened for reading (INSTREAM), and an output handle opened for writing (OUTSTREAM).

If you are writing your own decoder subclass, you must override this method in your class. Your method should read from the input handle via getline() or read(), decode this input, and print the decoded data to the output handle via print(). You may do this however you see fit, so long as the end result is the same.

Note that unblessed references and globrefs are automatically turned into I/O handles for you by decode(), so you don't need to worry about it.

Your method must return either undef (to indicate failure), or 1 (to indicate success). It may also throw an exception to indicate failure.

encode_it INSTREAM,OUTSTREAM

Abstract instance method. The back-end of the encode method. It takes an input handle opened for reading (INSTREAM), and an output handle opened for writing (OUTSTREAM).

If you are writing your own decoder subclass, you must override this method in your class. Your method should read from the input handle via getline() or read(), encode this input, and print the encoded data to the output handle via print(). You may do this however you see fit, so long as the end result is the same.

Note that unblessed references and globrefs are automatically turned into I/O handles for you by encode(), so you don't need to worry about it.

Your method must return either undef (to indicate failure), or 1 (to indicate success). It may also throw an exception to indicate failure.

filter IN, OUT, COMMAND...

Class method, utility. If your decoder involves an external program, you can invoke them easily through this method. The command must be a "filter": a command that reads input from its STDIN (which will come from the IN argument) and writes output to its STDOUT (which will go to the OUT argument).

For example, here's a decoder that un-gzips its data:

    sub decode_it {
	my ($self, $in, $out) = @_;
	$self->filter($in, $out, "gzip -d -");
    }

The usage is similar to IPC::Open2::open2 (which it uses internally), so you can specify COMMAND as a single argument or as an array.

init ARGS...

Instance method. Do any necessary initialization of the new instance, taking whatever arguments were given to new(). Should return the self object on success, undef on failure.

install ENCODINGS...

Class method. Install this class so that each encoding in ENCODINGS is handled by it:

install MyBase64Decoder 'base64', 'x-base64super';

You should not override this method.

uninstall ENCODINGS...

Class method. Uninstall support for encodings. This is a way to turn off the decoding of "experimental" encodings. For safety, always use MIME::Decoder directly:

uninstall MIME::Decoder 'x-uu', 'x-uuencode';

You should not override this method.

DECODER SUBCLASSES

You don't need to "use" any other Perl modules; the following "standard" subclasses are included as part of MIME::Decoder:

Class:                         Handles encodings:
------------------------------------------------------------
MIME::Decoder::Binary          binary
MIME::Decoder::NBit            7bit, 8bit
MIME::Decoder::Base64          base64
MIME::Decoder::QuotedPrint     quoted-printable

The following "non-standard" subclasses are also included:

Class:                         Handles encodings:
------------------------------------------------------------
MIME::Decoder::UU              x-uu, x-uuencode
MIME::Decoder::Gzip64          x-gzip64            ** requires gzip!

NOTES

Input/Output handles

As of MIME-tools 2.0, this class has to play nice with the new MIME::Body class... which means that input and output routines cannot just assume that they are dealing with filehandles.

Therefore, all that MIME::Decoder and its subclasses require (and, thus, all that they can assume) is that INSTREAMs and OUTSTREAMs are objects which respond to a subset of the messages defined in the IO::Handle interface; minimally:

print
getline
read(BUF,NBYTES)

Thanks to Achim Bohnet for suggesting this more-generic I/O model.

Writing a decoder

If you're experimenting with your own encodings, you'll probably want to write a decoder. Here are the basics:

  1. Create a module, like "MyDecoder::", for your decoder. Declare it to be a subclass of MIME::Decoder.

  2. Create the following instance methods in your class, as described above:

    decode_it
    encode_it
    init
  3. In your application program, activate your decoder for one or more encodings like this:

    require MyDecoder;
    
    install MyDecoder "7bit";   ### use MyDecoder to decode "7bit"
    install MyDecoder "x-foo";  ### also use MyDecoder to decode "x-foo"

To illustrate, here's a custom decoder class for the quoted-printable encoding:

    package MyQPDecoder;

    @ISA = qw(MIME::Decoder);
    use MIME::Decoder;
    use MIME::QuotedPrint;

    ### decode_it - the private decoding method
    sub decode_it {
	my ($self, $in, $out) = @_;
	local $_;
	while (defined($_ = $in->getline)) {
	    my $decoded = decode_qp($_);
	    $out->print($decoded);
	}
	1;
    }

    ### encode_it - the private encoding method
    sub encode_it {
	my ($self, $in, $out) = @_;

	my ($buf, $nread) = ('', 0);
	while ($in->read($buf, 60)) {
	    my $encoded = encode_qp($buf);
	    $out->print($encoded);
	}
	1;
    }

That's it. The task was pretty simple because the "quoted-printable" encoding can easily be converted line-by-line... as can even "7bit" and "8bit" (since all these encodings guarantee short lines, with a max of 1000 characters). The good news is: it is very likely that it will be similarly-easy to write a MIME::Decoder for any future standard encodings.

The "binary" decoder, however, really required block reads and writes: see "MIME::Decoder::Binary" for details.

SEE ALSO

MIME::Tools, other MIME::Decoder subclasses.

AUTHOR

Eryq (eryq@zeegee.com), ZeeGee Software Inc (http://www.zeegee.com).

All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1;