{"record":{"id":"5c63e7fde8d6a9d5","repo":"ansible/ansible","slug":"md5-not-available-possibly-running-in-fips-mode","errorCode":null,"errorMessage":"MD5 not available.  Possibly running in FIPS mode","messagePattern":"MD5 not available\\.  Possibly running in FIPS mode","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/ansible/module_utils/basic.py","lineNumber":1585,"sourceCode":"        while block:\n            digest_method.update(block)\n            block = infile.read(blocksize)\n        infile.close()\n        return digest_method.hexdigest()\n\n    def md5(self, filename):\n        \"\"\" Return MD5 hex digest of local file using digest_from_file().\n\n        Do not use this function unless you have no other choice for:\n            1) Optional backwards compatibility\n            2) Compatibility with a third party protocol\n\n        This function will not work on systems complying with FIPS-140-2.\n\n        Most uses of this function can use the module.sha1 function instead.\n        \"\"\"\n        if 'md5' not in AVAILABLE_HASH_ALGORITHMS:\n            raise ValueError('MD5 not available.  Possibly running in FIPS mode')\n        return self.digest_from_file(filename, 'md5')\n\n    def sha1(self, filename):\n        \"\"\" Return SHA1 hex digest of local file using digest_from_file(). \"\"\"\n        return self.digest_from_file(filename, 'sha1')\n\n    def sha256(self, filename):\n        \"\"\" Return SHA-256 hex digest of local file using digest_from_file(). \"\"\"\n        return self.digest_from_file(filename, 'sha256')\n\n    def backup_local(self, fn):\n        \"\"\"make a date-marked backup of the specified file, return True or False on success or failure\"\"\"\n\n        backupdest = ''\n        if os.path.exists(fn):\n            # backups named basename.PID.YYYY-MM-DD@HH:MM:SS~\n            ext = time.strftime(\"%Y-%m-%d@%H:%M:%S~\", time.localtime(time.time()))\n            backupdest = '%s.%s.%s' % (fn, os.getpid(), ext)","sourceCodeStart":1567,"sourceCodeEnd":1603,"githubUrl":"https://github.com/ansible/ansible/blob/9cf16a4aca7898481c257f1e17ad28d0b67b1f85/lib/ansible/module_utils/basic.py#L1567-L1603","documentation":"Raised by AnsibleModule.md5() in ansible.module_utils.basic when the 'md5' hash algorithm is absent from AVAILABLE_HASH_ALGORITHMS. This almost always means the managed host's Python/OpenSSL is running in FIPS-140-2 mode, where OpenSSL refuses to register MD5. The method's own docstring states it will not work on FIPS-compliant systems and that most callers should use sha256/sha1 instead.","triggerScenarios":"Calling module.md5('/path/to/file') (directly or via a module feature that compares MD5 checksums, e.g. copy/get_url with checksum=md5:...) on a host where hashlib does not expose md5 because FIPS enforcement (OPENSSL_FORCEFIPS_MODE=1, a FIPS kernel, or a FIPS-configured OpenSSL) is active.","commonSituations":"RHEL/CentOS hosts in FIPS mode (fips=1 kernel cmdline), government or compliance-hardened environments, and modules that still default to MD5 for backward compatibility with third-party protocols that require MD5.","solutions":["Switch to module.sha256(filename) or module.checksum_s('sha256') for local file digests","For copy/get_url style tasks, pass checksum with a stronger algorithm, e.g. checksum: sha256:...","If a third-party protocol mandates MD5, run the task with FIPS disabled (remove fips=1 and reboot) or use a Python/OpenSSL build with a non-FIPS MD5","If you maintain the module, gate the MD5 path: offer an algorithm option and fall back to sha256 when 'md5' not in AVAILABLE_HASH_ALGORITHMS"],"exampleFix":"# before\nchecksum = module.md5(dest_file)\n\n# after\nif 'md5' in AVAILABLE_HASH_ALGORITHMS:\n    checksum = module.md5(dest_file)\nelse:\n    checksum = module.sha256(dest_file)","handlingStrategy":"validation","validationCode":"from ansible.module_utils.basic import AVAILABLE_HASH_ALGORITHMS\n\nif 'md5' not in AVAILABLE_HASH_ALGORITHMS:\n    # FIPS host: pick a strong digest before calling module.md5\n    digest = module.sha256(path)\nelse:\n    digest = module.md5(path)","typeGuard":"def md5_available() -> bool:\n    return 'md5' in AVAILABLE_HASH_ALGORITHMS","tryCatchPattern":"try:\n    digest = module.md5(path)\nexcept ValueError as e:\n    if 'FIPS' in str(e):\n        digest = module.sha256(path)\n    else:\n        raise","preventionTips":["Default to sha256 for local digests; reserve MD5 for third-party protocols that mandate it","Prefer checksum: sha256:... on copy/get_url tasks instead of relying on module defaults","Document FIPS incompatibility in module docs if MD5 is required"],"tags":["fips","crypto","checksum","ansible-module-utils"],"backgroundTag":null,"analyzedSha":"9cf16a4aca7898481c257f1e17ad28d0b67b1f85","analyzedAt":"2026-08-15T00:15:47.100Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}