Skip to content

VNX-PHP-025: PHP deprecated mcrypt encryption functions

Reports calls to the PHP mcrypt functions that encrypt, decrypt or set up a cipher (mcrypt_encrypt/decrypt, mcrypt_cbc/cfb/ecb/ofb, mcrypt_module_open, mcrypt_generic, mdecrypt_generic, mcrypt_create_iv), directly or through call_user_func. Sizing and teardown helpers, same-named methods, polyfill definitions and mentions in strings or comments are not reported.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-PHP-025
Severity High
SARIF level error
Kind sast
Languages PHP
CWE CWE-327
CAPEC CAPEC-20
ATT&CK T1600
CWSS vector CWSS:1.0/TI:H/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H
Tags weak-crypto mcrypt deprecated php
Source internal/sast/rules/vnx-php-025.rego

Overview

This rule detects calls to functions from PHP’s mcrypt extension: mcrypt_encrypt(), mcrypt_decrypt(), mcrypt_cbc(), mcrypt_cfb(), mcrypt_ecb(), mcrypt_ofb(), mcrypt_create_iv(), mcrypt_generic(), mdecrypt_generic(), and related module management functions. The mcrypt extension was deprecated in PHP 7.1 and removed in PHP 7.2. Any codebase still using these functions is either running on an outdated PHP version with known security vulnerabilities or will fail to function on a current PHP installation.

The mcrypt library itself (libmcrypt) has been unmaintained since 2003. It implements a collection of cipher algorithms including DES, Triple-DES, Blowfish, and older stream ciphers, many of which are considered cryptographically weak or broken by current standards. The lack of maintenance means known vulnerabilities in the library have not been patched, and the implementations have not been audited to modern standards.

PHP’s recommended replacement is the OpenSSL extension (openssl_encrypt(), openssl_decrypt()), which is actively maintained, supports modern authenticated encryption modes (AES-GCM, ChaCha20-Poly1305), and is available on all current PHP installations. PHP 7.2+ also ships with the Sodium extension (sodium_crypto_secretbox(), etc.), which provides a modern, audited, and difficult-to-misuse cryptography API.

Why This Matters

Using deprecated and removed PHP functions has two categories of impact. The first is operational: code that calls mcrypt functions will throw a fatal error on PHP 7.2+, meaning applications that have not yet migrated are running on PHP 7.1 or earlier, which has reached end-of-life and no longer receives security patches for the PHP runtime itself.

The second impact is cryptographic: mcrypt’s commonly used algorithms are insecure by modern standards. DES has a 56-bit key that can be brute-forced in hours with commodity hardware. Triple-DES (3DES) is vulnerable to meet-in-the-middle attacks and Sweet32 birthday attacks. Blowfish has a maximum key size limitation and is being phased out. None of the modes supported by mcrypt include authenticated encryption, meaning ciphertexts encrypted with mcrypt can be modified by attackers without detection, the same padding oracle and bit-flipping risks as AES-CBC, covered in VNX-PHP-019.

Applications that encrypt sensitive data (credentials, personal information, health records, payment details) using these algorithms provide weaker protection than they appear to, and the ciphertext may be decryptable by a determined attacker.

What Gets Flagged

// FLAGGED: mcrypt_encrypt with deprecated algorithm
$encrypted = mcrypt_encrypt(MCRYPT_DES, $key, $plaintext, MCRYPT_MODE_CBC, $iv);

// FLAGGED: mcrypt_decrypt
$plaintext = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_ECB);

// FLAGGED: mcrypt generic interface (module_open and generic; the init call is not reported separately)
$module = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($module, $key, $iv);
$encrypted = mcrypt_generic($module, $data);

// FLAGGED: called by name
return call_user_func('mcrypt_decrypt', MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);

Not flagged: function_exists('mcrypt_encrypt'), $this->mcrypt_encrypt(...) on a class of your own, a polyfill function mcrypt_encrypt(...) definition, and mcrypt_get_iv_size() / mcrypt_module_close() helpers.

Remediation

  1. Migrate to openssl_encrypt() / openssl_decrypt() with AES-256-GCM for authenticated encryption.

  2. Or use the Sodium extension (sodium_crypto_secretbox() / sodium_crypto_secretbox_open()), which provides a higher-level API with built-in authentication and correct default parameters.

  3. Upgrade the PHP runtime to a supported version (8.1+), PHP 7.1 and earlier are end-of-life.

  4. Re-encrypt existing data stored with mcrypt using a migration script that decrypts with mcrypt on the old PHP version and re-encrypts with OpenSSL or Sodium.

<?php
// SAFE: OpenSSL with AES-256-GCM (see also VNX-PHP-019)
$nonce      = random_bytes(12);
$ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $key,
                              OPENSSL_RAW_DATA, $nonce, $tag);

// SAFE: Sodium secretbox, authenticated by default, simple API
$nonce     = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$encrypted = sodium_crypto_secretbox($plaintext, $nonce, $key);

$decrypted = sodium_crypto_secretbox_open($encrypted, $nonce, $key);
if ($decrypted === false) {
    throw new RuntimeException('Decryption failed, data may be tampered');
}

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-php-025
// nosec vnx-php-025

Or record an ignore rule: vulnetix ignore add --rule vnx-php-025 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-php-025.rego, cli/internal/sast/docs/vnx-php-025.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.