In 2012, security researchers at Kaspersky Lab discovered a piece of malware called Flame that had been quietly harvesting data from machines across the Middle East for years. What made Flame remarkable wasn't just its scope — it was how it spread. Flame carried a forged digital certificate that appeared to be signed by Microsoft, allowing it to masquerade as a legitimate Windows Update package. The forgery was possible because its authors exploited a collision in the MD5 hashing algorithm, a weakness that cryptographers had been warning about since 2004. Eight years passed between the first published MD5 collision and its use in a nation-state-grade attack. That gap is the story of insecure hash algorithm usage: the vulnerability is rarely a mystery, the fix is rarely hard, and yet the broken algorithm keeps showing up in production code, checksums, and certificates long after everyone agreed it should be gone.
What actually makes a hash algorithm "insecure"?
A hash algorithm becomes insecure the moment someone can reliably produce a collision — two different inputs that generate the same hash — faster than brute force should allow. MD5 crossed that line in 2004, when researcher Xiaoyun Wang and colleagues published a practical collision-finding method. SHA-1 crossed it publicly in February 2017, when Google and CWI Amsterdam released the "SHAttered" attack, producing two distinct PDF files that shared an identical SHA-1 hash. Both algorithms remain fast to compute and easy to implement, which is exactly why they still turn up in code: they work correctly for non-adversarial data, and it takes a targeted attack to expose the flaw. This class of weakness is formally tracked as CWE-327 (Use of a Broken or Risky Cryptographic Algorithm) and CWE-328 (Use of a Weak Hash), and it sits inside OWASP's A02:2021 Cryptographic Failures category — one of the most common findings in application security audits today.
Where do MD5 and SHA-1 still hide in modern application code?
They hide in four recurring places: password storage, file integrity checks, digital signatures, and internal deduplication or caching logic. Legacy authentication systems built before 2010 frequently hash passwords with unsalted MD5 or SHA-1 because that was the standard advice at the time, and the code has simply never been revisited. Build pipelines and package registries often generate MD5 or SHA-1 checksums to verify that a downloaded artifact matches what was published — a check that gives a false sense of integrity once collisions are practical. Git itself, used by essentially every engineering team, addressed identified as far back as its 2005 design, relies on SHA-1 for commit and object hashing; the project only began shipping experimental SHA-256 support in Git 2.29, released in October 2020. And plenty of internal tools use MD5 as a fast, "good enough" way to fingerprint files or dedupe records, without anyone flagging it as a security-relevant decision because it was never intended to be one.
What real-world breaches trace back to weak hashing?
The 2012 LinkedIn breach is the clearest case: attackers stole roughly 6.5 million password hashes, all generated with unsalted SHA-1, and cracked the vast majority within days of the dump surfacing online — a breach LinkedIn only fully disclosed as affecting over 167 million accounts when the same dataset resurfaced in 2016. The 2015 Ashley Madison breach shows a subtler version of the same problem: the company had actually adopted bcrypt, a strong password-hashing function, for its primary password store. But a legacy authentication system left behind an MD5-based "login key" derived from the username and a lowercased version of the password. Researchers used that leftover MD5 artifact to crack more than 11 million of the supposedly bcrypt-protected passwords within about ten days — proving that one insecure hash left in a corner of the codebase can undermine an otherwise solid cryptographic design. The Flame malware certificate forgery described above is the clearest example on the integrity side, showing that the same weakness applies just as much to code-signing trust chains as it does to passwords.
How cheap has it become to actually break these algorithms?
Cheap enough that it's now well within reach of a well-funded individual, not just a national intelligence agency. The original 2017 SHAttered SHA-1 collision required computation equivalent to 6,500 CPU-years and 110 GPU-years — enormous, but Google and CWI still pulled it off using cloud infrastructure. By 2020, researchers Gaëtan Leurent and Thomas Peyrin published "SHA-1 is a Shambles," demonstrating a chosen-prefix collision — the more dangerous variant, since it lets an attacker forge a malicious file that collides with an arbitrary target file — for an estimated $45,000 in rented cloud GPU time, and they used it to build a working forged PGP identity certificate. MD5 is cheaper still: full collisions can be generated in seconds on commodity hardware today. NIST has responded accordingly, announcing in December 2022 that it plans to retire SHA-1 entirely from federal use by December 31, 2030, formally recommending SHA-256 or better for any new system in the meantime.
Why hasn't this been fixed after 20+ years of warnings?
Because the fix requires finding code that was never labeled as a security control in the first place. Nobody schedules a migration project for a checksum function buried in a build script or a hashing call inside a third-party library that was vendored in five years ago. Insecure hash usage tends to survive not because teams disagree it's a problem, but because it's invisible in normal code review — a call to MD5() or hashlib.sha1() looks like ordinary utility code, not a cryptographic decision. It also frequently arrives through dependencies rather than first-party code: a logging library, an ORM, or a caching layer written years ago may quietly compute SHA-1 fingerprints internally, and that choice is inherited by every application that imports it. Manual audits catch the obvious cases in core authentication code but routinely miss the same pattern scattered across dozens of internal services, scripts, and vendored dependencies — which is exactly the scale problem that turns a known, 20-year-old vulnerability class into a recurring finding in almost every large codebase.
How Safeguard Helps
Safeguard is built to catch exactly this class of problem before it becomes the next Flame certificate or the next cracked password dump. Instead of relying on a point-in-time manual review, Safeguard continuously scans application code, dependency trees, build artifacts, and CI/CD pipelines for insecure cryptographic patterns, flagging every call site that uses MD5, SHA-1, or other deprecated hash and cipher constructions — mapped directly to CWE-327, CWE-328, and the relevant OWASP category so findings drop straight into existing compliance workflows. Because the scanning runs across the full software supply chain rather than just first-party source, Safeguard also surfaces insecure hashing that arrives indirectly, through a vendored library or a transitive dependency, which is where most of these issues hide in practice. Each finding comes with the specific file, line, and call context needed to fix it, along with a recommended modern replacement — such as SHA-256 or SHA-3 for integrity checks, and bcrypt, scrypt, or Argon2 for password storage — so remediation doesn't require a separate research project. For teams working toward SOC 2 or similar attestations, Safeguard also tracks these findings over time, giving auditors and security leads a clear record that known-weak cryptography has been identified, prioritized, and resolved rather than left to resurface in the next breach.