</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>MimeMagicDecompression</name>
+<description>Enable decompression of compressed files for MIME type detection</description>
+<syntax>MimeMagicDecompression On|Off</syntax>
+<default>MimeMagicDecompression Off</default>
+<contextlist><context>server config</context><context>virtual host</context>
+</contextlist>
+
+<usage>
+ <p>The <directive>MimeMagicDecompression</directive> directive controls
+ whether <module>mod_mime_magic</module> will attempt to decompress files
+ that appear to be compressed (gzip, compress, etc.) in order to determine
+ the MIME type of the uncompressed content. This feature is <strong>disabled
+ by default</strong> and should only be enabled if you understand the
+ significant drawbacks. It exists to maintain backward compatibility with
+ previous releases of httpd, but its use is discouraged.</p>
+
+ <note type="warning"><title>Security and Compatibility Issues</title>
+ <p>This feature has several serious flaws and is disabled by default:</p>
+ <ol>
+ <li><strong>Not RFC-compliant:</strong> Standards documents consistently
+ recommend against setting Content-Encoding for files that are already
+ compressed (such as .zip or .gz files). See
+ <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-content-encoding">RFC 9110</a>.</li>
+
+ <li><strong>Breaks content integrity:</strong> When Content-Encoding is set,
+ most HTTP clients will decompress the file before writing it to disk. This
+ causes the downloaded file to have a different size and checksum than the
+ original, breaking signature verification and checksum validation. Software
+ distribution sites will find this particularly problematic.</li>
+
+ <li><strong>Unpredictable behavior:</strong> This feature only applies to
+ files that don't match a MIME type via file extension. This can lead to
+ inconsistent behavior where some files in a directory are affected and
+ others are not, making problems difficult to diagnose.</li>
+
+ <li><strong>Performance impact:</strong> Decompression requires forking and
+ executing an external <code>gzip</code> process for each compressed file,
+ which adds significant overhead.</li>
+
+ <li><strong>Security risk:</strong> Passing untrusted uploaded file data to
+ an external binary (<code>gzip</code>) could potentially expose the server to
+ compression bombs, resource exhaustion, or remote code execution
+ vulnerabilities in the decompression tool.</li>
+ </ol>
+ </note>
+
+ <example><title>Example (not recommended)</title>
+ <highlight language="config">
+# Only enable if you fully understand the risks
+MimeMagicDecompression On
+ </highlight>
+ </example>
+
+ <p>In most cases, it is better to ensure files have proper extensions
+ that can be mapped via <module>mod_mime</module> rather than relying on
+ this feature.</p>
+</usage>
+</directivesynopsis>
+
</modulesynopsis>
#define MAXMIMESTRING 256
+#define UNSET -1
+
/* HOWMANY must be at least 4096 to make gzip -dcq work */
#define HOWMANY 4096
/* SMALL_HOWMANY limits how much work we do to figure out text files */
const char *magicfile; /* where magic be found */
struct magic *magic; /* head of magic config list */
struct magic *last;
+ int decompression_enabled; /* whether to decompress files for content detection */
} magic_server_config_rec;
/* per-request info */
static void *create_magic_server_config(apr_pool_t *p, server_rec *d)
{
+ magic_server_config_rec *conf;
/* allocate the config - use pcalloc because it needs to be zeroed */
- return apr_pcalloc(p, sizeof(magic_server_config_rec));
+ conf = apr_pcalloc(p, sizeof(magic_server_config_rec));
+ conf->decompression_enabled = UNSET;
+ return conf;
}
static void *merge_magic_server_config(apr_pool_t *p, void *basev, void *addv)
apr_palloc(p, sizeof(magic_server_config_rec));
new->magicfile = add->magicfile ? add->magicfile : base->magicfile;
+ new->decompression_enabled = (add->decompression_enabled != UNSET) ?
+ add->decompression_enabled : base->decompression_enabled;
new->magic = NULL;
new->last = NULL;
return new;
return NULL;
}
+static const char *set_decompression(cmd_parms *cmd, void *dummy, int arg)
+{
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(cmd->server->module_config,
+ &mime_magic_module);
+
+ conf->decompression_enabled = arg;
+ return NULL;
+}
+
/*
* configuration file commands - exported to Apache API
*/
{
AP_INIT_TAKE1("MimeMagicFile", set_magicfile, NULL, RSRC_CONF,
"Path to MIME Magic file (in file(1) format)"),
+ AP_INIT_FLAG("MimeMagicDecompression", set_decompression, NULL, RSRC_CONF,
+ "Enable decompression of compressed files for content type detection "
+ "(Off by default). WARNING: This feature is NOT RFC-compliant, can be "
+ "unpredictable, breaks content integrity (clients will decompress files "
+ "causing checksum mismatches), impacts performance (fork/exec overhead), "
+ "and is unsafe (passes untrusted data to external gzip binary). "
+ "Use only if you understand these risks."),
{NULL}
};
static int tryit(request_rec *r, unsigned char *buf, apr_size_t nb,
int checkzmagic)
{
+ magic_server_config_rec *conf = (magic_server_config_rec *)
+ ap_get_module_config(r->server->module_config, &mime_magic_module);
+
/*
- * Try compression stuff
+ * Try compression stuff (only if decompression is enabled)
*/
- if (checkzmagic == 1) {
+ if (checkzmagic == 1 && conf && conf->decompression_enabled == 1) {
if (zmagic(r, buf, nb) == 1)
return OK;
}