What Happened
In 2020, security researcher po6ix discovered a prototype pollution vulnerability in express-fileupload, a Node.js package for handling file uploads. Snyk confirmed the finding and assigned it CVE-2020-7699. The maintainers released version 1.1.8 to address the issue. That should have been the end of the story.
It wasn't. The initial fix was incomplete, requiring a second patch in version 1.1.10 to fully remediate the vulnerability. During the gap between these releases, nearly 8 million downloads of express-fileupload remained potentially vulnerable—and most teams using the package likely had no idea they needed to update twice.
Timeline
- Initial Discovery: po6ix identifies prototype pollution vulnerability in express-fileupload
- CVE Assignment: Snyk confirms the vulnerability and logs it as CVE-2020-7699
- First Patch: Maintainers release version 1.1.8 with initial fix
- Second Patch Required: Further research reveals incomplete remediation; version 1.1.10 released with complete fix
- July 2020: Package reaches nearly 8 million downloads with vulnerability window still affecting many installations
Which Controls Failed or Were Missing
The vulnerability—prototype pollution—represents a failure in input validation. However, the real issue was in your supply chain monitoring.
Vulnerability tracking broke down at the "fixed" declaration. Most security teams treat a CVE assignment and initial patch as closure. You update to the patched version, mark the ticket resolved, and move on. When that patch proves incomplete, you have no systematic way to learn about it unless you're actively monitoring:
- Release notes for every dependency
- Security advisories from multiple sources
- Follow-up CVE modifications
- Researcher disclosures on social channels
Your dependency update process likely assumes one-and-done fixes. When express-fileupload went from 1.1.8 to 1.1.10, did your team catch that the second update was security-critical? Or did it blend into the noise of routine maintenance releases?
Communication channels don't propagate urgency for iterative fixes. The initial CVE gets attention. The follow-up fix gets buried in changelog notes. There's no "CVE-2020-7699-INCOMPLETE" flag to trigger your alerting.
What the Relevant Standards Require
PCI DSS v4.0.1 Requirement 6.3.2 mandates that you maintain an inventory of bespoke and custom software and third-party software components. The emphasis here is "maintain"—not just catalog once, but actively track changes and vulnerabilities. When a component like express-fileupload requires a second patch, your inventory process should surface that.
Requirement 6.3.3 requires you to identify and address security vulnerabilities using reputable outside sources for security vulnerability information. The challenge: "reputable sources" often disagree on remediation completeness. The CVE database showed 1.1.8 as patched. Snyk's research revealed otherwise. You need multiple signal sources.
OWASP Top 10 2021: A06:2021 – Vulnerable and Outdated Components directly addresses this scenario. The guidance isn't just "patch things"—it's "continuously monitor for vulnerabilities in your dependencies and respond to new information." An incomplete fix followed by a second patch is exactly the pattern this control targets.
ISO/IEC 27001:2022 Annex A.8.8 (Management of technical vulnerabilities) requires you to obtain timely information about technical vulnerabilities and evaluate exposure. "Timely" means catching the 1.1.8-to-1.1.10 progression before an attacker does.
NIST CSF v2.0 function PR.DS-6 calls for integrity checking mechanisms to verify software integrity. In practice, this means your pipeline should flag when a "patched" dependency gets a rapid follow-up release—that's a signal worth investigating.
Lessons and Action Items for Your Team
Stop treating CVEs as binary states. A CVE assignment doesn't mean "fixed"—it means "acknowledged and tracked." Build your processes to expect iterative fixes:
- Set a 90-day watch period after applying any security patch
- Monitor the patched package for rapid follow-up releases
- Flag any version increment within 30 days of a security fix for manual review
Layer your vulnerability intelligence sources. Don't rely solely on CVE databases or your dependency scanner's built-in feeds:
- Subscribe to security advisories from package maintainers directly
- Follow security research teams (like Snyk's) that publish post-disclosure analysis
- Join language-specific security mailing lists (Node Security Project, PyPA announcements)
- Track researchers who specialize in your stack on professional networks
Automate the "is this security-related?" question for all dependency updates. When express-fileupload released 1.1.10 shortly after 1.1.8, that pattern should trigger investigation. Build a rule: any version bump within 30 days of a previous update gets flagged for security review, even if the changelog doesn't explicitly say "security fix."
Create a feedback loop from production monitoring to dependency decisions. If you're running express-fileupload in production, instrument it. When a new version drops, test it in a staging environment with the same monitoring. Compare behavior. Unexpected changes in error rates or request patterns might indicate the previous "fix" was incomplete.
Document your incomplete-fix protocol now. Don't wait for the next express-fileupload incident. Write the runbook today:
- When we apply a security patch, who monitors for follow-up releases?
- What's our SLA for evaluating a rapid follow-up version?
- How do we communicate "we need to patch again" to teams who already updated once?
- What's our rollback plan if the second fix introduces breaking changes?
For compliance managers: Update your evidence collection. Your auditor will ask how you track third-party vulnerabilities. "We scan with Tool X" isn't sufficient when Tool X might miss the incomplete-fix pattern. Document your multi-source approach and your follow-up monitoring window.
The express-fileupload incident didn't fail because of sophisticated exploitation. It failed because the security community's communication model assumes fixes work the first time. Your controls need to account for the reality that they often don't.



