Skip to content

fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod #7848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 6, 2025

Conversation

HandyG52
Copy link

Description of Change

Dependency.java getVulnerabilities(boolean sorted) method when sorted=false returns the vulnerabilities HashSet global to the Dependency object. It is returned wrapped in an UnmodifiableSet, but this does not protect against concurrent modifications as it just wraps the original set. Any future calls to add or remove vulnerabilities will proceed, as we are outside the synchronized methods, while someone is potentially iterating over the UnmodifiableSet retrieved earlier.

I came across this intermittent issue during my builds while in AbstractNpmAnalyzer.replaceOrAddVulnerability. I assume one AbstractNpmAnalyzer instance is performing a stream.anyMatch on the Set while another instance, or some other mechanism, is adding or removing vulnerabilities from the same dependency.

Note: In this same line of code (AbstractNpmAnalyzer.replaceOrAddVulnerability) there is another stream operation to locate references for a vulnerability by name, however I think the references Set is thread-safe. It also uses Collections.unmodifiableSet, but in this case the Set being wrapped is ConcurrentHashMap.newKeySet which should remain thread-safe. A similar approach could be taken in Dependency.java with the vulnerabilitySet, but would be more invasive.

Related issues

[ERROR]
java.util.ConcurrentModificationException
at java.util.HashMap$KeySpliterator.tryAdvance (HashMap.java:1738)
at java.util.stream.ReferencePipeline.forEachWithCancel (ReferencePipeline.java:129)
at java.util.stream.AbstractPipeline.copyIntoWithCancel (AbstractPipeline.java:527)
at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:513)
at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499)
at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:230)
at java.util.stream.MatchOps$MatchOp.evaluateSequential (MatchOps.java:196)
at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.anyMatch (ReferencePipeline.java:632)
at org.owasp.dependencycheck.analyzer.AbstractNpmAnalyzer.replaceOrAddVulnerability (AbstractNpmAnalyzer.java:508)
at org.owasp.dependencycheck.analyzer.AbstractNpmAnalyzer.processResults (AbstractNpmAnalyzer.java:494)
at org.owasp.dependencycheck.analyzer.NodeAuditAnalyzer.analyzeDependency (NodeAuditAnalyzer.java:151)
at org.owasp.dependencycheck.analyzer.AbstractAnalyzer.analyze (AbstractAnalyzer.java:131)
at org.owasp.dependencycheck.AnalysisTask.call (AnalysisTask.java:88)
at org.owasp.dependencycheck.AnalysisTask.call (AnalysisTask.java:37)
at java.util.concurrent.FutureTask.run (FutureTask.java:317)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
at java.lang.Thread.run (Thread.java:1583)

Have test cases been added to cover the new functionality?

no

@boring-cyborg boring-cyborg bot added the core changes to core label Jul 31, 2025
@HandyG52 HandyG52 changed the title Return unsorted vulnerabilities in new HashSet, avoiding CoMod fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod Jul 31, 2025
@HandyG52 HandyG52 changed the title fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod Aug 1, 2025
@nhumblot nhumblot added the bug label Aug 6, 2025
@nhumblot
Copy link
Collaborator

nhumblot commented Aug 6, 2025

Relates to #5809 & #7177

Thank you for your help!

Copy link
Collaborator

@nhumblot nhumblot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the callers of the updated method and did not see any call to Set<Vulnerability> getVulnerabilities(boolean sorted) that would try to add a new Vulnerability to the returned Set<Vulnerability>.

@nhumblot nhumblot merged commit 4333171 into dependency-check:main Aug 6, 2025
8 checks passed
@jeremylong jeremylong added this to the 12.1.4 milestone Aug 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug core changes to core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants