diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index ee3ab2fdb1e..335206d3910 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,6 +7,9 @@ assignees: ''
---
+**Precondition**
+- [ ] I checked the issues list for existing open or closed reports of the same problem.
+
**Describe the bug**
A clear and concise description of what the bug is.
diff --git a/.github/ISSUE_TEMPLATE/false-positive-report.yml b/.github/ISSUE_TEMPLATE/false-positive-report.yml
index 65e34b4c9d2..080828b4c7f 100644
--- a/.github/ISSUE_TEMPLATE/false-positive-report.yml
+++ b/.github/ISSUE_TEMPLATE/false-positive-report.yml
@@ -6,12 +6,22 @@ body:
- type: markdown
attributes:
value: |
- False Positive identified.
+ **Ensure you are using the latest version of dependency-check.**
+
+ **Automation is used to process most false positives reports**; failure to follow these guidelines will delay the process:
+
+ - Only enter a **single (1) Package URL**.
+ - Only enter a **single (1) CPE or CVE**.
+ - If filing a CPE report you do not need to add the CVEs. Note that **most reports should be for incorrectly matched CPEs**.
+
+ If reporting false positives for multiple PURL and/or CPE please file multiple reports.
+
+ Thank you for filing a false positive report!
- type: input
id: purl
attributes:
label: Package URl
- description: The identified package URL as identified in the HTML Report.
+ description: Please enter the single identified package URL as identified in the HTML Report. Only a **single PURL** can be specified, if you are reporting more then one - please open two issues using this template.
placeholder: ex. pkg:maven/org.apache.logging.log4j/log4j-slf4j-impl@2.12.1
validations:
required: true
@@ -19,7 +29,7 @@ body:
id: cpe
attributes:
label: CPE
- description: The Common Platform enumeration (CPE) as identified in the HTML Report. Please put backtic characters around the CPE to ensure it displays correctly.
+ description: Please enter the single Common Platform enumeration (CPE) as identified in the HTML Report. Only a **single CPE** can be specified. **Please put backtick characters around the CPE to ensure it displays correctly**.
placeholder: ex. `cpe:2.3:a:apache:log4j:2.12.1:*:*:*:*:*:*:*`
validations:
required: true
@@ -27,7 +37,7 @@ body:
id: cve
attributes:
label: CVE
- description: The vulnerability name as identified in the HTML Report. This is optional and may not be needed as most FP reports are due to an incorrect CPE.
+ description: The vulnerability name as identified in the HTML Report. If specifying a CPE this is not necessary; if entered please enter only a **single CVE**; if multiple CVE should be suppressed please enter multiple FP reports. This is optional and may not be needed as most FP reports are due to an incorrect CPE.
placeholder: ex. CVE-2021-44228
validations:
required: false
@@ -58,4 +68,4 @@ body:
label: Description
description: Additional information regarding the false positive report.
validations:
- required: false
\ No newline at end of file
+ required: false
diff --git a/.github/contributing.md b/.github/contributing.md
index c70f3a911c4..646996f90e4 100644
--- a/.github/contributing.md
+++ b/.github/contributing.md
@@ -3,8 +3,8 @@
## Reporting Bugs
- Ensure you're running the latest version of dependency-check.
-- Ensure the bug has not [already been reported](https://github.com/jeremylong/DependencyCheck/issues).
-- If you're unable to find an open issue addressing the problem, please [submit a new issue](https://github.com/jeremylong/DependencyCheck/issues/new/choose).
+- Ensure the bug has not [already been reported](https://github.com/dependency-check/DependencyCheck/issues).
+- If you're unable to find an open issue addressing the problem, please [submit a new issue](https://github.com/dependency-check/DependencyCheck/issues/new/choose).
- Please fill out the appropriate section of the bug report template provided.
- Delete any sections not needed in the template.
@@ -14,13 +14,13 @@
## Asking Questions
-- Your question may be answered by taking a look at the [documentation](https://jeremylong.github.io/DependencyCheck/).
-- Search both the [open and closed issues issues in GitHub](https://github.com/jeremylong/DependencyCheck/issues/)
-- If you still have a question ask a [new question](https://github.com/jeremylong/DependencyCheck/issues/new?assignees=&labels=question&template=ask-a-question.md&title=)
+- Your question may be answered by taking a look at the [documentation](https://dependency-check.github.io/DependencyCheck/).
+- Search both the [open and closed issues issues in GitHub](https://github.com/dependency-check/DependencyCheck/issues/)
+- If you still have a question ask a [new question](https://github.com/dependency-check/DependencyCheck/issues/new?assignees=&labels=question&template=ask-a-question.md&title=)
## Enhancement Requests
-- Suggest changes by [submitting a new issue](https://github.com/jeremylong/DependencyCheck/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=) and begin coding.
+- Suggest changes by [submitting a new issue](https://github.com/dependency-check/DependencyCheck/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=) and begin coding.
## Contributing Code
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 65449fc67fa..95c773197c9 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -11,10 +11,4 @@ updates:
- package-ecosystem: "docker"
directory: "/"
schedule:
- interval: "daily"
- ignore:
- # stay .net 3.1
- - dependency-name: "mcr.microsoft.com/dotnet/runtime"
- versions:
- - "5.x"
- - "6.x"
+ interval: "daily"
diff --git a/.github/lock.yml b/.github/lock.yml
deleted file mode 100644
index 16260112371..00000000000
--- a/.github/lock.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Number of days of inactivity before a closed issue or pull request is locked
-daysUntilLock: 30
-
-# Issues and pull requests with these labels will not be locked. Set to `[]` to disable
-exemptLabels: []
-
-# Label to add before locking, such as `outdated`. Set to `false` to disable
-lockLabel: false
-
-# Comment to post before locking. Set to `false` to disable
-lockComment: false
-
-# Assign `resolved` as the reason for locking. Set to `false` to disable
-setLockReason: false
-
-# Limit to only `issues` or `pulls`
-# only: issues
-
-# Optionally, specify configuration settings just for `issues` or `pulls`
-# issues:
-# exemptLabels:
-# - help-wanted
-# lockLabel: outdated
-
-# pulls:
-# daysUntilLock: 30
-
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index fa049cb30e2..c2b6de9bd72 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,8 +1,16 @@
-## Fixes Issue #
-
## Description of Change
-*Please add a description of the proposed change*
+
+
+## Related issues
+
+
## Have test cases been added to cover the new functionality?
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e10b84158cc..850054c0bb5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -20,12 +20,12 @@ jobs:
- name: Install gpg secret key
id: install-gpg-key
run: |
- cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import
+ cat <(echo -e "${{ secrets.GPG_PRIVATE_KEY }}") | gpg --batch --import
gpg --list-secret-keys --keyid-format LONG
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -33,53 +33,55 @@ jobs:
${{ runner.os }}-maven-
- name: Check Local Maven Cache
id: maven-it-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: maven/target/local-repo
key: mvn-it-repo
- name: Check ODC Data Cache
id: odc-data-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: core/target/data
key: odc-data
- - uses: actions/setup-dotnet@v3.0.3
+ - uses: actions/setup-dotnet@v5.0.0
with:
- dotnet-version: '6.0.x'
- - name: Set up JDK 1.8
- id: jdk-8
- uses: actions/setup-java@v3
+ dotnet-version: '8.0.x'
+ - name: Set up JDK 11
+ id: jdk-11
+ uses: actions/setup-java@v5
with:
- java-version: 8
+ java-version: 11
distribution: 'zulu'
- server-id: ossrh
- server-username: ${{ secrets.OSSRH_USERNAME }}
- server-password: ${{ secrets.OSSRH_TOKEN }}
- - uses: pnpm/action-setup@v2.2.4
+ server-id: central
+ server-username: ${{ secrets.CENTRAL_USER }}
+ server-password: ${{ secrets.CENTRAL_PASSWORD }}
+ - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 6.0.2
- name: Build Snapshot with Maven
id: build-snapshot
env:
- MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
- MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
- run: mvn -s settings.xml -Prelease clean package verify source:jar javadoc:jar gpg:sign deploy -DreleaseTesting --no-transfer-progress --batch-mode -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
+ MAVEN_USERNAME: ${{ secrets.CENTRAL_USER }}
+ MAVEN_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PRIVATE_KEY_PASSWORD }}
+ NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
+ run: mvn -V -s settings.xml -Prelease clean package verify source:jar javadoc:jar gpg:sign deploy -DreleaseTesting --no-transfer-progress --batch-mode
- name: SARIF Multitool
- uses: microsoft/sarif-actions@v0.1
+ uses: microsoft/sarif-actions@v0.2
with:
# Command to be sent to SARIF Multitool
command: 'validate core/target/test-reports/Report.sarif'
- name: Archive IT test logs
id: archive-logs
if: always()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: it-test-logs
retention-days: 7
path: maven/target/it/**/build.log
- name: Archive code coverage results
id: archive-coverage
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: code-coverage-report
retention-days: 7
@@ -88,7 +90,7 @@ jobs:
**/target/jacoco-results/**/*.html
- name: Archive Snapshot
id: archive-snapshot
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: archive-snapshot
retention-days: 7
@@ -99,20 +101,20 @@ jobs:
ant/target/*.zip
cli/target/*.zip
- publish_coverage:
- name: publish code coverage reports
- runs-on: ubuntu-latest
- needs: build
- steps:
- - name: Download coverage reports
- uses: actions/download-artifact@v3
- with:
- name: code-coverage-report
- - name: Run codacy-coverage-reporter
- uses: codacy/codacy-coverage-reporter-action@master
- with:
- project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
- coverage-reports: utils/target/jacoco-results/jacoco.xml,core/target/jacoco-results/jacoco.xml,maven/target/jacoco-results/jacoco.xml,ant/target/jacoco-results/jacoco.xml,cli/target/jacoco-results/jacoco.xml
+# publish_coverage:
+# name: publish code coverage reports
+# runs-on: ubuntu-latest
+# needs: build
+# steps:
+# - name: Download coverage reports
+# uses: actions/download-artifact@v5
+# with:
+# name: code-coverage-report
+# - name: Run codacy-coverage-reporter
+# uses: codacy/codacy-coverage-reporter-action@master
+# with:
+# project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+# coverage-reports: utils/target/jacoco-results/jacoco.xml,core/target/jacoco-results/jacoco.xml,maven/target/jacoco-results/jacoco.xml,ant/target/jacoco-results/jacoco.xml,cli/target/jacoco-results/jacoco.xml
docker:
permissions:
@@ -126,22 +128,34 @@ jobs:
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Download release build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v5
with:
name: archive-snapshot
+ - name: Set up Docker
+ uses: docker/setup-docker-action@v4
+ with:
+ daemon-config: |
+ {
+ "debug": true,
+ "features": {
+ "containerd-snapshotter": true
+ }
+ }
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
- name: Build Docker Image
run: ./build-docker.sh
- name: build scan target
- run: mvn -s settings.xml package -DskipTests=true --no-transfer-progress --batch-mode
+ run: mvn -V -s settings.xml package -DskipTests=true --no-transfer-progress --batch-mode
- name: Test Docker Image
run: ./test-docker.sh
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 8a2facfec59..428f96ee81a 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -33,11 +33,11 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -61,4 +61,4 @@ jobs:
mvn -s settings.xml clean package -DskipTests=true --no-transfer-progress --batch-mode
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v4
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
deleted file mode 100644
index c5cdec4008b..00000000000
--- a/.github/workflows/coverity.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: coverity-scan
-on:
- schedule:
- - cron: '0 0 * * SAT'
-
-permissions:
- contents: read
-
-jobs:
- scan:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Set up JDK 1.8
- id: jdk-8
- uses: actions/setup-java@v3
- with:
- java-version: 8
- distribution: 'zulu'
- - name: Get coverity cli
- run: |
- wget https://scan.coverity.com/download/linux64 --no-verbose --post-data "token=${{ secrets.COVERITY_TOKEN }}&project=jeremylong%2FDependencyCheck" -O coverity_tool.tgz
- mkdir coverity_tool
- tar xzf coverity_tool.tgz --strip 1 -C coverity_tool
- - name: Perform coverity scan
- run: |
- export PATH=`pwd`/coverity_tool/bin:$PATH
- cov-build --dir cov-int mvn -DskipTests=true package --no-transfer-progress --batch-mode
- - name: Submit coverity scan
- run: |
- tar czvf scan.tgz cov-int
- curl --form token=${{ secrets.COVERITY_TOKEN }} \
- --form email=jeremy.long@gmail.com \
- --form file=@scan.tgz \
- --form version="main" \
- --form description="Weekly Scan" \
- https://scan.coverity.com/builds?project=jeremylong%2FDependencyCheck
diff --git a/.github/workflows/false-positive-approvals.yml b/.github/workflows/false-positive-approvals.yml
index cec937428f5..32b978d9e96 100644
--- a/.github/workflows/false-positive-approvals.yml
+++ b/.github/workflows/false-positive-approvals.yml
@@ -17,19 +17,21 @@ jobs:
contains(github.event.comment.body,'approved') &&
(github.event.comment.user.login == 'jeremylong' ||
github.event.comment.user.login == 'aikebah' ||
- github.event.comment.user.login == 'nhumblot') }}
+ github.event.comment.user.login == 'nhumblot' ||
+ github.event.comment.user.login == 'marcelstoer' ||
+ github.event.comment.user.login == 'chadlwilson') }}
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
with:
ref: generatedSuppressions
- - uses: actions/setup-node@v3.6.0
+ - uses: actions/setup-node@v5.0.0
- run: |
npm install fast-xml-parser@4.0.9
npm install fs
- name: Commit Suppression Rule
id: fp-ops-commit
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
with:
script: |
const { execSync } = require("child_process");
@@ -150,14 +152,14 @@ jobs:
}
- name: Publish Updated Suppressions
if: ${{ steps.fp-ops-commit.outputs.publish == 'true' }}
- uses: JamesIves/github-pages-deploy-action@v4.4.1
+ uses: JamesIves/github-pages-deploy-action@v4.7.3
with:
branch: gh-pages
folder: suppressions
target-folder: suppressions
- name: Message failure
if: ${{ failure() || steps.fp-ops-commit.outputs.failed }}
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
with:
script: |
github.rest.issues.createComment({
diff --git a/.github/workflows/false-positive-ops.yml b/.github/workflows/false-positive-ops.yml
index ab8e7947ccf..81b0bb9f6db 100644
--- a/.github/workflows/false-positive-ops.yml
+++ b/.github/workflows/false-positive-ops.yml
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Remove Labels
if: contains(github.event.issue.labels.*.name, 'pending more information')
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
with:
script: |
github.rest.issues.removeLabel({
@@ -32,7 +32,7 @@ jobs:
repo: context.repo.repo
})
)
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
with:
path: odc
- name: Parse False Positive Issue
@@ -41,7 +41,7 @@ jobs:
with:
issue-body: ${{ github.event.issue.body }}
template-path: odc/.github/ISSUE_TEMPLATE/false-positive-report.yml
- - uses: actions/setup-node@v3.6.0
+ - uses: actions/setup-node@v5.0.0
with:
node-version: 14
- name: Initialize npm
@@ -50,7 +50,7 @@ jobs:
npm install packageurl-js
- name: Parse Package URL
id: purl-parser
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
env:
PURL: ${{ fromJSON(steps.issue-parser.outputs.jsonString).purl }}
with:
@@ -83,7 +83,7 @@ jobs:
ARTIFACTID: ${{ fromJSON(steps.purl-parser.outputs.result).name }}
VERSION: ${{ fromJSON(steps.purl-parser.outputs.result).version }}
run: |
- ver=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt)
+ ver=$(curl -s https://dependency-check.github.io/DependencyCheck/current.txt)
mkdir ./fp-project
cp ${{github.workspace}}/odc/.github/workflows/files/maven-pom.start ./fp-project/pom.xml
echo -n $ver >> ./fp-project/pom.xml
@@ -111,9 +111,9 @@ jobs:
cd ..
- name: Setup dotnet
if: ${{ fromJSON(steps.purl-parser.outputs.result).type == 'nuget' }}
- uses: actions/setup-dotnet@v3.0.3
+ uses: actions/setup-dotnet@v5.0.0
with:
- dotnet-version: '6.0.x'
+ dotnet-version: '8.0.x'
- name: Setup dotnet fp-project
if: ${{ fromJSON(steps.purl-parser.outputs.result).type == 'nuget' }}
env:
@@ -126,7 +126,7 @@ jobs:
dotnet publish
cd ..
- name: "Check for setup complete"
- uses: andstor/file-existence-action@v2
+ uses: andstor/file-existence-action@v3
id: check_files
with:
files: "./fp-project"
@@ -140,15 +140,17 @@ jobs:
args: >
--failOnCVSS 11
--enableExperimental
+ --ossIndexUsername ${{ secrets.OSS_INDEX_USERNAME }}
+ --ossIndexPassword ${{ secrets.OSS_INDEX_API_TOKEN }}
- name: Upload FP Report
if: steps.check_files.outputs.files_exists == 'true'
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: FP Report
path: ${{github.workspace}}/reports
- name: Comment on maven issue
if: ${{ fromJSON(steps.purl-parser.outputs.result).type == 'maven' }}
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
env:
GROUPID: ${{ fromJSON(steps.purl-parser.outputs.result).namespace }}
ARTIFACTID: ${{ fromJSON(steps.purl-parser.outputs.result).name }}
@@ -199,7 +201,7 @@ jobs:
})
- name: Comment on npm issue
if: ${{ fromJSON(steps.purl-parser.outputs.result).type == 'npm' }}
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
env:
NAME: ${{ fromJSON(steps.purl-parser.outputs.result).name }}
VERSION: ${{ fromJSON(steps.purl-parser.outputs.result).version }}
@@ -246,7 +248,7 @@ jobs:
})
- name: Comment on dotnet issue
if: ${{ fromJSON(steps.purl-parser.outputs.result).type == 'nuget' }}
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
env:
NAME: ${{ fromJSON(steps.purl-parser.outputs.result).name }}
VERSION: ${{ fromJSON(steps.purl-parser.outputs.result).version }}
@@ -293,7 +295,7 @@ jobs:
- name: Message failure
if: ${{ failure() }}
- uses: actions/github-script@v6.4.0
+ uses: actions/github-script@v8.0.0
with:
script: |
github.rest.issues.createComment({
diff --git a/.github/workflows/files/maven-pom.middle b/.github/workflows/files/maven-pom.middle
index 51c6559871d..9592cf9a49e 100644
--- a/.github/workflows/files/maven-pom.middle
+++ b/.github/workflows/files/maven-pom.middle
@@ -14,11 +14,10 @@
https://repo.itextsupport.com/releases
- spring
- spring
- https://repo.spring.io/release/
+ spring-milestones
+ springmilestones
+ https://repo.spring.io/milestone/
-
mavengooglemavengoogle
@@ -54,11 +53,21 @@
gradlehttps://plugins.gradle.org/m2/
+
+ splunk-artifactory
+ Splunk Releases
+ https://splunk.jfrog.io/splunk/ext-releases-local
+ vaadin-addonvaadin addonshttps://vaadin.com/nexus/content/repositories/vaadin-addons/
+
+ hazelcast-release
+ Hazelcast Repository
+ https://repository.hazelcast.com/release/
+ false
@@ -87,4 +96,4 @@
https://oss.sonatype.org/service/local/staging/deploy/maven2/
-
\ No newline at end of file
+
diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml
index ebefb0f01fb..0c4125f1bd8 100644
--- a/.github/workflows/lint-pr.yml
+++ b/.github/workflows/lint-pr.yml
@@ -18,6 +18,6 @@ jobs:
statuses: write
runs-on: ubuntu-latest
steps:
- - uses: amannn/action-semantic-pull-request@v5.2.0
+ - uses: amannn/action-semantic-pull-request@v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml
new file mode 100644
index 00000000000..9b7bd2d21ac
--- /dev/null
+++ b/.github/workflows/lock.yml
@@ -0,0 +1,24 @@
+name: 'Lock Threads'
+
+on:
+ schedule:
+ - cron: '0 3 * * *'
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+ discussions: write
+
+concurrency:
+ group: lock-threads
+
+jobs:
+ action:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: dessant/lock-threads@v5
+ with:
+ issue-inactive-days: '30'
+ pr-inactive-days: '30'
+ discussion-inactive-days: '30'
diff --git a/.github/workflows/publish-suppressions.yml b/.github/workflows/publish-suppressions.yml
new file mode 100644
index 00000000000..75245cb59f9
--- /dev/null
+++ b/.github/workflows/publish-suppressions.yml
@@ -0,0 +1,40 @@
+name: Publish Suppressions
+
+on:
+ workflow_dispatch:
+
+permissions: {}
+jobs:
+ update_suppression:
+ permissions:
+ contents: write # to push changes in repo (jamesives/github-pages-deploy-action)
+
+ name: Publish Suppressions
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v5
+ with:
+ ref: generatedSuppressions
+ - uses: actions/setup-node@v5.0.0
+ - run: |
+ npm install fs
+ - name: Create Generated Suppressions XML
+ uses: actions/github-script@v8.0.0
+ with:
+ script: |
+ const fs = require('fs');
+ const generatedSuppressions = fs.readFileSync('generatedSuppressions.xml', 'utf8');
+ if (!fs.existsSync('./suppressions')){
+ fs.mkdirSync('./suppressions');
+ }
+ fs.appendFileSync('suppressions/publishedSuppressions.xml', '\n' + generatedSuppressions + '\n', function (err) {
+ if (err) throw err;
+ console.log('publishedSuppressions.xml created');
+ });
+ - name: Publish Updated Suppressions
+ uses: JamesIves/github-pages-deploy-action@v4.7.3
+ with:
+ branch: gh-pages
+ folder: suppressions
+ target-folder: suppressions
+
diff --git a/.github/workflows/pull_requests.yml b/.github/workflows/pull_requests.yml
index 5d28966f2de..fc35f684891 100644
--- a/.github/workflows/pull_requests.yml
+++ b/.github/workflows/pull_requests.yml
@@ -10,104 +10,190 @@ jobs:
test:
name: Build and Test
permissions:
+ security-events: write
contents: read
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository/
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - uses: actions/setup-dotnet@v3.0.3
+ - uses: actions/setup-dotnet@v5.0.0
with:
- dotnet-version: '6.0.x'
- - name: Set up JDK 1.8
- id: jdk-8
- uses: actions/setup-java@v3
+ dotnet-version: '8.0.x'
+ - name: Set up JDK 11
+ id: jdk-11
+ uses: actions/setup-java@v5
with:
- java-version: 8
+ java-version: 11
distribution: 'zulu'
- - uses: pnpm/action-setup@v2.2.4
+ - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 6.0.2
- name: Test with Maven
id: build
run: |
- mvn -s settings.xml -pl utils,core,cli,ant,archetype -am compile verify --no-transfer-progress --batch-mode
+ mvn -V -s settings.xml -pl utils,core,cli,ant,archetype -am compile verify --no-transfer-progress --batch-mode
- name: SARIF Multitool
- uses: microsoft/sarif-actions@v0.1
+ uses: microsoft/sarif-actions@v0.2
with:
# Command to be sent to SARIF Multitool
command: 'validate core/target/test-reports/Report.sarif'
-
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: utils/target/spotbugsSarif.json
+ category: spotbugs-utils
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: cli/target/spotbugsSarif.json
+ category: spotbugs-cli
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: ant/target/spotbugsSarif.json
+ category: spotbugs-ant
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: core/target/spotbugsSarif.json
+ category: spotbugs-core
+ - name: Archive Snapshot
+ id: archive-snapshot
+ uses: actions/upload-artifact@v4
+ with:
+ name: archive-snapshot
+ retention-days: 1
+ path: |
+ **/target/*.asc
+ **/target/*.jar
+ **/target/*.pom
+ ant/target/*.zip
+ cli/target/*.zip
+
maven:
name: Regression Test Maven Plugin
permissions:
+ security-events: write
contents: read
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository/
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - uses: actions/setup-dotnet@v3.0.3
+ - uses: actions/setup-dotnet@v5.0.0
with:
- dotnet-version: '6.0.x'
- - name: Set up JDK 1.8
- id: jdk-8
- uses: actions/setup-java@v3
+ dotnet-version: '8.0.x'
+ - name: Set up JDK 11
+ id: jdk-11
+ uses: actions/setup-java@v5
with:
- java-version: 8
+ java-version: 11
distribution: 'zulu'
- - uses: pnpm/action-setup@v2.2.4
+ - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 6.0.2
- name: Regression Test Maven Plugin
id: build
+ env:
+ NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
run: |
- mvn -s settings.xml -pl utils,core,maven -am compile verify -DtestMavenPlugin -DreleaseTesting --no-transfer-progress --batch-mode
+ mvn -V -s settings.xml -pl maven -am compile verify -DtestMavenPlugin -DreleaseTesting --no-transfer-progress --batch-mode
- name: Archive IT test logs
id: archive-logs
if: always()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: it-test-logs
retention-days: 7
path: maven/target/it/**/build.log
- audit:
- runs-on: ubuntu-latest
- permissions:
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: maven/target/spotbugsSarif.json
+ category: spotbugs-maven
+
+ checkstyle:
+ name: Checkstyle Validation
+ permissions:
+ security-events: write
contents: read
- pull-requests: write
- name: Audit
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository/
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- - name: Semgrep
- id: semgrep
- run: |
- docker run --rm -v "${PWD}:/src" returntocorp/semgrep semgrep --config "p/ci" --sarif > semgrep.sarif
- - name: Maven Site
- if: always()
- run: |
- mvn -s settings.xml package site -DskipTests=true --no-transfer-progress --batch-mode
- - name: Publish Comments
- if: always()
+ - name: Set up JDK 11
+ id: jdk-11
+ uses: actions/setup-java@v5
+ with:
+ java-version: 11
+ distribution: 'zulu'
+ - name: Checkstyle
+ id: checkstyle
run: |
- mvn se.bjurr.violations:violation-comments-to-github-maven-plugin:violation-comments --no-transfer-progress --batch-mode -DpullRequestId=${{ github.event.pull_request.number }} -DoAuth2Token=${{ secrets.GITHUB_TOKEN }}
+ mvn -V -s settings.xml checkstyle:checkstyle-aggregate --no-transfer-progress --batch-mode
+ - name: Upload SARIF file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: target/checkstyle-result.sarif
+ category: checkstyle
+
+ docker:
+ permissions:
+ contents: read # to fetch code (actions/checkout)
+
+ name: Build and Test Docker
+ runs-on: ubuntu-latest
+ needs: test
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v5
+ - name: Check Maven Cache
+ id: maven-cache
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+ - name: Download release build
+ uses: actions/download-artifact@v5
+ with:
+ name: archive-snapshot
+ - name: Set up Docker
+ uses: docker/setup-docker-action@v4
+ with:
+ daemon-config: |
+ {
+ "debug": true,
+ "features": {
+ "containerd-snapshotter": true
+ }
+ }
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Build Docker Image
+ run: ./build-docker.sh
+ - name: build scan target
+ run: mvn -V -s settings.xml package -DskipTests=true --no-transfer-progress --batch-mode
+ - name: Test Docker Image
+ run: ./test-docker.sh
diff --git a/.github/workflows/purge-cache.yml b/.github/workflows/purge-cache.yml
index 0c22a03c533..9820e850a90 100644
--- a/.github/workflows/purge-cache.yml
+++ b/.github/workflows/purge-cache.yml
@@ -10,10 +10,10 @@ jobs:
name: Purge GitHub Cache
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -21,13 +21,13 @@ jobs:
${{ runner.os }}-maven-
- name: Check Local Maven Cache
id: maven-it-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: maven/target/local-repo
key: mvn-it-repo
- name: Check ODC Data Cache
id: odc-data-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: core/target/data
key: odc-data
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 67d500e3706..d2cbf30c8e7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -2,10 +2,10 @@ name: Build and Deploy Release
##
## Automates the release process
-## 1. Update the 'body:' below and the changelog.md
+## 1. Run `./list-changes.sh` and update the changelog.md.
## 2. Run `./prepare-release.sh`
## 3. Create PR, merge PR
-## 4. Run `git push origin main --tags`
+## 4. Run `git push origin --tags`
##
permissions:
@@ -24,40 +24,40 @@ jobs:
- name: Install gpg secret key
id: install-gpg-key
run: |
- cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import
+ cat <(echo -e "${{ secrets.GPG_PRIVATE_KEY }}") | gpg --batch --import
gpg --list-secret-keys --keyid-format LONG
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v5
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository/
key: mvn-repo
- name: Check Local Maven Cache
id: maven-it-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: maven/target/local-repo
key: mvn-it-repo
- name: Check ODC Data Cache
id: odc-data-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: core/target/data
key: odc-data
- - uses: actions/setup-dotnet@v3.0.3
+ - uses: actions/setup-dotnet@v5.0.0
with:
- dotnet-version: '6.0.x'
- - name: Set up JDK 1.8
- id: jdk-8
- uses: actions/setup-java@v3
+ dotnet-version: '8.0.x'
+ - name: Set up JDK 11
+ id: jdk-11
+ uses: actions/setup-java@v5
with:
- java-version: 8
+ java-version: 11
distribution: 'zulu'
- server-id: ossrh
- server-username: ${{ secrets.OSSRH_USERNAME }}
- server-password: ${{ secrets.OSSRH_TOKEN }}
- - uses: pnpm/action-setup@v2.2.4
+ server-id: central
+ server-username: ${{ secrets.CENTRAL_USER }}
+ server-password: ${{ secrets.CENTRAL_PASSWORD }}
+ - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: 6.0.2
- name: Configure Git user
@@ -72,13 +72,15 @@ jobs:
id: build-release
timeout-minutes: 120
env:
- MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
- MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
+ MAVEN_USERNAME: ${{ secrets.CENTRAL_USER }}
+ MAVEN_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}
+ MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PRIVATE_KEY_PASSWORD }}
+ NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
run: |
- mvn -s settings.xml -Prelease "-DnexusUrl=https://oss.sonatype.org/" clean package source:jar javadoc:jar gpg:sign deploy site site:stage -DreleaseTesting --no-transfer-progress --batch-mode -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
+ mvn -V -s settings.xml -Prelease clean package source:jar javadoc:jar gpg:sign deploy site site:stage -DreleaseTesting --no-transfer-progress --batch-mode
- name: Archive code coverage results
id: archive-coverage
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: code-coverage-report
retention-days: 7
@@ -87,7 +89,7 @@ jobs:
**/target/jacoco-results/**/*.html
- name: Archive Release
id: archive-release
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: archive-release
retention-days: 7
@@ -100,26 +102,26 @@ jobs:
target/*.buildinfo
- name: Archive Site
id: archive-site
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: archive-site
retention-days: 7
path: target/staging/
- publish_coverage:
- name: publish code coverage reports
- runs-on: ubuntu-latest
- needs: build
- steps:
- - name: Download coverage reports
- uses: actions/download-artifact@v3
- with:
- name: code-coverage-report
- - name: Run codacy-coverage-reporter
- uses: codacy/codacy-coverage-reporter-action@master
- with:
- project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
- coverage-reports: utils/target/jacoco-results/jacoco.xml,core/target/jacoco-results/jacoco.xml,maven/target/jacoco-results/jacoco.xml,ant/target/jacoco-results/jacoco.xml,cli/target/jacoco-results/jacoco.xml
+# publish_coverage:
+# name: publish code coverage reports
+# runs-on: ubuntu-latest
+# needs: build
+# steps:
+# - name: Download coverage reports
+# uses: actions/download-artifact@v5
+# with:
+# name: code-coverage-report
+# - name: Run codacy-coverage-reporter
+# uses: codacy/codacy-coverage-reporter-action@master
+# with:
+# project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+# coverage-reports: utils/target/jacoco-results/jacoco.xml,core/target/jacoco-results/jacoco.xml,maven/target/jacoco-results/jacoco.xml,ant/target/jacoco-results/jacoco.xml,cli/target/jacoco-results/jacoco.xml
docker:
name: Publish Docker
@@ -131,22 +133,34 @@ jobs:
steps:
- name: Check Maven Cache
id: maven-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/.m2/repository/
key: mvn-repo
- name: Check Docker ODC Cache
id: docker-odc-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~/OWASP-Dependency-Check
key: docker-repo
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
- name: Download release build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v5
with:
name: archive-release
+ - name: Set up Docker
+ uses: docker/setup-docker-action@v4
+ with:
+ daemon-config: |
+ {
+ "debug": true,
+ "features": {
+ "containerd-snapshotter": true
+ }
+ }
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
- name: Build Docker Image
run: ./build-docker.sh
- name: build scan target
@@ -164,14 +178,14 @@ jobs:
needs: build
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
- name: Get version
id: get-version
run: |
VERSION=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Download release build
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v5
with:
name: archive-release
- name: Create Release
@@ -185,13 +199,7 @@ jobs:
prerelease: false
draft: false
body: |
- ### Fixed
-
- - NullPointerException in MSBuildAnalyzer (#5589)
- - SQL Syntax for Oracle (#5590)
- - Use `https://` URLs in report templates (#5582)
-
- See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/64?closed=1).
+ Refer to the [CHANGELOG.md](https://github.com/dependency-check/DependencyCheck/blob/main/CHANGELOG.md#change-log) for information about improvements and upgrade notes.
- name: Upload CLI
id: upload-release-cli
@@ -250,9 +258,9 @@ jobs:
needs: build
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v5
- name: Download Site
- uses: actions/download-artifact@v3
+ uses: actions/download-artifact@v5
with:
name: archive-site
path: target/staging
@@ -260,7 +268,7 @@ jobs:
run: ls -R
working-directory: target
- name: Deploy gh-pages
- uses: JamesIves/github-pages-deploy-action@v4.4.1
+ uses: JamesIves/github-pages-deploy-action@v4.7.3
with:
branch: gh-pages
folder: target/staging
diff --git a/.java-version b/.java-version
index 6259340971b..2dbc24b32d3 100644
--- a/.java-version
+++ b/.java-version
@@ -1 +1 @@
-1.8
+11.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dd26b3b1e1..6686cb21509 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,482 +1,976 @@
# Change Log
+## [Version 12.1.8](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.8) (2025-10-13)
+
+- fix: improve VulnerableSoftware comparison ([#8031](https://github.com/dependency-check/DependencyCheck/pull/8031))
+- build: fix flaky central test ([#8039](https://github.com/dependency-check/DependencyCheck/pull/8039))
+- docs: Improve Gradle docs wrt experimental analyzers, use of Central and Proxy configuration ([#8036](https://github.com/dependency-check/DependencyCheck/pull/8036))
+- docs: add note about central analyzer for gradle ([#8038](https://github.com/dependency-check/DependencyCheck/pull/8038))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/101?closed=1)
+
+## [Version 12.1.7](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.7) (2025-10-12)
+
+- fix: disable central analyzer after failures ([#7993](https://github.com/dependency-check/DependencyCheck/pull/7993))
+- fix: Suppress JVM warnings from Lucene within CLI ([#8003](https://github.com/dependency-check/DependencyCheck/pull/8003))
+- fix: Clean up Apache Lucene logging via SLF4j redirect ([#7979](https://github.com/dependency-check/DependencyCheck/pull/7979))
+- fix: Correct Archive Analyzer behaviour on certain tgz archives ([#7986](https://github.com/dependency-check/DependencyCheck/pull/7986))
+- fix: Update NVD CPE search URLs in generated reports to match new search interface ([#7970](https://github.com/dependency-check/DependencyCheck/pull/7970))
+- fix: improve OSS Index Error Reporting ([#7977](https://github.com/dependency-check/DependencyCheck/pull/7977))
+- fix(fp): Consolidate false positive suppression for false positives on Redis client libs ([#8017](https://github.com/dependency-check/DependencyCheck/pull/8017))
+- fix(fp): Fix more common false positives for popular PHP/composer frameworks with generic names ([#7994](https://github.com/dependency-check/DependencyCheck/pull/7994))
+- docs: improve slack notification documentation ([#8026](https://github.com/dependency-check/DependencyCheck/pull/8026))
+- docs: Documentation artifactory settings fix ([#7999](https://github.com/dependency-check/DependencyCheck/pull/7999))
+- docs: Clarify Nexus Analyzer requirements and usage ([#8000](https://github.com/dependency-check/DependencyCheck/pull/8000))
+- build: Build amd64 and arm64 multi-platform Docker image ([#7952](https://github.com/dependency-check/DependencyCheck/pull/7952))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/100?closed=1)
+
+## [Version 12.1.6](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.6) (2025-09-24)
+
+- fix: Disable OSS Index if its credentials are missing ([#7963](https://github.com/dependency-check/DependencyCheck/pull/7963))
+- fix: Correct CVSSv4 parsing for low precision OSSIndex values ([#7935](https://github.com/dependency-check/DependencyCheck/pull/7935))
+- fix(fp): Fix false positives for Redis Server against NPM/JS client libs ([#7942](https://github.com/dependency-check/DependencyCheck/pull/7942))
+- docs: Fix legacy GitHub links within docs and CHANGELOG ([#7944](https://github.com/dependency-check/DependencyCheck/pull/7944))
+- chore: fix version typo in security policy ([#7936](https://github.com/dependency-check/DependencyCheck/pull/7936))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/99?closed=1)
+
+## [Version 12.1.5](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.5) (2025-09-20)
+
+- **fix**: Update to support OSS Index Authentication Requirements ([#7920](https://github.com/dependency-check/DependencyCheck/pull/7920))
+ - Note: OSS Index will require authentication starting 9/22/2025. Users must configure a free account to continue using the OSS Index Analyzer. See https://ossindex.sonatype.org/doc/auth-required.
+- fix: add CVSSv4 to suppressed entries in JSON report ([#7900](https://github.com/dependency-check/DependencyCheck/pull/7900))
+- fix: correctly utilize CVSSv4 from ossindex ([#7899](https://github.com/dependency-check/DependencyCheck/pull/7899))
+- fix: npe when processing cve with empty configuration ([#7888](https://github.com/dependency-check/DependencyCheck/pull/7888))
+- fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod ([#7848](https://github.com/dependency-check/DependencyCheck/pull/7848))
+- fix: Return unsorted vulnerabilities in new HashSet, avoiding CoMod
+- fix: class loading problem with fat jars ([#7786](https://github.com/dependency-check/DependencyCheck/pull/7786)) ([#7787](https://github.com/dependency-check/DependencyCheck/pull/7787))
+- fix: Improve Artifactory handler log message ([#7838](https://github.com/dependency-check/DependencyCheck/pull/7838))
+- fix: classloading problem with fat jars ([#7786](https://github.com/dependency-check/DependencyCheck/pull/7786))
+- fix: Add null checking when parsing the license json in AbstractNpmAnalyzer. ([#7784](https://github.com/dependency-check/DependencyCheck/pull/7784))
+- fix(fp): resolves several false positives related to CVE-2021-41033 ([#7736](https://github.com/dependency-check/DependencyCheck/pull/7736))
+- docs: Clarify format of exclude patterns ([#7879](https://github.com/dependency-check/DependencyCheck/pull/7879))
+- docs: Document poetry-based analysis behaviour in Python analyzer ([#7855](https://github.com/dependency-check/DependencyCheck/pull/7855))
+- docs: request FP reporters use the latest version of ODC. ([#7820](https://github.com/dependency-check/DependencyCheck/pull/7820))
+- docs: update development pre-reqs ([#7792](https://github.com/dependency-check/DependencyCheck/pull/7792))
+- docs: fix minor typos in false positive issue template ([#7763](https://github.com/dependency-check/DependencyCheck/pull/7763))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/98?closed=1)
+
+## [Version 12.1.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.3) (2025-06-10)
+
+- fix: correct regex matches introduced in 12.1.2 ([#7726](https://github.com/dependency-check/DependencyCheck/pull/7726))
+- build(deps): bump org.semver4j:semver4j from 5.7.0 to 5.7.1 ([#7718](https://github.com/dependency-check/DependencyCheck/pull/7718))
+- build(deps): bump junit.version from 5.13.0 to 5.13.1 ([#7719](https://github.com/dependency-check/DependencyCheck/pull/7719))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/97?closed=1)
+
+## [Version 12.1.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.2) (2025-06-07)
+
+- fix: Allow configuring OSS Index user/pw directly ([#7640](https://github.com/dependency-check/DependencyCheck/pull/7640))
+- fix: remove vulnerable transitive dependency - beanutils ([#7705](https://github.com/dependency-check/DependencyCheck/pull/7705))
+- fix: Simplify PHP framework suppression for Composer ([#7693](https://github.com/dependency-check/DependencyCheck/pull/7693))
+- fix: update CPE pattern to remove FP ([#7684](https://github.com/dependency-check/DependencyCheck/pull/7684))
+- fix(cli): Patch generated Windows shell script for JAVACMD installs with spaces ([#7653](https://github.com/dependency-check/DependencyCheck/pull/7653))
+- fix: Resolve various WCAG accessibility / css issues in the HTML report ([#7629](https://github.com/dependency-check/DependencyCheck/pull/7629))
+- fix: [#7510](https://github.com/dependency-check/DependencyCheck/pull/7510) Display a dedicated message when receiving an HTTP 403 ([#7575](https://github.com/dependency-check/DependencyCheck/pull/7575))
+- docs: Make `Vulnerability Sources` in `Related Work` clearer ([#7691](https://github.com/dependency-check/DependencyCheck/pull/7691))
+- docs: [#7610](https://github.com/dependency-check/DependencyCheck/pull/7610) add a reference to NVD mirroring in getting started documentation ([#7611](https://github.com/dependency-check/DependencyCheck/pull/7611))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/96?closed=1)
+
+## [Version 12.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.1) (2025-04-05)
+
+- fix: resolve NVD data Parse error `com.fasterxml.jackson.core.JsonParseException: Unexpected character (']' (code 93))`
+ - bump open-vulnerability-client from 7.3.1 to 7.3.2 ([#7577](https://github.com/dependency-check/DependencyCheck/pull/7577))
+- fix: update links for repository move from `jeremylong` to the `dependency-check` organization ([#7373](https://github.com/dependency-check/DependencyCheck/pull/7373))
+- fix: resolve NPE when processing CVE-2025-2682 ([#7558](https://github.com/dependency-check/DependencyCheck/pull/7558))
+- fix: prevent rogue base suppression files ([#7544](https://github.com/dependency-check/DependencyCheck/pull/7544))
+- fix: [#6819](https://github.com/dependency-check/DependencyCheck/pull/6819) handle invalid toml file ([#7548](https://github.com/dependency-check/DependencyCheck/pull/7548))
+- fix: Use unscored severity only in absence of any CVSS baseScore ([#7530](https://github.com/dependency-check/DependencyCheck/pull/7530))
+- fix: protect against exotic version number of yarn ([#7525](https://github.com/dependency-check/DependencyCheck/pull/7525))
+- fix: Ignore require-bundle MANIFEST.MF entry for evidence ([#7523](https://github.com/dependency-check/DependencyCheck/pull/7523))
+- fix: avoid error on yarn berry audit when no vulnerability found ([#7501](https://github.com/dependency-check/DependencyCheck/pull/7501))
+- fix: improve null checks in Downloader ([#7493](https://github.com/dependency-check/DependencyCheck/pull/7493))
+- fix: improve null checks resolves https://github.com/dependency-check/dependency-check-gradle/issues/441
+- fix: Avoid FPs when Composer product name has php ([#7486](https://github.com/dependency-check/DependencyCheck/pull/7486))
+- fix: cli not honoring window paths correctly ([#7470](https://github.com/dependency-check/DependencyCheck/pull/7470))
+- fix: Also apply muteNoisyLoggers to UpdateMojo ([#7469](https://github.com/dependency-check/DependencyCheck/pull/7469))
+- fix: Make HC5 Downloader honor the connection- and readTimeout settings that the old URLConnectionFactory based downloads observed ([#7437](https://github.com/dependency-check/DependencyCheck/pull/7437))
+- docs: sync the supported Maven version with the one stated in the system requirement section ([#7570](https://github.com/dependency-check/DependencyCheck/pull/7570))
+- docs: update proxy config documentation ([#7550](https://github.com/dependency-check/DependencyCheck/pull/7550))
+- docs: Remove copyright as requested by the Apache foundation
+- docs: drop redundant text in the Internet Access Required section ([#7521](https://github.com/dependency-check/DependencyCheck/pull/7521))
+- docs: correct gradle documentation ([#7511](https://github.com/dependency-check/DependencyCheck/pull/7511))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/95?closed=1)
+
+## [Version 12.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.1.0) (2025-02-16)
+
+- build(deps): bump open-vulnerability-client to 7.2.2 ([#7407](https://github.com/dependency-check/DependencyCheck/pull/7407))
+ - resolves issue with downloading data from the NVD ([#7406](https://github.com/dependency-check/DependencyCheck/pull/7406))
+- fix: Improve thread safety issue [#7338](https://github.com/dependency-check/DependencyCheck/pull/7338) alternative ([#7367](https://github.com/dependency-check/DependencyCheck/pull/7367))
+- feat: Implement Yarn Berry Analyser ([#7319](https://github.com/dependency-check/DependencyCheck/pull/7319))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/94?closed=1)
+
+## [Version 12.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.0.2) (2025-01-29)
+
+- fix: correct JSON report error ([#7350](https://github.com/dependency-check/DependencyCheck/pull/7350))
+- fix: some compatability issues in the gitlab report ([#7349](https://github.com/dependency-check/DependencyCheck/pull/7349))
+- fix: ArtifactoryAnalyzer updated to use the HTTPClient5-based Downloader and skip unusable results ([#7293](https://github.com/dependency-check/DependencyCheck/pull/7293))
+- chore: allow messages via EngineVersionCheck ([#7353](https://github.com/dependency-check/DependencyCheck/pull/7353))
+- chore: switch from javax.json to jakarta.json ([#7326](https://github.com/dependency-check/DependencyCheck/pull/7326))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/93?closed=1).
+
+## [Version 12.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.0.1) (2025-01-19)
+
+- docs: Fix OSS Index Maven config documentation ([#7322](https://github.com/dependency-check/DependencyCheck/pull/7322))
+- Fix OSS Index Maven config documentation
+- chore(docs): Document Gradle plugin support for failBuildOnUnusedSuppressionRule ([#7307](https://github.com/dependency-check/DependencyCheck/pull/7307))
+- chore(docs): Correct analyzers config example to use Gradle dot-syntax ([#7305](https://github.com/dependency-check/DependencyCheck/pull/7305))
+- fix: improve error message on improperly configured serverId credentials in settings.xml ([#7313](https://github.com/dependency-check/DependencyCheck/pull/7313))
+- fix: Lower Basic serverId when Bearer was expected to a warning
+- fix: improve error message on improperly configured serverId credentials
+- fix: Correct nonProxyHosts support when no sys properties set ([#7306](https://github.com/dependency-check/DependencyCheck/pull/7306))
+- core(docs): Group failBuildOnUnusedSuppressionRule flag next to suppression file configuration
+- core(docs): Update Gradle plugin documentation for failBuildOnUnusedSuppressionRule support
+- fix: Correct nonProxyHosts support when no sys properties set
+- chore(docs): Correct analyzers config example to use Gradle dot-syntax
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/92?closed=1).
+
+## [Version 12.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v12.0.0) (2025-01-11)
+
+- BREAKING CHANGE: report on CVSS v4 ([#7204](https://github.com/dependency-check/DependencyCheck/pull/7204))
+ - the schema has been updated to include CVSS v4 for JSON and XML reports
+- feat: show from which dependency the CVE comes in failure report ([#7224](https://github.com/dependency-check/DependencyCheck/pull/7224))
+- feat: Use Maven settings decryption API for decrypting secrets from settings.xml ([#7284](https://github.com/dependency-check/DependencyCheck/pull/7284))
+- feat: Extend authentication to support Bearer token for many resources ([#7277](https://github.com/dependency-check/DependencyCheck/pull/7277))
+- feat: Add a flag to fail when one or more suppression rules are not used ([#7244](https://github.com/dependency-check/DependencyCheck/pull/7244))
+- fix: add product evidence as vendor to reduce FN ([#7295](https://github.com/dependency-check/DependencyCheck/pull/7295))
+- fix: Make the HTTP-Client use pre-emptive authentication ([#7255](https://github.com/dependency-check/DependencyCheck/pull/7255))
+- fix: Add the missing proxy credentials for suppressionFileUser/Password authentication scenario
+- fix: increase max retry count ([#7252](https://github.com/dependency-check/DependencyCheck/pull/7252))
+- fix: Make the HTTP-Client use pre-emptive authentication for configured server credentials and extend HTTPClient usage to Nexus search
+- fix: Tranform into UTC the last modified date from database ([#7222](https://github.com/dependency-check/DependencyCheck/pull/7222))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/91?closed=1).
+
+## [Version 11.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v11.1.1) (2024-12-04)
+
+- fix: re-enable issue locking ([#7220](https://github.com/dependency-check/DependencyCheck/pull/7220))
+- fix: add username/password properties to be able to authenticate for central.content.url and analyzer.central.url again ([#7169](https://github.com/dependency-check/DependencyCheck/pull/7169))
+- fix: rework replaceOrAddVulnerability ([#7177](https://github.com/dependency-check/DependencyCheck/pull/7177))
+- fix: do not log loading of JDBC driver ([#7155](https://github.com/dependency-check/DependencyCheck/pull/7155))
+- fix: expose flag to disable version check ([#7147](https://github.com/dependency-check/DependencyCheck/pull/7147))
+- fix: Gracefully handle CVEs with bad configuration nodes missing CPE match expressions ([#7125](https://github.com/dependency-check/DependencyCheck/pull/7125))
+- chore: cleanup base suppression ([#7138](https://github.com/dependency-check/DependencyCheck/pull/7138))
+- docs: update gradle configuration documentation ([#7176](https://github.com/dependency-check/DependencyCheck/pull/7176))
+- docs: update documentation for Gradle plugin ([#7143](https://github.com/dependency-check/DependencyCheck/pull/7143))
+- docs: improve false positive issue templat ([#7130](https://github.com/dependency-check/DependencyCheck/pull/7130))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/90?closed=1).
+
+## [Version 11.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v11.1.0) (2024-10-30)
+
+- feat: PHP Composer Analyzer now scans packages-dev by default ([#7114](https://github.com/dependency-check/DependencyCheck/pull/7114))
+ - Users can configure if packages-dev should be skipped
+- fix(regression): re-add h2 database driver name ([#7115](https://github.com/dependency-check/DependencyCheck/pull/7115))
+- fix(regression): Make the Downloader honour the proxy.nonproxyhosts ODC Setting ([#7077](https://github.com/dependency-check/DependencyCheck/pull/7077))
+- fix: do not set legacy proxy from maven or env ([#7072](https://github.com/dependency-check/DependencyCheck/pull/7072)) ([#7074](https://github.com/dependency-check/DependencyCheck/pull/7074))
+- docs: add missing documentation for the MS Build Analyzer ([#7113](https://github.com/dependency-check/DependencyCheck/pull/7113))
+- docs: Document the breaking change for Maven plugin as reporting plugin ([#7079](https://github.com/dependency-check/DependencyCheck/pull/7079))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/89?closed=1).
+
+## [Version 11.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v11.0.0) (2024-10-21)
+
+- **breaking change**: Switch from JMockit to Mockito & build target to Java 11 ([#6922](https://github.com/dependency-check/DependencyCheck/pull/6922))
+ - dependency-check now requires a minimum of Java 11.0 to run
+- **breaking change**: bump com.h2database:h2 from 2.1.214 to 2.3.232 ([#6132](https://github.com/dependency-check/DependencyCheck/pull/6132))
+ - H2 databases generated with an older version of ODC will not work with ODC 11.0.0; a new H2 db must be generated
+- **breaking change**: Maven plugin updated to Doxia 2.x reporting stack
+ - Users of the Maven plugin that configure it as a reporting plugin will need to use maven-site-plugin 3.20.0 or later ([#6959](https://github.com/dependency-check/DependencyCheck/pull/6959))
+- feat: Replace old Downloader by an Apache HTTPClient based downloader
+- feat: Use Apache HTTPClient for downloads of public resources ([#6949](https://github.com/dependency-check/DependencyCheck/pull/6949))
+- feat: Also make NodeAuditSearch usr our HTTPClient based connections
+- feat: Also make OSSIndexAnalyzer use our HTTPClient based connections
+- feat: Migrate CentralSearch to use Apache HTTP-client via Downloader
+- feat: Extend apache HTTP-client usage to EngineVersionCheck
+- feat: Remove the need to specify dbDriver for external databases using JDBCv4 ServiceLoader supporting JDBC drivers ([#6938](https://github.com/dependency-check/DependencyCheck/pull/6938))
+- fix: use latest generated suppressions ([#7064](https://github.com/dependency-check/DependencyCheck/pull/7064))
+- fix: Fixup parameter sequence for Dowloader credentials ([#7033](https://github.com/dependency-check/DependencyCheck/pull/7033))
+- fix: Fixup the missing addition of NVD API Datafeed credentials (if configured)
+- fix: Fixup broken proxy authentication in first attempt; extend to include KEV downloads
+- fix: store timestamps locally for local resources ([#6936](https://github.com/dependency-check/DependencyCheck/pull/6936))
+- build: Remove the animal-sniffer, propagate java version to plugin-archetype ([#6950](https://github.com/dependency-check/DependencyCheck/pull/6950))
+- build: Update Checkstyle configuration and Suppression DTD references ([#6951](https://github.com/dependency-check/DependencyCheck/pull/6951))
+- chore: Update test db schema ([#7036](https://github.com/dependency-check/DependencyCheck/pull/7036))
+- chore: remove old, unneeded database upgrade script
+- docs: reformat javadoc ([#7009](https://github.com/dependency-check/DependencyCheck/pull/7009))
+- docs: Fixup javadoc warnings ([#6995](https://github.com/dependency-check/DependencyCheck/pull/6995))
+- chore: Replace use of several deprecated methods/classes by their successors ([#6933](https://github.com/dependency-check/DependencyCheck/pull/6933))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/87?closed=1).
+
+## [Version 10.0.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v10.0.4) (2024-09-01)
+
+ - build(deps): exclude unused dependency ([#6916](https://github.com/dependency-check/DependencyCheck/pull/6916))
+ - fix: improve regex ([#6917](https://github.com/dependency-check/DependencyCheck/pull/6917))
+ - fix: correctly handle null values in cpeMatch ([#6915](https://github.com/dependency-check/DependencyCheck/pull/6915))
+ - fix(site): Update Fluido skin to resolve broken fork-me-on-github image ([#6914](https://github.com/dependency-check/DependencyCheck/pull/6914))
+ - fix: do not report over 100% download complete ([#6899](https://github.com/dependency-check/DependencyCheck/pull/6899))
+ - fix: Correct spelling of occurring in NvdApiDataSource.java ([#6883](https://github.com/dependency-check/DependencyCheck/pull/6883))
+ - fix: skip blank lines in requirements.txt ([#6867](https://github.com/dependency-check/DependencyCheck/pull/6867))
+ - fix: correct percentage calculation ([#6868](https://github.com/dependency-check/DependencyCheck/pull/6868))
+ - docs: remove old recommendation ([#6860](https://github.com/dependency-check/DependencyCheck/pull/6860))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/88?closed=1).
+
+## [Version 10.0.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v10.0.3) (2024-07-16)
+
+- feat: Enable configuration of a lower resultsPerPage on NVD API ([#6843](https://github.com/dependency-check/DependencyCheck/pull/6843))
+- build(deps): bump open-vulnerability-clients from 6.1.6 to 6.1.7 ([#6848](https://github.com/dependency-check/DependencyCheck/pull/6848))
+- build(deps): bump JamesIves/github-pages-deploy-action from 4.6.1 to 4.6.3 ([#6814](https://github.com/dependency-check/DependencyCheck/pull/6814))
+- build(deps): bump org.codehaus.mojo:versions-maven-plugin from 2.16.2 to 2.17.0 ([#6762](https://github.com/dependency-check/DependencyCheck/pull/6762))
+- build(deps): bump org.apache.maven.plugins:maven-checkstyle-plugin from 3.3.1 to 3.4.0 ([#6815](https://github.com/dependency-check/DependencyCheck/pull/6815))
+- build(deps): bump golang from 1.22.4-alpine to 1.22.5-alpine ([#6805](https://github.com/dependency-check/DependencyCheck/pull/6805))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/84?closed=1).
+
+## [Version 10.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v10.0.2) (2024-07-06)
+
+**Mandatory Upgrade** - due to older versions of dependency-check causing numerous, spurious requests that end in processing failures, this upgrade is mandatory so that the NVD can differentiate valid requests and block the old clients.
+
+- build(deps): bump open-vulnerability-clients ([#6810](https://github.com/dependency-check/DependencyCheck/pull/6810))
+- fix(db): [#6788](https://github.com/dependency-check/DependencyCheck/pull/6788) removing redundant db index "idxVulnerability" on "vulnerability.cve" ([#6807](https://github.com/dependency-check/DependencyCheck/pull/6807))
+- docs: Further improve formatting and docs of H2 database caching strats ([#6804](https://github.com/dependency-check/DependencyCheck/pull/6804))
+- fix: update_vulnerability in dbStatements_oracle.properties ([#6803](https://github.com/dependency-check/DependencyCheck/pull/6803))
+- fix: fix NPE ([#6778](https://github.com/dependency-check/DependencyCheck/pull/6778))
+- fix: add hint to resolve false negative ([#6802](https://github.com/dependency-check/DependencyCheck/pull/6802))
+- chore: update configure ([#6794](https://github.com/dependency-check/DependencyCheck/pull/6794))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/86?closed=1).
+
+## [Version 10.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v10.0.1) (2024-07-02)
+
+- build(deps): bump open-vulnerability-client ([#6772](https://github.com/dependency-check/DependencyCheck/pull/6772))
+- fix: remove debug logging ([#6770](https://github.com/dependency-check/DependencyCheck/pull/6770))
+- fix: postgresql column count error ([#6773](https://github.com/dependency-check/DependencyCheck/pull/6773))
+- fix: mssql column name and version ([#6761](https://github.com/dependency-check/DependencyCheck/pull/6761))
+- docs: update supported versions ([#6771](https://github.com/dependency-check/DependencyCheck/pull/6771))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/85?closed=1).
+
+## [Version 10.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v10.0.0) (2024-07-01)
+
+- **breaking change**: upgrade to dotnet 8.0 ([#6580](https://github.com/dependency-check/DependencyCheck/pull/6580))
+ - Users of the AssemblyAnalyzer must upgrade/utilize dotnet 8 to analyze assemblies
+- feat: fix the NVD API related errors by adding cvssV4 support ([#6756](https://github.com/dependency-check/DependencyCheck/pull/6756))
+ - **breaking changes**: anyone utilizing a centralized database will need to upgrade the schema; see changes in [PR #6756](https://github.com/dependency-check/DependencyCheck/pull/6756/files#diff-ca432c4b41d39caa84d140e06694b09c7e6394c8a2db72ba27516dc77ee3bd67)
+- fix: avoid escaping unnecessary chars in HTML report suppression regexes ([#6749](https://github.com/dependency-check/DependencyCheck/pull/6749))
+- fix: [#6688](https://github.com/dependency-check/DependencyCheck/pull/6688) Trim version number when parsing POM ([#6705](https://github.com/dependency-check/DependencyCheck/pull/6705))
+- fix: change request if lockfile is file v3 ([#6690](https://github.com/dependency-check/DependencyCheck/pull/6690))
+- fix: skip pyproject.toml unless it contains `tool.poetry` before ensuring lockfiles ([#6681](https://github.com/dependency-check/DependencyCheck/pull/6681))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/83?closed=1).
+
+## [Version 9.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.2.0) (2024-05-15)
+
+ - docs: update logo per intellj ([#6660](https://github.com/dependency-check/DependencyCheck/pull/6660))
+ - feat: Carthage analyzer ([#6614](https://github.com/dependency-check/DependencyCheck/pull/6614))
+ - fix: Ensure valid JSON output for gitlab report ([#6630](https://github.com/dependency-check/DependencyCheck/pull/6630))
+ - feat: Support Package.swift version 3 Specification ([#6578](https://github.com/dependency-check/DependencyCheck/pull/6578))
+ - chore: Update the packaged suppressions to include new hosted suppressions ([#6567](https://github.com/dependency-check/DependencyCheck/pull/6567))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/82?closed=1).
+
+## [Version 9.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.1.0) (2024-03-31)
+
+- feat: Add v2 support for maven_install.json ([#6528](https://github.com/dependency-check/DependencyCheck/pull/6528))
+- build(deps): bump open-vulnerability-client ([#6554](https://github.com/dependency-check/DependencyCheck/pull/6554))
+ - resolves update issues due to CVSS Metrics 4.0
+- build(deps): bump jackson.version from 2.16.0 to 2.16.1 ([#6353](https://github.com/dependency-check/DependencyCheck/pull/6353))
+- build(deps): bump org.jsoup:jsoup from 1.16.2 to 1.17.2 ([#6362](https://github.com/dependency-check/DependencyCheck/pull/6362))
+- build(deps): bump golang from 1.21.5-alpine to 1.22.1-alpine ([#6506](https://github.com/dependency-check/DependencyCheck/pull/6506))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/81?closed=1).
+
+## [Version 9.0.10](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.10) (2024-03-15)
+
+- fix: [#4321](https://github.com/dependency-check/DependencyCheck/pull/4321) Suppress redis server CVEs for client libraries ([#4321](https://github.com/dependency-check/DependencyCheck/pull/4321)) ([#6489](https://github.com/dependency-check/DependencyCheck/pull/6489))
+- fix: bump commons-compress from 1.25.0 to 1.26.0 to fix CVE-2024-25710 and CVE-2024-26308 ([#6492](https://github.com/dependency-check/DependencyCheck/pull/6492))
+- feat: Allow to pass NVD API key via environment variable ([#6454](https://github.com/dependency-check/DependencyCheck/pull/6454))
+- fix: issue 5452 - ConcurrentModificationException in NodePackageAnalyzer.processDependencies - adding synchronized block ([#6501](https://github.com/dependency-check/DependencyCheck/pull/6501))
+- docs: document the default data directory ([#6484](https://github.com/dependency-check/DependencyCheck/pull/6484))
+- fix: prevent NPE in bundler audit ([#6462](https://github.com/dependency-check/DependencyCheck/pull/6462))
+- fix: [#6441](https://github.com/dependency-check/DependencyCheck/pull/6441) Improve suppression rule to not restrict to a single version ([#6442](https://github.com/dependency-check/DependencyCheck/pull/6442))
-## [Version 8.2.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.2.1) (2023-03-23)
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/80?closed=1).
+
+## [Version 9.0.9](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.9) (2024-01-17)
+
+- fix: for [#6374](https://github.com/dependency-check/DependencyCheck/pull/6374) to delete non-empty directories ([#6375](https://github.com/dependency-check/DependencyCheck/pull/6375))
+- fix: NoSuchMethodError closeQuietly(java.io.Closeable[]) ([#6377](https://github.com/dependency-check/DependencyCheck/pull/6377))
+- chore: close stream to prevent possible resource leak ([#6382](https://github.com/dependency-check/DependencyCheck/pull/6382))
+- docs: Document default for CLI --data ([#6359](https://github.com/dependency-check/DependencyCheck/pull/6359))
+- docs: document gradle build ([#6371](https://github.com/dependency-check/DependencyCheck/pull/6371))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/79?closed=1).
+
+## [Version 9.0.8](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.8) (2024-01-06)
+
+- fix: favor stability over performance ([#6349](https://github.com/dependency-check/DependencyCheck/pull/6349))
+- chore: replace commons-io with core java calls ([#6343](https://github.com/dependency-check/DependencyCheck/pull/6343))
+- fix: improve error reporting for invalid H2 database ([#6339](https://github.com/dependency-check/DependencyCheck/pull/6339))
+- fix: rework fix for closing input streams on errors correctly ([#6338](https://github.com/dependency-check/DependencyCheck/pull/6338))
+- fix: reduce chance NVD API block updates due to rate limit ([#6333](https://github.com/dependency-check/DependencyCheck/pull/6333))
+- fix: ensure open handles will not leak on errors ([#6326](https://github.com/dependency-check/DependencyCheck/pull/6326))
+- fix: improve error reporting ([#6324](https://github.com/dependency-check/DependencyCheck/pull/6324))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/78?closed=1).
+
+## [Version 9.0.7](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.7) (2023-12-18)
+
+- docs: document insecure configuration for GHSA-qqhq-8r2c-c3f5 ([#6315](https://github.com/dependency-check/DependencyCheck/pull/6315))
+- fix: improve memory usage on NVD update ([#6321](https://github.com/dependency-check/DependencyCheck/pull/6321))
+- fix: skip pyproject.toml unless it contains `tool.poetry` ([#6316](https://github.com/dependency-check/DependencyCheck/pull/6316))
+- fix: resolve build error that may cause an issue on some JDK versions ([#6312](https://github.com/dependency-check/DependencyCheck/pull/6312))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/77?closed=1).
+
+## [Version 9.0.6](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.6) (2023-12-15)
+
+- build: bump open-vulnerability-clients@5.1.1 ([#6308](https://github.com/dependency-check/DependencyCheck/pull/6308))
+- fix: mask nvd.api.key in logs; see GHSA-qqhq-8r2c-c3f5 ([#6307](https://github.com/dependency-check/DependencyCheck/pull/6307))
+- fix: update java version check ([#6297](https://github.com/dependency-check/DependencyCheck/pull/6297))
+- fix: more efficient memory usage ([#6299](https://github.com/dependency-check/DependencyCheck/pull/6299))
+- fix: stream NVD data via Jackson to reduce memory footprint ([#6275](https://github.com/dependency-check/DependencyCheck/pull/6275))
+- docs: document github action caching ([#6301](https://github.com/dependency-check/DependencyCheck/pull/6301))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/76?closed=1).
+
+## [Version 9.0.5](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.5) (2023-12-13)
+
+- fix: make NVD API endpoint configurable ([#6287](https://github.com/dependency-check/DependencyCheck/pull/6287))
+- fix: synch last modified timestamp for NVD API ([#6281](https://github.com/dependency-check/DependencyCheck/pull/6281))
+- fix: read NVD cache meta files if cache.properties does not exist ([#6282](https://github.com/dependency-check/DependencyCheck/pull/6282))
+- fix: correct property for nonProxyHosts ([#6285](https://github.com/dependency-check/DependencyCheck/pull/6285))
+- fix: reduce apache http logging ([#6280](https://github.com/dependency-check/DependencyCheck/pull/6280))
+- fix: store last modified timestamp for RetireJS and the Hosted Suppression File in db ([#6271](https://github.com/dependency-check/DependencyCheck/pull/6271))
+- build: bump golang in the docker image ([#6274](https://github.com/dependency-check/DependencyCheck/pull/6274))
+- fix: use temporary files to reduce memory usage during the NVD Update ([#6270](https://github.com/dependency-check/DependencyCheck/pull/6270))
+- fix: use BIT for Oracle DB instead of Boolean when calling prepared statements ([#6264](https://github.com/dependency-check/DependencyCheck/pull/6264))
+- fix: showing all reference tags in reports ([#6259](https://github.com/dependency-check/DependencyCheck/pull/6259))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/75?closed=1).
+
+## [Version 9.0.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.4) (2023-12-08)
+
+- fix: utilize maven proxy if present ([#6255](https://github.com/dependency-check/DependencyCheck/pull/6255))
+- fix: allow api key in cli to be quoted ([#6253](https://github.com/dependency-check/DependencyCheck/pull/6253))
+- fix: use correct maven plugin reporting plugin ([#6244](https://github.com/dependency-check/DependencyCheck/pull/6244))
+- fix: correct trailing comma in JSON report ([#6245](https://github.com/dependency-check/DependencyCheck/pull/6245))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/74?closed=1).
+
+## [Version 9.0.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.3) (2023-12-06)
+
+- fix: use Java properties for proxy configuration ([#6238](https://github.com/dependency-check/DependencyCheck/pull/6238))
+- docs: update proxy configuration documentation ([#6237](https://github.com/dependency-check/DependencyCheck/pull/6237))
+- docs: add documentation on caching ([#6204](https://github.com/dependency-check/DependencyCheck/pull/6204))
+- docs: Clarify H2 database caching strategy ([#6220](https://github.com/dependency-check/DependencyCheck/pull/6220))
+- docs: Update list of supported report formats ([#6224](https://github.com/dependency-check/DependencyCheck/pull/6224))
+- docs: example 5 with new nvdDatafeedUrl parameter ([#6215](https://github.com/dependency-check/DependencyCheck/pull/6215))
+- fix: prevent NPEs ([#6232](https://github.com/dependency-check/DependencyCheck/pull/6232) and [#6206](https://github.com/dependency-check/DependencyCheck/pull/6206))
+- fix: check valid for hours for NVD API ([#6225](https://github.com/dependency-check/DependencyCheck/pull/6225))
+- fix: correct NVD cache last checked logic ([#6218](https://github.com/dependency-check/DependencyCheck/pull/6218))
+- fix: nvd datafeed should process current year ([#6213](https://github.com/dependency-check/DependencyCheck/pull/6213))
+- fix: correct references to cvssv2 and cvssv3 fields in json and xml reports ([#6212](https://github.com/dependency-check/DependencyCheck/pull/6212))
+- fix: correct name on reference links in report ([#6205](https://github.com/dependency-check/DependencyCheck/pull/6205))
+- fix: flaws int the gitlab report ([#6193](https://github.com/dependency-check/DependencyCheck/pull/6193))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/73?closed=1).
+
+## [Version 9.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.2) (2023-12-01)
+
+- fix: remove virtual match string on NVD API Request ([#6177](https://github.com/dependency-check/DependencyCheck/pull/6177))
+- fix: correct meta data in report after switching the NVD API ([#6154](https://github.com/dependency-check/DependencyCheck/pull/6154))
+- fix: retry HTTP connections to NVD on 502 and 504 errors ([#6151](https://github.com/dependency-check/DependencyCheck/pull/6151))
+- fix: Gitlab report format needs severity capitalized ([#6182](https://github.com/dependency-check/DependencyCheck/pull/6182))
+- fix: improve JDK update version parsing ([#6163](https://github.com/dependency-check/DependencyCheck/pull/6163))
+- fix: mute JCS logging (again) ([#6153](https://github.com/dependency-check/DependencyCheck/pull/6153))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/72?closed=1).
+
+## [Version 9.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.1) (2023-11-26)
+
+**breaking changes**: See the [upgrade notice](https://github.com/dependency-check/DependencyCheck#900-upgrade-notice)
+
+- fix: check java 8 update version; minimum JRE is 8 update 251 ([#6118](https://github.com/dependency-check/DependencyCheck/pull/6118))
+- fix: add retry for failed NVD API requests ([#6136](https://github.com/dependency-check/DependencyCheck/pull/6136))
+- docs: add default values to documentation for the NVD API Delay ([#6135](https://github.com/dependency-check/DependencyCheck/pull/6135))
+- chore: Revert "build(deps): bump com.h2database:h2 from 2.1.214 to 2.2.224" ([#6131](https://github.com/dependency-check/DependencyCheck/pull/6131))
+ - this is a **breaking change** for anyone that successfully created the H2 database with 9.0.0.
+- fix: mute jcs logging ([#6130](https://github.com/dependency-check/DependencyCheck/pull/6130))
+- docs: update NVD notice ([#6110](https://github.com/dependency-check/DependencyCheck/pull/6110))
+- fix: Use the correct key for NVD API-Key from Maven Settings serverId ([#6109](https://github.com/dependency-check/DependencyCheck/pull/6109))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/71?closed=1).
+
+## [Version 9.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v9.0.0) (2023-11-22)
+
+**breaking changes**: See the [upgrade notice](https://github.com/dependency-check/DependencyCheck#900-upgrade-notice)
+
+- feat: Utilize NVD API ([#5978](https://github.com/dependency-check/DependencyCheck/pull/5978))
+- feat: gitlab dependency scanner report format [#5919](https://github.com/dependency-check/DependencyCheck/pull/5919) ([#5920](https://github.com/dependency-check/DependencyCheck/pull/5920))
+- fix: Use ASCII apostrophe for console message ([#6076](https://github.com/dependency-check/DependencyCheck/pull/6076))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/68?closed=1).
+
+## [Version 8.4.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.4.3) (2023-11-15)
+
+- fix: bump jcs3 ([#6047](https://github.com/dependency-check/DependencyCheck/pull/6047))
+- docs: Corrected docs on hostedSuppressions ([#6035](https://github.com/dependency-check/DependencyCheck/pull/6035))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/70?closed=1).
+
+## [Version 8.4.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.4.2) (2023-10-22)
+
+- fix: correct log configuration in cli ([#6002](https://github.com/dependency-check/DependencyCheck/pull/6002))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/69?closed=1).
+
+## [Version 8.4.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.4.1) (2023-10-21)
+
+### Fixed
+
+- fix: upgrade to JCS3 ([#5114](https://github.com/dependency-check/DependencyCheck/pull/5114))
+- fix: Support ~= version specifier in requirements.txt and pipfile ([#5902](https://github.com/dependency-check/DependencyCheck/pull/5902))
+- fix: Version of dependency no longer ignored when CPE product has a 'java' suffix in a product name ([#5901](https://github.com/dependency-check/DependencyCheck/pull/5901))
+- fix: Do not filter out evidences added by hints ([#5900](https://github.com/dependency-check/DependencyCheck/pull/5900))
+- fix: fixes FP [#5925](https://github.com/dependency-check/DependencyCheck/pull/5925) ([#5927](https://github.com/dependency-check/DependencyCheck/pull/5927))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/67?closed=1).
+
+## [Version 8.4.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.4.0) (2023-08-19)
+
+### Added
+
+- feat: Add support for Nexus v3 to NexusAnalyzer ([#5849](https://github.com/dependency-check/DependencyCheck/pull/5849))
+
+### Fixed
+
+- fix: Hint Analyzer should run before VersionFilter Analyzer ([#5818](https://github.com/dependency-check/DependencyCheck/pull/5818))
+- chore: switch to sha1-pinning as suggested by Semgrep
+- fix: OSS Index Analyzer SocketTimeoutException exception handling based on warn only parameter ([#5845](https://github.com/dependency-check/DependencyCheck/pull/5845))
+- fix: use curl with -L to follow github redirect ([#5808](https://github.com/dependency-check/DependencyCheck/pull/5808))
+- fix: use curl with -L to follow github redirect
+- fix: [#5671](https://github.com/dependency-check/DependencyCheck/pull/5671) out of memory error ([#5789](https://github.com/dependency-check/DependencyCheck/pull/5789))
+- fix: [#5671](https://github.com/dependency-check/DependencyCheck/pull/5671) Exit method as soon as we detect a loop to prevent an infinite loop leading to an OutOfMemoryError
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/66?closed=1).
+
+## [Version 8.3.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.3.1) (2023-06-12)
+
+Re-release of 8.3.0 as 8.3.1.
+
+## [Version 8.3.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.3.0) (2023-06-12)
+
+### Added
+
+ - Add LibmanAnalyzer ([#5652](https://github.com/dependency-check/DependencyCheck/pull/5652))
+ - Update HTML report Dependencies header based on display settings ([#5619](https://github.com/dependency-check/DependencyCheck/pull/5619))
+ - Add link to suppressed vulnerabilities header in HTML report ([#5620](https://github.com/dependency-check/DependencyCheck/pull/5620))
+ - Enable local proxy configuration in maven plugin configuration ([#5696](https://github.com/dependency-check/DependencyCheck/pull/5696))
+
+### Fixed
+
+ - Fix npm alias present in requires of dependencies ([#5703](https://github.com/dependency-check/DependencyCheck/pull/5703))
+ - Make Central URL configurable via CLI ([#5667](https://github.com/dependency-check/DependencyCheck/pull/5667))
+ - Ensure support of CVSSv3.1 ([#5602](https://github.com/dependency-check/DependencyCheck/pull/5602))
+
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/65?closed=1).
+
+## [Version 8.2.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.2.1) (2023-03-23)
### Fixed
- - NullPointerException in MSBuildAnalyzer (#5589)
- - SQL Syntax for Oracle (#5590)
- - Use `https://` URLs in report templates (#5582)
+ - NullPointerException in MSBuildAnalyzer ([#5589](https://github.com/dependency-check/DependencyCheck/pull/5589))
+ - SQL Syntax for Oracle ([#5590](https://github.com/dependency-check/DependencyCheck/pull/5590))
+ - Use `https://` URLs in report templates ([#5582](https://github.com/dependency-check/DependencyCheck/pull/5582))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/64?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/64?closed=1).
-## [Version 8.2.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.2.0) (2023-03-22)
+## [Version 8.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.2.0) (2023-03-22)
### Added
- - Support msbuild Directory.build.props (#5475)
+ - Support msbuild Directory.build.props ([#5475](https://github.com/dependency-check/DependencyCheck/pull/5475))
- better display of NPM audit references
- Add CVSS V3 results from NPM Audit results
### Fixed
- - Fix several issues on NPM Audit reporting (#5546)
- - Case issue in SQL (#5557)
+ - Fix several issues on NPM Audit reporting ([#5546](https://github.com/dependency-check/DependencyCheck/pull/5546))
+ - Case issue in SQL ([#5557](https://github.com/dependency-check/DependencyCheck/pull/5557))
- Fix CWE(s) extraction for NPM Audit advisories
- Use the stable github_advisory_id instead of the now unstable id in NPM audit results
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/63?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/63?closed=1).
-## [Version 8.1.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.1.2) (2023-02-28)
+## [Version 8.1.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.1.2) (2023-02-28)
### Fixed
- - Fix `NullPointerException` in the Jar Analyzer introduced in 8.1.1 (#5512)
+ - Fix `NullPointerException` in the Jar Analyzer introduced in 8.1.1 ([#5512](https://github.com/dependency-check/DependencyCheck/pull/5512))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/62?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/62?closed=1).
-## [Version 8.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.1.1) (2023-02-27)
+## [Version 8.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.1.1) (2023-02-27)
### Fixed
- - allow hosted suppressions file to be disabled (#5509)
- - Several FPs not suitable for our automation (#5504)
- - Fix incorrect defaults for nexus and central-analyzer in gradle plugin documentation (#5503)
- - Erroneous error-log for deprecated CLI flag usage when using properyfile based disablement of Node Audit Analyzer (#5487)
- - Prefer pom.properties G/A/V over pom.xml G/A/V to resolve GAV interpolation issues (#5473)
- - Node package dependencies ending up as related dependency of the wrong version of the package (#5479)
- - do not throw error if pyproject.toml is in node_modules (#5470)
+ - allow hosted suppressions file to be disabled ([#5509](https://github.com/dependency-check/DependencyCheck/pull/5509))
+ - Several FPs not suitable for our automation ([#5504](https://github.com/dependency-check/DependencyCheck/pull/5504))
+ - Fix incorrect defaults for nexus and central-analyzer in gradle plugin documentation ([#5503](https://github.com/dependency-check/DependencyCheck/pull/5503))
+ - Erroneous error-log for deprecated CLI flag usage when using properyfile based disablement of Node Audit Analyzer ([#5487](https://github.com/dependency-check/DependencyCheck/pull/5487))
+ - Prefer pom.properties G/A/V over pom.xml G/A/V to resolve GAV interpolation issues ([#5473](https://github.com/dependency-check/DependencyCheck/pull/5473))
+ - Node package dependencies ending up as related dependency of the wrong version of the package ([#5479](https://github.com/dependency-check/DependencyCheck/pull/5479))
+ - do not throw error if pyproject.toml is in node_modules ([#5470](https://github.com/dependency-check/DependencyCheck/pull/5470))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/61?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/61?closed=1).
-## [Version 8.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.1.0) (2023-01-26)
+## [Version 8.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.1.0) (2023-01-26)
### Added
-- `Pipefile.lock` files are now supported ([#5404](https://github.com/jeremylong/DependencyCheck/pull/5404)).
-- Python projects with only a `pyproject.toml` but no lock file or requirements will report an error as ODC is unable to analyze the project ([#5409](https://github.com/jeremylong/DependencyCheck/pull/5409)).
+- `Pipefile.lock` files are now supported ([#5404](https://github.com/dependency-check/DependencyCheck/pull/5404)).
+- Python projects with only a `pyproject.toml` but no lock file or requirements will report an error as ODC is unable to analyze the project ([#5409](https://github.com/dependency-check/DependencyCheck/pull/5409)).
### Fixed
-- Some maven projects caused false positives due to bad string interpolation ([#5421](https://github.com/jeremylong/DependencyCheck/pull/5421)).
-- Error message from Assembly Analyzer has been updated to emphasize dotnet 6 is required for analysis ([#5408](https://github.com/jeremylong/DependencyCheck/pull/5408)).
-- Correct issue where database defrag occurs even when no updates were performed ([#5441](https://github.com/jeremylong/DependencyCheck/pull/5441)).
+- Some maven projects caused false positives due to bad string interpolation ([#5421](https://github.com/dependency-check/DependencyCheck/pull/5421)).
+- Error message from Assembly Analyzer has been updated to emphasize dotnet 6 is required for analysis ([#5408](https://github.com/dependency-check/DependencyCheck/pull/5408)).
+- Correct issue where database defrag occurs even when no updates were performed ([#5441](https://github.com/dependency-check/DependencyCheck/pull/5441)).
- Fixed several False Positives and one False Negative.
- Fixed the `format` configuration more flexible in the gradle plugin ([dependency-check-gradle/#324](https://github.com/dependency-check/dependency-check-gradle/pull/324)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/60?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/60?closed=1).
-## [Version 8.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.0.2) (2023-01-26)
+## [Version 8.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.0.2) (2023-01-26)
### Fixed
-- Resolved bug causing an issue with some Maven Extensions ([#5366](https://github.com/jeremylong/DependencyCheck/pull/5366)).
-- ArchiveAnalyzer will now correctly throw an exception if it cannot open an Archive ([#5371](https://github.com/jeremylong/DependencyCheck/pull/5371)).
-- Updated CSV report so that it no longer has a duplicate `description` column ([#5364](https://github.com/jeremylong/DependencyCheck/pull/5364)).
-- Moved several logging statements to trace which should drastically reduce the log size ([#5350](https://github.com/jeremylong/DependencyCheck/pull/5350)).
-- Fixed bug with RetireJS' `--retirejsFilterNonVulnerable` and `--retirejsFilter` when used with the CLI ([#5351](https://github.com/jeremylong/DependencyCheck/pull/5351)).
-- Fixed the `sarif` report format and added validation ([#5345](https://github.com/jeremylong/DependencyCheck/pull/5345) and ([#5363](https://github.com/jeremylong/DependencyCheck/pull/5363))
+- Resolved bug causing an issue with some Maven Extensions ([#5366](https://github.com/dependency-check/DependencyCheck/pull/5366)).
+- ArchiveAnalyzer will now correctly throw an exception if it cannot open an Archive ([#5371](https://github.com/dependency-check/DependencyCheck/pull/5371)).
+- Updated CSV report so that it no longer has a duplicate `description` column ([#5364](https://github.com/dependency-check/DependencyCheck/pull/5364)).
+- Moved several logging statements to trace which should drastically reduce the log size ([#5350](https://github.com/dependency-check/DependencyCheck/pull/5350)).
+- Fixed bug with RetireJS' `--retirejsFilterNonVulnerable` and `--retirejsFilter` when used with the CLI ([#5351](https://github.com/dependency-check/DependencyCheck/pull/5351)).
+- Fixed the `sarif` report format and added validation ([#5345](https://github.com/dependency-check/DependencyCheck/pull/5345) and ([#5363](https://github.com/dependency-check/DependencyCheck/pull/5363))
- Fixed `MalformedPackageException` in the gradle plugin ([dependency-check-gradle/#320](https://github.com/dependency-check/dependency-check-gradle/pull/320)).
- Fixed `MissingMethodException` in the gradle plugin ([dependency-check-gradle/#316](https://github.com/dependency-check/dependency-check-gradle/pull/316)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/59?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/59?closed=1).
-## [Version 8.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.0.1) (2023-01-18)
+## [Version 8.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.0.1) (2023-01-18)
### Fixed
- Fixed Stack Overflow Exception in the gradle plugin ([dependency-check-gradle/#308](https://github.com/dependency-check/dependency-check-gradle/pull/308)).
- Fixed No Signature of Method Exception in the gradle plugin ([dependency-check-gradle/#305](https://github.com/dependency-check/dependency-check-gradle/pull/305)).
-- Updated DB initialization scripts for externally hosted DBs ([#5314](https://github.com/jeremylong/DependencyCheck/pull/5314) and [#5317](https://github.com/jeremylong/DependencyCheck/pull/5317)).
+- Updated DB initialization scripts for externally hosted DBs ([#5314](https://github.com/dependency-check/DependencyCheck/pull/5314) and [#5317](https://github.com/dependency-check/DependencyCheck/pull/5317)).
- Postgres users will need to use the updated init script and 8.0.1.
-- Resolved NPE in the NodePackageAnalyzer ([#5339](https://github.com/jeremylong/DependencyCheck/pull/5339)).
+- Resolved NPE in the NodePackageAnalyzer ([#5339](https://github.com/dependency-check/DependencyCheck/pull/5339)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/58?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/58?closed=1).
-## [Version 8.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v8.0.0) (2023-01-15)
+## [Version 8.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v8.0.0) (2023-01-15)
### Added
-- Utilize the hosted suppression file to allow for faster remediation of reported False Positives ([#4723](https://github.com/jeremylong/DependencyCheck/issues/4723)).
-- Include the [CISA Known Exploited Vulnerability Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) ([#4878](https://github.com/jeremylong/DependencyCheck/issues/4878)).
-- The `gradle` and `maven` plugins now have the capability to scan the build plugins ([#4035](https://github.com/jeremylong/DependencyCheck/issues/4035)).
-- The `gradle` and `maven` plugins, for transitive dependencies, will report the root dependency in the project that included the transitive dependency ([#5001](https://github.com/jeremylong/DependencyCheck/pull/5001)).
-- Added `properties.security-severity` to SARIF report for better integration with GitHub Security Code scanning ([#5277](https://github.com/jeremylong/DependencyCheck/pull/5227)).
-- Allow for HTTP auth settings for Retire JS respository ([#5209](https://github.com/jeremylong/DependencyCheck/pull/5209)).
-- New schema for the XML report was added to support some of the above additions ([#5296](https://github.com/jeremylong/DependencyCheck/pull/5296)).
+- Utilize the hosted suppression file to allow for faster remediation of reported False Positives ([#4723](https://github.com/dependency-check/DependencyCheck/issues/4723)).
+- Include the [CISA Known Exploited Vulnerability Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) ([#4878](https://github.com/dependency-check/DependencyCheck/issues/4878)).
+- The `gradle` and `maven` plugins now have the capability to scan the build plugins ([#4035](https://github.com/dependency-check/DependencyCheck/issues/4035)).
+- The `gradle` and `maven` plugins, for transitive dependencies, will report the root dependency in the project that included the transitive dependency ([#5001](https://github.com/dependency-check/DependencyCheck/pull/5001)).
+- Added `properties.security-severity` to SARIF report for better integration with GitHub Security Code scanning ([#5277](https://github.com/dependency-check/DependencyCheck/pull/5227)).
+- Allow for HTTP auth settings for Retire JS repository ([#5209](https://github.com/dependency-check/DependencyCheck/pull/5209)).
+- New schema for the XML report was added to support some of the above additions ([#5296](https://github.com/dependency-check/DependencyCheck/pull/5296)).
- Added missing gradle option to only warn on remote errors from the OSS Index Analyzer ([gradle #303](https://github.com/dependency-check/dependency-check-gradle/pull/303)).
### Changed
- **Breaking:** the database schema updated - if using an external database the update scripts must be run!
-- The [exit codes](https://tldp.org/LDP/abs/html/exit-status.html) from the CLI have been changed to be in the range from 0-255 ([#4511](https://github.com/jeremylong/DependencyCheck/pull/4511).
-- The OSS Index Analyzer will automatically disable itself if a transport error occurs - preventing copious errors from being reported ([#5300](https://github.com/jeremylong/DependencyCheck/pull/5300])).
+- The [exit codes](https://tldp.org/LDP/abs/html/exit-status.html) from the CLI have been changed to be in the range from 0-255 ([#4511](https://github.com/dependency-check/DependencyCheck/pull/4511).
+- The OSS Index Analyzer will automatically disable itself if a transport error occurs - preventing copious errors from being reported ([#5300](https://github.com/dependency-check/DependencyCheck/pull/5300])).
### Fixed
-- Added an additional check for rejected CVEs to reduce FP ([#5268](https://github.com/jeremylong/DependencyCheck/pull/5268).
-- Corrected the analysis of `node_modules` to prevent NPEs ([#5266](https://github.com/jeremylong/DependencyCheck/pull/5266)).
-- Fixed error when scanning node packages with local dependencies ([#5235](https://github.com/jeremylong/DependencyCheck/pull/5235)).
-- Fixed NPE in the MSBuild Analyzer ([#5293](https://github.com/jeremylong/DependencyCheck/pull/5293)).
+- Added an additional check for rejected CVEs to reduce FP ([#5268](https://github.com/dependency-check/DependencyCheck/pull/5268).
+- Corrected the analysis of `node_modules` to prevent NPEs ([#5266](https://github.com/dependency-check/DependencyCheck/pull/5266)).
+- Fixed error when scanning node packages with local dependencies ([#5235](https://github.com/dependency-check/DependencyCheck/pull/5235)).
+- Fixed NPE in the MSBuild Analyzer ([#5293](https://github.com/dependency-check/DependencyCheck/pull/5293)).
- Several False Positives have been resolved.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/46?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/46?closed=1).
-## [Version 7.4.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.4.4) (2023-01-06)
+## [Version 7.4.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.4.4) (2023-01-06)
### Fixed
-- Resolved issue processing NVD CVE data due to column width (#5229)
+- Resolved issue processing NVD CVE data due to column width ([#5229](https://github.com/dependency-check/DependencyCheck/pull/5229))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/56?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/56?closed=1).
-## [Version 7.4.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.4.3) (2022-12-29)
+## [Version 7.4.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.4.3) (2022-12-29)
### Fixed
-- Fixed NPE when analyzing version ranges in NPM (#5158 & #5190)
-- Resolved several FP (#5191)
+- Fixed NPE when analyzing version ranges in NPM ([#5158](https://github.com/dependency-check/DependencyCheck/pull/5158) & [#5190](https://github.com/dependency-check/DependencyCheck/pull/5190))
+- Resolved several FP ([#5191](https://github.com/dependency-check/DependencyCheck/pull/5191))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/55?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/55?closed=1).
-## [Version 7.4.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.4.2) (2022-12-28)
+## [Version 7.4.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.4.2) (2022-12-28)
### Fixed
-- Fixes maven 3.1 compatibility issue (#5152)
-- Fixed issue with invalid `node_module` paths in some scans (#5135)
-- Fixed missing option to disable the Poetry Analyzer in the CLI (#5160)
-- Fixed missing option to configure the OSS Index URL in the CLI (#5180)
-- Fixed NPE when analyzing version ranges in NPM (#5158)
+- Fixes maven 3.1 compatibility issue ([#5152](https://github.com/dependency-check/DependencyCheck/pull/5152))
+- Fixed issue with invalid `node_module` paths in some scans ([#5135](https://github.com/dependency-check/DependencyCheck/pull/5135))
+- Fixed missing option to disable the Poetry Analyzer in the CLI ([#5160](https://github.com/dependency-check/DependencyCheck/pull/5160))
+- Fixed missing option to configure the OSS Index URL in the CLI ([#5180](https://github.com/dependency-check/DependencyCheck/pull/5180))
+- Fixed NPE when analyzing version ranges in NPM ([#5158](https://github.com/dependency-check/DependencyCheck/pull/5158))
- Fixed issue with non-proxy host in the gradle plugin (https://github.com/dependency-check/dependency-check-gradle/pull/298)
- Resolved several FP
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/54?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/54?closed=1).
-## [Version 7.4.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.4.1) (2022-12-09)
+## [Version 7.4.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.4.1) (2022-12-09)
### Fixed
-- Fixed bug when setting the proxy port in gradle (#5123)
-- Fixed issue with invalid `node_module` paths in some scans (#5127)
+- Fixed bug when setting the proxy port in gradle ([#5123](https://github.com/dependency-check/DependencyCheck/pull/5123))
+- Fixed issue with invalid `node_module` paths in some scans ([#5127](https://github.com/dependency-check/DependencyCheck/pull/5127))
- Resolved several FP
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/53?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/53?closed=1).
-## [Version 7.4.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.4.0) (2022-12-04)
+## [Version 7.4.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.4.0) (2022-12-04)
### Added
-- Add support for npm package lock v2 and v3 (#5078)
-- Added experimental support for Python Poetry (#5025)
-- Added a vanilla HTML report for use in Jenkins (#5053)
+- Add support for npm package lock v2 and v3 ([#5078](https://github.com/dependency-check/DependencyCheck/pull/5078))
+- Added experimental support for Python Poetry ([#5025](https://github.com/dependency-check/DependencyCheck/pull/5025))
+- Added a vanilla HTML report for use in Jenkins ([#5053](https://github.com/dependency-check/DependencyCheck/pull/5053))
### Changed
- Renamed `RELEASE_NOTES.md` to `CHANGELOG.md` to be more conventional
-- Optimized checksum calculation to improve performance (#5112)
-- Added support for scanning .NET assemblies when only the dotnet runtime is installed (#5087)
+- Optimized checksum calculation to improve performance ([#5112](https://github.com/dependency-check/DependencyCheck/pull/5112))
+- Added support for scanning .NET assemblies when only the dotnet runtime is installed ([#5087](https://github.com/dependency-check/DependencyCheck/pull/5087))
- Bumped several dependencies
### Fixed
-- Fixed bug when setting the proxy port (#5076)
+- Fixed bug when setting the proxy port ([#5076](https://github.com/dependency-check/DependencyCheck/pull/5076))
- Resolved several FP and FN
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/52?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/52?closed=1).
-## [Version 7.3.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.3.2) (2022-11-18)
+## [Version 7.3.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.3.2) (2022-11-18)
### Changed
- Automated release of 7.3.1 failed and only published to Central; 7.3.2 is a re-release of 7.3.1.
- Resolved several false positives and false negatives.
-- Use Jackson Afterburner if still on Java 8 (#4966).
-- Exclude `node_modules` from the Maven plugin's scan path (#4974).
+- Use Jackson Afterburner if still on Java 8 ([#4966](https://github.com/dependency-check/DependencyCheck/pull/4966)).
+- Exclude `node_modules` from the Maven plugin's scan path ([#4974](https://github.com/dependency-check/DependencyCheck/pull/4974)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/51?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/51?closed=1).
-## [Version 7.3.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.3.1) (2022-11-16)
+## [Version 7.3.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.3.1) (2022-11-16)
### Changed
- Resolved several false positives and false negatives.
-- Use Jackson Afterburner if still on Java 8 (#4966).
-- Exclude `node_modules` from the Maven plugin's scan path (#4974).
+- Use Jackson Afterburner if still on Java 8 ([#4966](https://github.com/dependency-check/DependencyCheck/pull/4966)).
+- Exclude `node_modules` from the Maven plugin's scan path ([#4974](https://github.com/dependency-check/DependencyCheck/pull/4974)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/51?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/51?closed=1).
-## [Version 7.3.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.3.0) (2022-10-19)
+## [Version 7.3.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.3.0) (2022-10-19)
### Added
-- Added an experimental Dart analyzer (#4869).
+- Added an experimental Dart analyzer ([#4869](https://github.com/dependency-check/DependencyCheck/pull/4869)).
### Changed
-- Migrated from Jackson Afterburner to Blackbird (#4905).
+- Migrated from Jackson Afterburner to Blackbird ([#4905](https://github.com/dependency-check/DependencyCheck/pull/4905)).
### Fixed
-- Fixed issue with the Maven plugin that caused concurrent modification exceptions (#4935).
+- Fixed issue with the Maven plugin that caused concurrent modification exceptions ([#4935](https://github.com/dependency-check/DependencyCheck/pull/4935)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/50?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/50?closed=1).
-## [Version 7.2.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.2.1) (2022-09-20)
+## [Version 7.2.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.2.1) (2022-09-20)
### Fixed
-- Fixed logging issue (#4846).
+- Fixed logging issue ([#4846](https://github.com/dependency-check/DependencyCheck/pull/4846)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/49?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/49?closed=1).
-## [Version 7.2.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.2.0) (2022-09-14)
+## [Version 7.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.2.0) (2022-09-14)
### Changed
-- Add support for Bazel's pinned `maven_install.json` (#4772).
-- Fixed bug preventing the use of custom report templates (#4800).
+- Add support for Bazel's pinned `maven_install.json` ([#4772](https://github.com/dependency-check/DependencyCheck/pull/4772)).
+- Fixed bug preventing the use of custom report templates ([#4800](https://github.com/dependency-check/DependencyCheck/pull/4800)).
- Updated several dependencies including upgrades for dependencies with CVEs.
- Several bug fixes made and suppression rules were added.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/48?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/48?closed=1).
-## [Version 7.1.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.1.2) (2022-08-20)
+## [Version 7.1.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.1.2) (2022-08-20)
### Changed
-- The maven plugin now includes pnpm and yarn lock files in the scan by default (#4753).
-- If a suppression rule is no longer used a log entry will be written (#4685).
+- The maven plugin now includes pnpm and yarn lock files in the scan by default ([#4753](https://github.com/dependency-check/DependencyCheck/pull/4753)).
+- If a suppression rule is no longer used a log entry will be written ([#4685](https://github.com/dependency-check/DependencyCheck/pull/4685)).
- Several bug fixes made and suppression rules added.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/47?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/47?closed=1).
-## [Version 7.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.1.1) (2022-06-12)
+## [Version 7.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.1.1) (2022-06-12)
### Fixed
- Minor bug fixes.
- Resolved several false positives.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/45?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/45?closed=1).
-## [Version 7.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.1.0) (2022-04-23)
+## [Version 7.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.1.0) (2022-04-23)
### Changed
-- Improved sorting in the HTML report ([see #4112](https://github.com/jeremylong/DependencyCheck/issues/4112)).
-- Improved support for Swift ([see #4265](https://github.com/jeremylong/DependencyCheck/pull/4265)).
+- Improved sorting in the HTML report ([see #4112](https://github.com/dependency-check/DependencyCheck/issues/4112)).
+- Improved support for Swift ([see #4265](https://github.com/dependency-check/DependencyCheck/pull/4265)).
- Resolved several false positives.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/45?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/45?closed=1).
-## [Version 7.0.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.0.4) (2022-03-30)
+## [Version 7.0.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.0.4) (2022-03-30)
### Changed
-- Update to `jackson-databind` (see #4285).
+- Update to `jackson-databind` (see [#4285](https://github.com/dependency-check/DependencyCheck/pull/4285)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/43?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/43?closed=1).
-## [Version 7.0.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.0.3) (2022-03-29)
+## [Version 7.0.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.0.3) (2022-03-29)
### Changed
-- Update to `jackson-databind` (see #4285).
+- Update to `jackson-databind` (see [#4285](https://github.com/dependency-check/DependencyCheck/pull/4285)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/42?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/42?closed=1).
-## [Version 7.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.0.2) (2022-03-28)
+## [Version 7.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.0.2) (2022-03-28)
### Changed
- General project maintenance, bug fixes, and false positive and false negative reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/41?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/41?closed=1).
-## [Version 7.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.0.1) (2022-03-23)
+## [Version 7.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.0.1) (2022-03-23)
### Changed
- General project maintenance, bug fixes, and false positive reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/40?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/40?closed=1).
-## [Version 7.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v7.0.0) (2022-02-28)
+## [Version 7.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v7.0.0) (2022-02-28)
### Changed
- **Breaking:** The H2 database version has been upgraded.
- if you use the `dataDirectory` option you will need to run a purge after upgrading.
- **Breaking:** Upgraded to dotnet core 6.0. If analyzing dotnet assemblies the system will need to have the dotnet core 6.0.x runtime available.
-- The Sarif report format has been fixed and can now be imported into GitHub if desired (See #3993).
+- The Sarif report format has been fixed and can now be imported into GitHub if desired (See [#3993](https://github.com/dependency-check/DependencyCheck/pull/3993)).
- Introduced IssueOps for False Positive reports to assist the team in evaluating FP reports.
- - [Create New FP Report Issue](https://github.com/jeremylong/DependencyCheck/issues/new?assignees=&labels=FP+Report&template=false-positive-report.yml&title=%5BFP%5D%3A+).
+ - [Create New FP Report Issue](https://github.com/dependency-check/DependencyCheck/issues/new?assignees=&labels=FP+Report&template=false-positive-report.yml&title=%5BFP%5D%3A+).
- When analyzing Java projects ODC now includes data from the developers section.
- This will likely cause false positives on things like Apache James, please report the FP and we will fix these quickly.
- General project maintenance, bug fixes, and false positive reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/28?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/28?closed=1).
-## [Version 6.5.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.5.3) (2022-01-12)
+## [Version 6.5.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.5.3) (2022-01-12)
### Changed
-- Performance improvements for some Maven projects (see #3923 and #3931).
-- Fixed bug in npm version handling introduced in 6.5.2 (see #3956).
-- Improved the node package analyzer to correctly report the origin of a dependency (see #3970).
+- Performance improvements for some Maven projects (see [#3923](https://github.com/dependency-check/DependencyCheck/pull/3923) and [#3931](https://github.com/dependency-check/DependencyCheck/pull/3931)).
+- Fixed bug in npm version handling introduced in 6.5.2 (see [#3956](https://github.com/dependency-check/DependencyCheck/pull/3956)).
+- Improved the node package analyzer to correctly report the origin of a dependency (see [#3970](https://github.com/dependency-check/DependencyCheck/pull/3970)).
- General code maintenance and false positive reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/39?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/39?closed=1).
-## [Version 6.5.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.5.2) (2022-01-03)
+## [Version 6.5.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.5.2) (2022-01-03)
### Changed
-- Fixed false positives around log4j-api and Log4j-web (#3910 & #3937).
-- Bug fix when processing NPM lock files (#3893).
-- Added missing `pnpm` argmument to the CLI (#3916).
+- Fixed false positives around log4j-api and Log4j-web ([#3910](https://github.com/dependency-check/DependencyCheck/pull/3910) & [#3937](https://github.com/dependency-check/DependencyCheck/pull/3937)).
+- Bug fix when processing NPM lock files ([#3893](https://github.com/dependency-check/DependencyCheck/pull/3893)).
+- Added missing `pnpm` argmument to the CLI ([#3916](https://github.com/dependency-check/DependencyCheck/pull/3916)).
- General code maintenance and false positive reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/38?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/38?closed=1).
-## [Version 6.5.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.5.1) (2021-12-17)
+## [Version 6.5.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.5.1) (2021-12-17)
### Changed
-- Updated the dependency-check-maven plugin to correctly support SNAPSHOT version when a classifier is specified (#3787).
-- Improved the analysis of Swift package manager (package.resolved - see #3813).
+- Updated the dependency-check-maven plugin to correctly support SNAPSHOT version when a classifier is specified ([#3787](https://github.com/dependency-check/DependencyCheck/pull/3787)).
+- Improved the analysis of Swift package manager (package.resolved - see [#3813](https://github.com/dependency-check/DependencyCheck/pull/3813)).
- General code maintenance and false positive reductions.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/37?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/37?closed=1).
-## [Version 6.5.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.5.0) (2021-11-08)
+## [Version 6.5.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.5.0) (2021-11-08)
### Changed
- Updated build configuration to create [reproducible builds](https://reproducible-builds.org/).
- Updated automated release process to work with branch protection.
- Resolved several false positives in the Java ecosystem.
-- Enabled the Swift Resolved analyzer per #3735
-- Improved iOS support per #3168 and #3765
+- Enabled the Swift Resolved analyzer per [#3735](https://github.com/dependency-check/DependencyCheck/pull/3735)
+- Improved iOS support per [#3168](https://github.com/dependency-check/DependencyCheck/pull/3168) and [#3765](https://github.com/dependency-check/DependencyCheck/pull/3765)
- Added the a new pnpm Analyzer
- Fixed issue with some npm and yarn analysis failing due to large audit output
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/36?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/36?closed=1).
-## [Version 6.4.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.4.1) (2021-10-11)
+## [Version 6.4.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.4.1) (2021-10-11)
### Added
-- Added download attempts with increasing wait time for `CVE meta` files from the NVD to prevent rate limiting issues (see [#3725](https://github.com/jeremylong/DependencyCheck/pull/3725)).
+- Added download attempts with increasing wait time for `CVE meta` files from the NVD to prevent rate limiting issues (see [#3725](https://github.com/dependency-check/DependencyCheck/pull/3725)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/35?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/35?closed=1).
-## [Version 6.4.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.4.0) (2021-10-11)
+## [Version 6.4.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.4.0) (2021-10-11)
### Changed
-- Increased timeout between downloads from the NVD to prevent rate limiting issues (see [#3722](https://github.com/jeremylong/DependencyCheck/pull/3722)).
+- Increased timeout between downloads from the NVD to prevent rate limiting issues (see [#3722](https://github.com/dependency-check/DependencyCheck/pull/3722)).
- `cveStartYear` is now configurable and can be set to any year from 2002 to present.
- - `cveWaitTime` is a new configuration option to define how many milliseconds to wait between NVD downloads; default is 4000 ms (see [#3690](https://github.com/jeremylong/DependencyCheck/pull/3690)).
+ - `cveWaitTime` is a new configuration option to define how many milliseconds to wait between NVD downloads; default is 4000 ms (see [#3690](https://github.com/dependency-check/DependencyCheck/pull/3690)).
- The NVD CVE data files are now being cached for up to 4 hours in case a download fails, re-running ODC will use the cached version.
-- Fixed NPE in the ODC maven plugin (see [#3702](https://github.com/jeremylong/DependencyCheck/pull/3702).
+- Fixed NPE in the ODC maven plugin (see [#3702](https://github.com/dependency-check/DependencyCheck/pull/3702).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/34?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/34?closed=1).
-## [Version 6.3.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.3.2) (2021-09-29)
+## [Version 6.3.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.3.2) (2021-09-29)
### Changed
-- Reduced chance of rate limiting when download files from NVD (see [#2670](https://github.com/jeremylong/DependencyCheck/pull/3670)).
-- Fixed bug causing some transitive dependencies being skipped in the odc-maven-plugin (see [#3627](https://github.com/jeremylong/DependencyCheck/pull/3627)).
+- Reduced chance of rate limiting when download files from NVD (see [#2670](https://github.com/dependency-check/DependencyCheck/pull/3670)).
+- Fixed bug causing some transitive dependencies being skipped in the odc-maven-plugin (see [#3627](https://github.com/dependency-check/DependencyCheck/pull/3627)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/33?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/33?closed=1).
-## [Version 6.3.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.3.1) (2021-09-01)
+## [Version 6.3.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.3.1) (2021-09-01)
### Fixed
-- Fixed [ConcurrentModificationException](https://github.com/jeremylong/DependencyCheck/issues/3618)
+- Fixed [ConcurrentModificationException](https://github.com/dependency-check/DependencyCheck/issues/3618)
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/32?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/32?closed=1).
-## [Version 6.3.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.3.0) (2021-08-31)
+## [Version 6.3.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.3.0) (2021-08-31)
### Changed
- Many updates were made to improve performance on large scans, reduce false positives, and other bug fixes.
-- Increased the width of four columns in the database; if you use a an external database you should also update the width (see [upgrade_5.1.sql](https://github.com/jeremylong/DependencyCheck/blob/main/core/src/main/resources/data/upgrade_5.1.sql)).
+- Increased the width of four columns in the database; if you use a an external database you should also update the width (see [upgrade_5.1.sql](https://github.com/dependency-check/DependencyCheck/blob/main/core/src/main/resources/data/upgrade_5.1.sql)).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/31?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/31?closed=1).
-## [Version 6.2.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.2.2) (2021-06-10)
+## [Version 6.2.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.2.2) (2021-06-10)
### Fixed
-- Resolved issue with database connections introduced in 6.2.0 (see https://github.com/jeremylong/DependencyCheck/issues/3432).
+- Resolved issue with database connections introduced in 6.2.0 (see https://github.com/dependency-check/DependencyCheck/issues/3432).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/30?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/30?closed=1).
-## [Version 6.2.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.2.1) (2021-06-08)
+## [Version 6.2.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.2.1) (2021-06-08)
### Fixed
-- Resolved issue with database connections introduced in 6.2.0 (see https://github.com/jeremylong/DependencyCheck/issues/3416).
+- Resolved issue with database connections introduced in 6.2.0 (see https://github.com/dependency-check/DependencyCheck/issues/3416).
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/29?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/29?closed=1).
-## [Version 6.2.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.2.0) (2021-05-29)
+## [Version 6.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.2.0) (2021-05-29)
### Changed
-- Added an experimental Perl CPAN analyzer [#3378](https://github.com/jeremylong/DependencyCheck/pull/3378)
+- Added an experimental Perl CPAN analyzer [#3378](https://github.com/dependency-check/DependencyCheck/pull/3378)
- Note that the full DSL of the CPAN is not yet supported so any required dependency is analyzed (i.e. there is no way to exclude development requirements)
-- Improved database performance [#3206](https://github.com/jeremylong/DependencyCheck/pull/3206)
-- The archive analyzer now extracts files from RPM archives [#3226](https://github.com/jeremylong/DependencyCheck/pull/3226)
-- Ensure ordered output in reports [#3243](https://github.com/jeremylong/DependencyCheck/pull/3343)
+- Improved database performance [#3206](https://github.com/dependency-check/DependencyCheck/pull/3206)
+- The archive analyzer now extracts files from RPM archives [#3226](https://github.com/dependency-check/DependencyCheck/pull/3226)
+- Ensure ordered output in reports [#3243](https://github.com/dependency-check/DependencyCheck/pull/3343)
- Several minor bug fixes and updates to reduce false positives
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/27?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/27?closed=1).
-## [Version 6.1.6](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.6) (2021-04-29)
+## [Version 6.1.6](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.6) (2021-04-29)
### Fixed
-- Resolved issue with Sarif report (#3243)
-- Resolved issue with Ruby Bundle Audit (#3256)
+- Resolved issue with Sarif report ([#3243](https://github.com/dependency-check/DependencyCheck/pull/3243))
+- Resolved issue with Ruby Bundle Audit ([#3256](https://github.com/dependency-check/DependencyCheck/pull/3256))
- Several minor bug fixes and updates to reduce false positives
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/26?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/26?closed=1).
-## [Version 6.1.5](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.5) (2021-03-31)
+## [Version 6.1.5](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.5) (2021-03-31)
### Fixed
-- Fixed a second NPE introduced in 6.1.3 (see #3246)
+- Fixed a second NPE introduced in 6.1.3 (see [#3246](https://github.com/dependency-check/DependencyCheck/pull/3246))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/25?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/25?closed=1).
-## [Version 6.1.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.4) (2021-03-30)
+## [Version 6.1.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.4) (2021-03-30)
### Changed
-- Fixed an NPE introduced in 6.1.3 (see #3212)
+- Fixed an NPE introduced in 6.1.3 (see [#3212](https://github.com/dependency-check/DependencyCheck/pull/3212))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/24?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/24?closed=1).
-## [Version 6.1.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.3) (2021-03-22)
+## [Version 6.1.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.3) (2021-03-22)
### Changed
-- Modified the new CPE matching strategy to be more performant (#3207)
-- Upgraded a vulnerable dependency (velocity-engine-core/CVE-2020-13936) (#3205)
+- Modified the new CPE matching strategy to be more performant ([#3207](https://github.com/dependency-check/DependencyCheck/pull/3207))
+- Upgraded a vulnerable dependency (velocity-engine-core/CVE-2020-13936) ([#3205](https://github.com/dependency-check/DependencyCheck/pull/3205))
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/23?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/23?closed=1).
-## [Version 6.1.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.2) (2021-03-08)
+## [Version 6.1.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.2) (2021-03-08)
### Changed
@@ -486,79 +980,79 @@ See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/
- CLI and Ant task will no longer be published to bintray.
- Several minor bug fixes.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/22?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/22?closed=1).
-## [Version 6.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.1) (2021-02-13)
+## [Version 6.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.1) (2021-02-13)
### Changed
- Added missing configuration options for yarn and msbuild.
- Several bug fixes.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/21?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/21?closed=1).
-## [Version 6.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.1.0) (2021-01-27)
+## [Version 6.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.1.0) (2021-01-27)
### Changed
-- Added SARIF file format per [#3081](https://github.com/jeremylong/DependencyCheck/issues/3081).
-- Added support for Yarn per [#3063](https://github.com/jeremylong/DependencyCheck/pull/3063).
+- Added SARIF file format per [#3081](https://github.com/dependency-check/DependencyCheck/issues/3081).
+- Added support for Yarn per [#3063](https://github.com/dependency-check/DependencyCheck/pull/3063).
- False positive reduction and minor bug fixes.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/20?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/20?closed=1).
-## [Version 6.0.5](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.5) (2021-01-07)
+## [Version 6.0.5](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.5) (2021-01-07)
### Changed
-- Added missing command line arguments per #3028 and #3035.
+- Added missing command line arguments per [#3028](https://github.com/dependency-check/DependencyCheck/pull/3028) and [#3035](https://github.com/dependency-check/DependencyCheck/pull/3035).
- False positive reduction and minor bug fixes.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/19?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/19?closed=1).
-## [Version 6.0.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.4) (2020-12-31)
+## [Version 6.0.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.4) (2020-12-31)
### Changed
- Minor bug fixes and reduction of false positives.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/18?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/18?closed=1).
-## [Version 6.0.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.3) (2020-11-03)
+## [Version 6.0.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.3) (2020-11-03)
### Changed
-- Added a bash command completion script (see #2916); to add completion to your shell
+- Added a bash command completion script (see [#2916](https://github.com/dependency-check/DependencyCheck/pull/2916)); to add completion to your shell
`completion-for-dependency-check.sh` can be found in the bin directory of the CLI:
```bash
$ source completion-for-dependency-check.sh
```
-- An experimental PIP File Analyzer was added (see #2877).
-- Analysis of Node JS produced several false positives (see #2796); the analysis has
+- An experimental PIP File Analyzer was added (see [#2877](https://github.com/dependency-check/DependencyCheck/pull/2877)).
+- Analysis of Node JS produced several false positives (see [#2796](https://github.com/dependency-check/DependencyCheck/pull/2796)); the analysis has
been updated to reduce the number of false positives.
- If analyzing Node JS projects it is highly recommended to disable the Node JS Analyzer
and solely rely on the Node Audit Analyzer. There are plans to rework Node JS analysis
in a future release.
-- Support for external Oracle databases has been add for the 6.x releases (see #2899)
+- Support for external Oracle databases has been add for the 6.x releases (see [#2899](https://github.com/dependency-check/DependencyCheck/pull/2899))
- Resolved several reported false positives.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/17?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/17?closed=1).
-## [Version 6.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.2) (2020-09-27)
+## [Version 6.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.2) (2020-09-27)
### Changed
-- The project is migrating from hosting the release archives on Bintray and moving them to Github under the assets for each [release](https://github.com/jeremylong/DependencyCheck/releases)
+- The project is migrating from hosting the release archives on Bintray and moving them to Github under the assets for each [release](https://github.com/dependency-check/DependencyCheck/releases)
- **Please update any automation you have to point to the new location.**
-- Npm Audit Analyzer now correctly skips dev dependencies (`--nodeAuditSkipDevDependencies`); see #2482.
-- GoLang Analyzer now scans transitive dependencies; see #2680.
+- Npm Audit Analyzer now correctly skips dev dependencies (`--nodeAuditSkipDevDependencies`); see [#2482](https://github.com/dependency-check/DependencyCheck/pull/2482).
+- GoLang Analyzer now scans transitive dependencies; see [#2680](https://github.com/dependency-check/DependencyCheck/pull/2680).
- Several bug fixes found in 6.0.1.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/16?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/16?closed=1).
-## [Version 6.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.1) (2020-09-13)
+## [Version 6.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.1) (2020-09-13)
### Changed
@@ -567,85 +1061,85 @@ See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/
- Fixed the database path for the Ant and Gradle plugins.
- Added locking around the RetireJS updates to resolve read/write conflicts in CI environments.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/15?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/15?closed=1).
-## [Version 6.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v6.0.0) (2020-09-07)
+## [Version 6.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v6.0.0) (2020-09-07)
### Changed
- Updated database schema; this is a *breaking change* and anyone using an external database or those whom
specify the data directory will need recreate the database (including users of the docker image). The schema
changes were made to:
- - Improve the CVSS data, when available, per #2547
+ - Improve the CVSS data, when available, per [#2547](https://github.com/dependency-check/DependencyCheck/pull/2547)
- Improve the way that ecosystems are determined
- Improve the update performance of external databases
-- Users with an **external Oracle** database will not be able to upgrade as https://github.com/jeremylong/DependencyCheck/issues/2755
+- Users with an **external Oracle** database will not be able to upgrade as https://github.com/dependency-check/DependencyCheck/issues/2755
has not been resolved - as such, version 6.0.0 does not support Oracle.
- Users mirroring the NVD - ODC 6.0.0 requires the use of the version 1.1 data feeds
- please ensure you are using 1.1 not the 1.0 data feed.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/14?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/14?closed=1).
-## [Version 5.3.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.3.2) (2020-03-26)
+## [Version 5.3.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.3.2) (2020-03-26)
### Changed
- Several bug fixes
-- Full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/13?closed=1).
+- Full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/13?closed=1).
-## [Version 5.3.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.3.1) (2020-03-10)
+## [Version 5.3.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.3.1) (2020-03-10)
### Changed
-- Added an experimental PE Analyzer that reads the PE headers of DLL and EXE files; see [#2448](https://github.com/jeremylong/DependencyCheck/pull/2448) and [#2446](https://github.com/jeremylong/DependencyCheck/pull/2446).
+- Added an experimental PE Analyzer that reads the PE headers of DLL and EXE files; see [#2448](https://github.com/dependency-check/DependencyCheck/pull/2448) and [#2446](https://github.com/dependency-check/DependencyCheck/pull/2446).
- Lots of bug fixes and updates to false positives and false negatives
- You may see a large one time performance hit when updating the database after updating to 5.3.1
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/12?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/12?closed=1).
-## [Version 5.3.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.3.0) (2020-01-15)
+## [Version 5.3.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.3.0) (2020-01-15)
### Changed
-- Updated the JSON report to include a new field for unscored vulnerabilities (see #2392).
-- Updated the XML report to include a new attribute to flag unscored vulnerabilities (see #2392)
- - see https://github.com/jeremylong/DependencyCheck/blob/main/core/src/main/resources/schema/dependency-check.2.3.xsd
-- Added an experimental analyzer that will lookup Node libraries in the NVD data feeds (see #1249)
+- Updated the JSON report to include a new field for unscored vulnerabilities (see [#2392](https://github.com/dependency-check/DependencyCheck/pull/2392)).
+- Updated the XML report to include a new attribute to flag unscored vulnerabilities (see [#2392](https://github.com/dependency-check/DependencyCheck/pull/2392))
+ - see https://github.com/dependency-check//DependencyCheck/blob/main/core/src/main/resources/schema/dependency-check.2.3.xsd
+- Added an experimental analyzer that will lookup Node libraries in the NVD data feeds (see [#1249](https://github.com/dependency-check/DependencyCheck/pull/1249))
- `NpmCPEAnalyzer`, experimental analyzers must be enabled, controlled via property `analyzer.npm.cpe.enabled` which will be exposed as a configuration option in the next release.
-See the full listing of [changes](https://github.com/jeremylong/DependencyCheck/milestone/11?closed=1).
+See the full listing of [changes](https://github.com/dependency-check/DependencyCheck/milestone/11?closed=1).
-## [Version 5.2.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.2.4) (2019-11-12)
+## [Version 5.2.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.2.4) (2019-11-12)
### Changed
- Reverted a in 5.2.3 that caused the dependency-check.sh script to fail on some systems (including the docker image).
- Fixed issue with pretty printing the XML report.
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.4).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.4).
-## [Version 5.2.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.2.3) (2019-11-11)
+## [Version 5.2.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.2.3) (2019-11-11)
### Changed
-- Updated to use the NVD JSON 1.1 schema (see [#2273](https://github.com/jeremylong/DependencyCheck/issues/2273)).
+- Updated to use the NVD JSON 1.1 schema (see [#2273](https://github.com/dependency-check/DependencyCheck/issues/2273)).
- This update is 100% backward compatible with the 1.0 schema if you are mirroring the 1.0 JSON files.
- Added `nonProxyHosts` to the CLI and gradle plugin.
- False positive corrections.
- General code cleanup/bug fix.
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.3) and [pull requests](https://github.com/jeremylong/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.2.3+is%3Aclosed+).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.3) and [pull requests](https://github.com/dependency-check/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.2.3+is%3Aclosed+).
-## [Version 5.2.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.2.2) (2019-09-22)
+## [Version 5.2.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.2.2) (2019-09-22)
### Changed
- False positive corrections
- General code cleanup/bug fix
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.2).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.2).
-## [Version 5.2.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.2.1) (2019-08-04)
+## [Version 5.2.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.2.1) (2019-08-04)
### Changed
@@ -654,49 +1148,49 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
- False positive corrections
- General code cleanup/bug fix
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.1).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.1).
-## [Version 5.2.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.2.0) (2019-07-21)
+## [Version 5.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.2.0) (2019-07-21)
### Changed
- Resolved formatting issues within the CSV report
- False positive corrections
- Renamed three properties within the `dependencycheck.properties`; there is no impact unless you are using a properties file in your build to control the CLI.
-- Added support for rbenv for Bundle Audit Analysis (see https://github.com/jeremylong/DependencyCheck/issues/2060).
+- Added support for rbenv for Bundle Audit Analysis (see https://github.com/dependency-check/DependencyCheck/issues/2060).
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.0).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue++is%3Aclosed+milestone%3A5.2.0).
-## [Version 5.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.1.1) (2019-07-15)
+## [Version 5.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.1.1) (2019-07-15)
### Changed
- False positive corrections
- General code cleanup
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?q=is%3Aissue+milestone%3A5.1.1+is%3Aclosed).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?q=is%3Aissue+milestone%3A5.1.1+is%3Aclosed).
-## [Version 5.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.1.0) (2019-06-28)
+## [Version 5.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.1.0) (2019-06-28)
### Changed
- Added two experimental analyzers to support Golang.
- Updated the suppression schema to support suppressing OSS Index, RetireJS, NSP vulnerabilities, etc.
- The HTML report now uses the 1.3 suppression schema by default to generate suppression rules.
- - See the updated examples on https://jeremylong.github.io/DependencyCheck/general/suppression.html.
+ - See the updated examples on https://dependency-check.github.io/DependencyCheck/general/suppression.html.
- Added optional configuration to add credentials to the OSS Index analysis.
- Resolved issues when Oracle or MySQL were used as a centralized database in 5.0.0.
-See the full listing of [resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+milestone%3A5.1.0) and [pull requests](https://github.com/jeremylong/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.1.0).
+See the full listing of [resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+milestone%3A5.1.0) and [pull requests](https://github.com/dependency-check/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.1.0).
-## [Version 5.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.0.0) (2019-06-09)
+## [Version 5.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.0.0) (2019-06-09)
### Changed
- Add caching of OSS-Index, Central Analyzer, and Node Audit analysis results.
-- General bug fixes identified in the previous milestone releases; see [5.0.0 resolved issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+milestone%3A5.0.0+) and [pull requests](https://github.com/jeremylong/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.0.0).
+- General bug fixes identified in the previous milestone releases; see [5.0.0 resolved issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+milestone%3A5.0.0+) and [pull requests](https://github.com/dependency-check/DependencyCheck/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.0.0).
-## [Version 5.0.0-M3](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.0.0-M3) (2019-05-06)
+## [Version 5.0.0-M3](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.0.0-M3) (2019-05-06)
### Changed
@@ -704,7 +1198,7 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
### Changed
-- Several bug fixes and minor enhancements have been made; see the related [issues](https://github.com/jeremylong/DependencyCheck/issues?utf8=%E2%9C%93&q=+milestone%3A5.0.0-M3+) and [pull requests](https://github.com/jeremylong/DependencyCheck/pulls?utf8=%E2%9C%93&q=+milestone%3A5.0.0-M3+).
+- Several bug fixes and minor enhancements have been made; see the related [issues](https://github.com/dependency-check/DependencyCheck/issues?utf8=%E2%9C%93&q=+milestone%3A5.0.0-M3+) and [pull requests](https://github.com/dependency-check/DependencyCheck/pulls?utf8=%E2%9C%93&q=+milestone%3A5.0.0-M3+).
- Multiple report formats can be specified; if you wanted just two of the reports you no longer need to use ALL.
- A new JUNIT formatted report has been added; this provides a different way to integrate with Jenkins builds; the following example creates a JUNIT report with failures for any CVE with a CVSS score greater than or equal to 7.0 the Jenkins pipeline script shows how to publish the report:
@@ -747,14 +1241,14 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
}
```
-## [Version 5.0.0-M2](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.0.0-M2) (2019-03-11)
+## [Version 5.0.0-M2](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.0.0-M2) (2019-03-11)
### Changed
- **Breaking:** [dotnet core](https://dotnet.microsoft.com/download/dotnet-core/2.2) must be installed to analyze .NET assemblies.
- **Breaking:** The retire.js analyzer is no longer considered experimental and is enabled by default.
-## [Version 5.0.0-M1](https://github.com/jeremylong/DependencyCheck/releases/tag/v5.0.0-M1) (2019-02-17)
+## [Version 5.0.0-M1](https://github.com/dependency-check/DependencyCheck/releases/tag/v5.0.0-M1) (2019-02-17)
### Changed
@@ -771,7 +1265,7 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
from one technology stack do not appear on a dependency built using a completely different stack (e.g.
NodeJS vulnerabilities should not show up on a .NET DLL).
-## [Version 4.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v4.0.2) (2019-01-01)
+## [Version 4.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v4.0.2) (2019-01-01)
### Added
@@ -780,91 +1274,91 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
To enable this feature set `false`.
- If using a local Nexus server (v2 or v3 pro) it is now possible to provide authentication credentials.
- Previous versions only worked with anonymous/unauthenticated access.
- - See [issue #977](https://github.com/jeremylong/DependencyCheck/issues/977)
+ - See [issue #977](https://github.com/dependency-check/DependencyCheck/issues/977)
### Fixed
- Updated fix for transitive dependencies with known vulnerabilities (guava and commons-collections)
so that the upgrade occurs correctly in other integrations that utilize core; see
- [issue #1562](https://github.com/jeremylong/DependencyCheck/issues/1561#issuecomment-450112110).
+ [issue #1562](https://github.com/dependency-check/DependencyCheck/issues/1561#issuecomment-450112110).
- Resolved several false positives
-## [Version 4.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v4.0.1) (2018-12-17)
+## [Version 4.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v4.0.1) (2018-12-17)
### Fixed
-- Fixed issue with false positives due to Lucene upgrade. See [#1531](https://github.com/jeremylong/DependencyCheck/issues/1580).
+- Fixed issue with false positives due to Lucene upgrade. See [#1531](https://github.com/dependency-check/DependencyCheck/issues/1580).
- Resolved several false positives.
- Resolved typo in documentation.
-## [Version 4.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v4.0.0) (2018-11-21)
+## [Version 4.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v4.0.0) (2018-11-21)
### Changed
-- OWASP dependency-check no longer supports running in JRE/JDK 7; JRE/JDK 8 or higher is required run dependency-check. See [#1531](https://github.com/jeremylong/DependencyCheck/issues/1531).
+- OWASP dependency-check no longer supports running in JRE/JDK 7; JRE/JDK 8 or higher is required run dependency-check. See [#1531](https://github.com/dependency-check/DependencyCheck/issues/1531).
### Fixed
-- Upgraded dependencies to resolve published vulnerabilities (Guava and Lucene); See [#1561](https://github.com/jeremylong/DependencyCheck/issues/1561).
+- Upgraded dependencies to resolve published vulnerabilities (Guava and Lucene); See [#1561](https://github.com/dependency-check/DependencyCheck/issues/1561).
-## [Version 3.3.4](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.3.4) (2018-10-28)
+## [Version 3.3.4](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.3.4) (2018-10-28)
### Fixed
- Resolved bug with parsing license information during analysis of Node.js modules.
-## [Version 3.3.3](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.3.3) (2018-10-27)
+## [Version 3.3.3](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.3.3) (2018-10-27)
### Changed
-- Migrated the NSP Analyzer to use the Node Audit APIs instead; see [#1366](https://github.com/jeremylong/DependencyCheck/issues/1366).
+- Migrated the NSP Analyzer to use the Node Audit APIs instead; see [#1366](https://github.com/dependency-check/DependencyCheck/issues/1366).
- Note that the analyzer and configuration was changed to NodeAuditAnalyzer.
- Configurations for the NSP analyzer have been deprecated and will control the NodeAuditAnalyzer if used; note that the NSP configuration options will be removed in a future release.
-- The [dependency-check-gradle](https://github.com/jeremylong/dependency-check-gradle) plugin was updated to include a default scan set
+- The [dependency-check-gradle](https://github.com/dependency-check/Dependency-check-gradle) plugin was updated to include a default scan set
of ['src/main/resources','src/main/webapp'] and any dependencies contained in these directories will be analyzed. The purpose of this
enhancement is to enable the RetireJS Analyzer to scan JavaScript files that may be included.
### Fixed
-- Resolved **false negative** on Bouncy Castle JAR files; see [#1500](https://github.com/jeremylong/DependencyCheck/issues/1500).
-- Resolved **false negatives** that may occur when using the Maven plugin if transitive dependencies of a library in use and is also declared as a primary dependency in a scope that is not used; see [#1512](https://github.com/jeremylong/DependencyCheck/issues/1512).
-- Resolved **false negatives** on libraries that contain an update version or timestamp tacked onto the end of the version number; see [#1537](https://github.com/jeremylong/DependencyCheck/issues/1537).
+- Resolved **false negative** on Bouncy Castle JAR files; see [#1500](https://github.com/dependency-check/DependencyCheck/issues/1500).
+- Resolved **false negatives** that may occur when using the Maven plugin if transitive dependencies of a library in use and is also declared as a primary dependency in a scope that is not used; see [#1512](https://github.com/dependency-check/DependencyCheck/issues/1512).
+- Resolved **false negatives** on libraries that contain an update version or timestamp tacked onto the end of the version number; see [#1537](https://github.com/dependency-check/DependencyCheck/issues/1537).
- The resolution for these false negatives may generate some false positives, please continue to report false positives and the engine can continue to be tuned.
-- Fixed bug preventing multiple proxies from being defined for Maven; see [#831](https://github.com/jeremylong/DependencyCheck/issues/831).
-- Updated the suppress buttons in the HTML report to generate the XML using the latest suppression schema; see [#489](https://github.com/jeremylong/DependencyCheck/issues/1489).
-- Added the `--artifactoryUrl` argument to the CLI - this was missed when the Artifactory Analyzer was previously added; see [#1492](https://github.com/jeremylong/DependencyCheck/issues/1492).
-- Updated test cases so that they no longer fail behind a proxy; see [#1493](https://github.com/jeremylong/DependencyCheck/issues/1493).
-- Resolved several reported false positives; see [#1504](https://github.com/jeremylong/DependencyCheck/issues/1504), [#1513](https://github.com/jeremylong/DependencyCheck/issues/1513),
- [#1515](https://github.com/jeremylong/DependencyCheck/issues/1515), [#1529](https://github.com/jeremylong/DependencyCheck/issues/1529), [#1535](https://github.com/jeremylong/DependencyCheck/issues/1535),
- and [#1437](https://github.com/jeremylong/DependencyCheck/issues/1437).
-- Fixed copy/paste error in JavaDoc; see [#1509](https://github.com/jeremylong/DependencyCheck/issues/1509).
+- Fixed bug preventing multiple proxies from being defined for Maven; see [#831](https://github.com/dependency-check/DependencyCheck/issues/831).
+- Updated the suppress buttons in the HTML report to generate the XML using the latest suppression schema; see [#489](https://github.com/dependency-check/DependencyCheck/issues/1489).
+- Added the `--artifactoryUrl` argument to the CLI - this was missed when the Artifactory Analyzer was previously added; see [#1492](https://github.com/dependency-check/DependencyCheck/issues/1492).
+- Updated test cases so that they no longer fail behind a proxy; see [#1493](https://github.com/dependency-check/DependencyCheck/issues/1493).
+- Resolved several reported false positives; see [#1504](https://github.com/dependency-check/DependencyCheck/issues/1504), [#1513](https://github.com/dependency-check/DependencyCheck/issues/1513),
+ [#1515](https://github.com/dependency-check/DependencyCheck/issues/1515), [#1529](https://github.com/dependency-check/DependencyCheck/issues/1529), [#1535](https://github.com/dependency-check/DependencyCheck/issues/1535),
+ and [#1437](https://github.com/dependency-check/DependencyCheck/issues/1437).
+- Fixed copy/paste error in JavaDoc; see [#1509](https://github.com/dependency-check/DependencyCheck/issues/1509).
-## [Version 3.3.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.3.2) (2018-09-14)
+## [Version 3.3.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.3.2) (2018-09-14)
### Fixed
-- Gradle plugin was updated to include backward compatibility with gradle < v4.0; see [#95](https://github.com/jeremylong/dependency-check-gradle/issues/95).
-- Gradle plugin improved handling of Android project; see [#94](https://github.com/jeremylong/dependency-check-gradle/issues/94)
-- CLI used an incorrect key for RetireJS causing the analyzer to not be loaded in some cases; see [#1440](https://github.com/jeremylong/DependencyCheck/issues/1440).
-- Resolved failure in the `CentralAnalyzer` when the pom.xml is not available in Central; see [#1439](https://github.com/jeremylong/DependencyCheck/issues/1439).
-- Resolved exception when JAR files contain invalid pom.xml files outside of META-INF; see [#1438](https://github.com/jeremylong/DependencyCheck/issues/1438).
+- Gradle plugin was updated to include backward compatibility with gradle < v4.0; see [#95](https://github.com/dependency-check/Dependency-check-gradle/issues/95).
+- Gradle plugin improved handling of Android project; see [#94](https://github.com/dependency-check/Dependency-check-gradle/issues/94)
+- CLI used an incorrect key for RetireJS causing the analyzer to not be loaded in some cases; see [#1440](https://github.com/dependency-check/DependencyCheck/issues/1440).
+- Resolved failure in the `CentralAnalyzer` when the pom.xml is not available in Central; see [#1439](https://github.com/dependency-check/DependencyCheck/issues/1439).
+- Resolved exception when JAR files contain invalid pom.xml files outside of META-INF; see [#1438](https://github.com/dependency-check/DependencyCheck/issues/1438).
- Resolved several reported false positives.
-## [Version 3.3.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.3.1) (2018-08-06)
+## [Version 3.3.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.3.1) (2018-08-06)
### Changed
-- An Nuget Packages.config Analyzer was added; see [#1412](https://github.com/jeremylong/DependencyCheck/issues/1412).
+- An Nuget Packages.config Analyzer was added; see [#1412](https://github.com/dependency-check/DependencyCheck/issues/1412).
### Fixed
-- Fixed error handling with regard to invalid manifest files contained within JAR files; see [#1024](https://github.com/jeremylong/DependencyCheck/issues/1024).
-- Fixed parsing of pom.xml files, in some cases a SAX Exception would be thrown; see [#1400](https://github.com/jeremylong/DependencyCheck/issues/1400).
-- Fixed bug that caused dependency-check to crash if the temporary directory and data directory were on different drives; see [#1394](https://github.com/jeremylong/DependencyCheck/issues/1394).
-- Fixed bug in dependency-check-maven where an aggregate analysis did not scan all files defined in the ScanSet; see [#1421](https://github.com/jeremylong/DependencyCheck/issues/1421).
-- Fixed NPE in dependency-check-gradle that occurred when artifacts where included using `implementation files("./lib/some.jar")`; see [#91](https://github.com/jeremylong/dependency-check-gradle/issues/91).
+- Fixed error handling with regard to invalid manifest files contained within JAR files; see [#1024](https://github.com/dependency-check/DependencyCheck/issues/1024).
+- Fixed parsing of pom.xml files, in some cases a SAX Exception would be thrown; see [#1400](https://github.com/dependency-check/DependencyCheck/issues/1400).
+- Fixed bug that caused dependency-check to crash if the temporary directory and data directory were on different drives; see [#1394](https://github.com/dependency-check/DependencyCheck/issues/1394).
+- Fixed bug in dependency-check-maven where an aggregate analysis did not scan all files defined in the ScanSet; see [#1421](https://github.com/dependency-check/DependencyCheck/issues/1421).
+- Fixed NPE in dependency-check-gradle that occurred when artifacts where included using `implementation files("./lib/some.jar")`; see [#91](https://github.com/dependency-check/Dependency-check-gradle/issues/91).
-## [Version 3.3.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.3.0) (2018-07-22)
+## [Version 3.3.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.3.0) (2018-07-22)
### Changed
@@ -873,52 +1367,52 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
- An experimental Retire JS analyzer has been added to analyze client side JavaScript.
- This utilizes information from the RetireJS repo on github. If you have a proxy that prevents access you will either need to have access granted to https://raw.githubusercontent.com/Retirejs/retire.js/main/repository/jsrepository.json or host the file internally, update the environment variable `analyzer.retirejs.repo.js.ur`, and periodically update the file.
- This analyzer is considered experimental, but the team expects this to be promoted quickly.
-- NuGet dependencies contained in MSBuild files are now included in the scan. See [Issue #1131](https://github.com/jeremylong/DependencyCheck/issues/1131) for more details.
-- Cocoapod's Podfile.lock is now analyzed when present. See [PR #1324](https://github.com/jeremylong/DependencyCheck/pull/1324) for more information.
+- NuGet dependencies contained in MSBuild files are now included in the scan. See [Issue #1131](https://github.com/dependency-check/DependencyCheck/issues/1131) for more details.
+- Cocoapod's Podfile.lock is now analyzed when present. See [PR #1324](https://github.com/dependency-check/DependencyCheck/pull/1324) for more information.
### Fixed
-- The dependency-check-gradle plugin can now analyze multi-project android builds. See [PR #09](https://github.com/jeremylong/dependency-check-gradle/pull/90) for more information.
-- In some cases extremely large project may cause dependency-check to fail due to the analysis time. Previously, the analysis was capped at 10 minutes; the timeout was increased to 20 minutes and made configurable if this continues to be an issue for some users. See [issue #936](https://github.com/jeremylong/DependencyCheck/issues/936) for more information.
+- The dependency-check-gradle plugin can now analyze multi-project android builds. See [PR #09](https://github.com/dependency-check/Dependency-check-gradle/pull/90) for more information.
+- In some cases extremely large project may cause dependency-check to fail due to the analysis time. Previously, the analysis was capped at 10 minutes; the timeout was increased to 20 minutes and made configurable if this continues to be an issue for some users. See [issue #936](https://github.com/dependency-check/DependencyCheck/issues/936) for more information.
- Some pom.xml files could not be analyzed because they contained a doctype definition. The parser has been enhanced to strip the doctype definitions.
- Fixed issue where, in some cases, temporary files were not correctly cleaned up in Jenkins and gradle builds.
-- Fixed issue where, in some cases, files were retrieved from Maven Central using HTTP instead of HTTPS. See [issue #1325](https://github.com/jeremylong/DependencyCheck/issues/1325) for more information.
+- Fixed issue where, in some cases, files were retrieved from Maven Central using HTTP instead of HTTPS. See [issue #1325](https://github.com/dependency-check/DependencyCheck/issues/1325) for more information.
- Additionally, a retry count was added when attempting to download pom.xml files during analysis.
-- Fixed issue where nodejs dependencies were not correctly analyzed. See [issue #1355](https://github.com/jeremylong/DependencyCheck/issues/1355) for more information.
+- Fixed issue where nodejs dependencies were not correctly analyzed. See [issue #1355](https://github.com/dependency-check/DependencyCheck/issues/1355) for more information.
- Fixed issue where the CWE was not written to the CSV report.
- In addition, general bug fixes, code cleanup, and false positive/negatives updates were made.
-## [Version 3.2.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.2.1) (2018-05-28)
+## [Version 3.2.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.2.1) (2018-05-28)
### Fixed
-- In some cases when using the Maven or Gradle plugins the GAV coordinates were not being added as an Identifier causing suppression rules to fail; this has been resolved (#1298)
-- Documentation Update (SCM links in the maven site were broken) (#1297)
-- False positive reduction (#1290)
-- Enhanced logging output for TLS failures to better assist with debugging (#1269)
-- Resolved a Null Pointer Exception (#1296)
+- In some cases when using the Maven or Gradle plugins the GAV coordinates were not being added as an Identifier causing suppression rules to fail; this has been resolved ([#1298](https://github.com/dependency-check/DependencyCheck/pull/1298))
+- Documentation Update (SCM links in the maven site were broken) ([#1297](https://github.com/dependency-check/DependencyCheck/pull/1297))
+- False positive reduction ([#1290](https://github.com/dependency-check/DependencyCheck/pull/1290))
+- Enhanced logging output for TLS failures to better assist with debugging ([#1269](https://github.com/dependency-check/DependencyCheck/pull/1269))
+- Resolved a Null Pointer Exception ([#1296](https://github.com/dependency-check/DependencyCheck/pull/1296))
-## [Version 3.2.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.2.0) (2018-05-21)
+## [Version 3.2.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.2.0) (2018-05-21)
### Changed
- Excess white space has been removed from the XML and HTML reports; the JSON report is still pretty printed (a future release will convert this to a configurable option)
- Better error reporting
- Changed to use commons-text instead of commons-lang3 as a portion of commons-lang3 was moved to commonts-text
-- Added more flexible suppression rules with the introduction of the `until` attribute (see [#1145](https://github.com/jeremylong/DependencyCheck/issues/1145) and [dependency-suppression.1.2.xsd](https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.2.xsd)
+- Added more flexible suppression rules with the introduction of the `until` attribute (see [#1145](https://github.com/dependency-check/DependencyCheck/issues/1145) and [dependency-suppression.1.2.xsd](https://dependency-check.github.io/DependencyCheck/dependency-suppression.1.2.xsd)
### Fixed
- Unsafe unzip operations ([zip slip](https://github.com/snyk/zip-slip-vulnerability)), as reported by the Snyk Security Research Team, have been corrected. CVE-2018-12036 allows attackers to write to arbitrary files via a crafted archive that holds directory traversal filenames.
-- The dependency-check-maven plugin no longer uses the [Central Analyzer](https://jeremylong.github.io/DependencyCheck/analyzers/central-analyzer.html) by default
-- Updated dependency-check-maven so that it will not fail when your multi-module build has dependencies that have not yet been built in the reactor (See [#740](https://github.com/jeremylong/DependencyCheck/issues/740))
+- The dependency-check-maven plugin no longer uses the [Central Analyzer](https://dependency-check.github.io/DependencyCheck/analyzers/central-analyzer.html) by default
+- Updated dependency-check-maven so that it will not fail when your multi-module build has dependencies that have not yet been built in the reactor (See [#740](https://github.com/dependency-check/DependencyCheck/issues/740))
- Note if the required dependency has not yet been built in the reactor and the dependency is available in a configured repository dependency-check-maven, as expected, would pull the dependency from the repository for analysis.
- Minor documentation updates
- False positive reduction
- Fixed the Gradle Plugin and Ant Task so that the temp directory is properly cleaned up after execution
-- Removed TLSv1 from the list of protocols used by default (See [#1237](https://github.com/jeremylong/DependencyCheck/pull/1237))
+- Removed TLSv1 from the list of protocols used by default (See [#1237](https://github.com/dependency-check/DependencyCheck/pull/1237))
-## [Version 3.1.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.1.2) (2018-04-02)
+## [Version 3.1.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.1.2) (2018-04-02)
### Fixed
@@ -928,11 +1422,11 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
will include a reference to the project/module where they were found
- The configuration option `versionCheckEnabled` was added to Maven to allow users to disable the check for
new versions of dependency-check; this will be added to gradle plugin, Ant Task, and the CLI in a future release
-- The XML and JSON reports were fixed so that the correct version number is displayed see [issue #1109](https://github.com/jeremylong/DependencyCheck/issues/1109)
+- The XML and JSON reports were fixed so that the correct version number is displayed see [issue #1109](https://github.com/dependency-check/DependencyCheck/issues/1109)
- The initial database creation time for H2 databases was improved
- Changes made to decrease false positive and false negatives
-## [Version 3.1.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.1.1) (2018-01-29)
+## [Version 3.1.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.1.1) (2018-01-29)
### Fixed
@@ -941,7 +1435,7 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
- False positive reduction.
- Minor documentation cleanup.
-## [Version 3.1.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.1.0) (2018-01-02)
+## [Version 3.1.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.1.0) (2018-01-02)
### Changed
@@ -961,19 +1455,19 @@ See the full listing of [resolved issues](https://github.com/jeremylong/Dependen
the query to break.
- General cleanup, false positive, and false negative reduction.
-## [Version 3.0.2](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.2) (2017-11-13)
+## [Version 3.0.2](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.0.2) (2017-11-13)
### Fixed
- Updated the query format for the CentralAnalyzer; the old format caused the CentralAnalyzer to fail
-## [Version 3.0.1](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.1) (2017-10-20)
+## [Version 3.0.1](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.0.1) (2017-10-20)
### Fixed
- Fixed a database connection issue that affected some usages.
-## [Version 3.0.0](https://github.com/jeremylong/DependencyCheck/releases/tag/v3.0.0) (2017-10-16)
+## [Version 3.0.0](https://github.com/dependency-check/DependencyCheck/releases/tag/v3.0.0) (2017-10-16)
- Several bug fixes and false positive reduction
- The 2.x branch introduced several new false positives – but also reduced the false negatives
diff --git a/Dockerfile b/Dockerfile
index dffcc4af62f..bce18e1cdf3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,14 +1,14 @@
-FROM golang:1.17.1-alpine AS go
+FROM golang:1.25.3-alpine AS go
-FROM azul/zulu-openjdk-alpine:17 AS jlink
+FROM azul/zulu-openjdk-alpine:25 AS jlink
-RUN "$JAVA_HOME/bin/jlink" --compress=2 --module-path /opt/java/openjdk/jmods --add-modules java.base,java.compiler,java.datatransfer,jdk.crypto.ec,java.desktop,java.instrument,java.logging,java.management,java.naming,java.rmi,java.scripting,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.unsupported --output /jlinked
+RUN "$JAVA_HOME/bin/jlink" --compress=zip-6 --module-path /opt/java/openjdk/jmods --add-modules java.base,java.compiler,java.datatransfer,jdk.crypto.ec,java.desktop,java.instrument,java.logging,java.management,java.naming,java.rmi,java.scripting,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.unsupported --output /jlinked
-FROM mcr.microsoft.com/dotnet/runtime:6.0-alpine3.16
+FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine3.22
ARG VERSION
-ARG POSTGRES_DRIVER_VERSION=42.2.19
-ARG MYSQL_DRIVER_VERSION=8.0.23
+ARG POSTGRES_DRIVER_VERSION=42.7.5
+ARG MYSQL_DRIVER_VERSION=9.2.0
ARG UID=1000
ARG GID=1000
@@ -34,9 +34,9 @@ RUN apk update
rm dependency-check-${VERSION}-release.zip && \
cd /usr/share/dependency-check/plugins && \
curl -Os "https://jdbc.postgresql.org/download/postgresql-${POSTGRES_DRIVER_VERSION}.jar" && \
- curl -Ls "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-${MYSQL_DRIVER_VERSION}.tar.gz" \
+ curl -Ls "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-${MYSQL_DRIVER_VERSION}.tar.gz" \
| tar -xz --directory "/usr/share/dependency-check/plugins" --strip-components=1 --no-same-owner \
- "mysql-connector-java-${MYSQL_DRIVER_VERSION}/mysql-connector-java-${MYSQL_DRIVER_VERSION}.jar" && \
+ "mysql-connector-j-${MYSQL_DRIVER_VERSION}/mysql-connector-j-${MYSQL_DRIVER_VERSION}.jar" && \
addgroup -S -g ${GID} ${user} && adduser -S -D -u ${UID} -G ${user} ${user} && \
mkdir /usr/share/dependency-check/data && \
chown -R ${user}:0 /usr/share/dependency-check && \
@@ -47,7 +47,7 @@ RUN apk update
apk del .build-deps
### remove any suid sgid - we don't need them
-RUN find / -perm +6000 -type f -exec chmod a-s {} \;
+RUN find / -path /proc -prune -perm +6000 -type f -exec chmod a-s {} \;
USER ${UID}
VOLUME ["/src", "/report"]
diff --git a/NOTICE.txt b/NOTICE.txt
index 6638101b332..2a7d5099f7f 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,6 +1,6 @@
dependency-check
-Copyright (c) 2012-2013 Jeremy Long. All Rights Reserved.
+Copyright (c) 2012-2025 OWASP Dependency-Check Contributors. All Rights Reserved.
The licenses for the software listed below can be found in the META-INF/licenses/[dependency name].
diff --git a/README.md b/README.md
index b29246c5cbe..50a2edfec1a 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,85 @@
-[](https://mvnrepository.com/artifact/org.owasp/dependency-check-maven) [](https://github.com/jeremylong/DependencyCheck/actions/workflows/build.yml) [](https://scan.coverity.com/projects/dependencycheck) [](https://www.codacy.com/app/jeremylong/DependencyCheck?utm_source=github.com&utm_medium=referral&utm_content=jeremylong/DependencyCheck&utm_campaign=Badge_Grade) [](https://bestpractices.coreinfrastructure.org/projects/843) [](https://www.apache.org/licenses/LICENSE-2.0.txt)
+[](https://mvnrepository.com/artifact/org.owasp/dependency-check-maven) [](https://github.com/dependency-check/DependencyCheck/actions/workflows/build.yml) [](https://scan.coverity.com/projects/dependencycheck) [](https://www.codacy.com/app/jeremylong/DependencyCheck?utm_source=github.com&utm_medium=referral&utm_content=jeremylong/DependencyCheck&utm_campaign=Badge_Grade) [](https://bestpractices.coreinfrastructure.org/projects/843) [](https://www.apache.org/licenses/LICENSE-2.0.txt)
-[](http://www.toolswatch.org/2018/05/black-hat-arsenal-usa-2018-the-w0w-lineup/) [](https://www.toolswatch.org/2015/06/black-hat-arsenal-usa-2015-speakers-lineup/) [](https://www.toolswatch.org/2014/06/black-hat-usa-2014-arsenal-tools-speaker-list/) [](https://www.toolswatch.org/2013/06/announcement-blackhat-arsenal-usa-2013-selected-tools/)
+[](https://www.blackhat.com/us-18/arsenal.html#jeremy-long) [](https://www.blackhat.com/us-15/arsenal.html#jeremy-long) [](https://www.blackhat.com/us-14/arsenal.html#Long) [](https://www.blackhat.com/us-13/arsenal.html#Long)
# Dependency-Check
Dependency-Check is a Software Composition Analysis (SCA) tool that attempts to detect publicly disclosed vulnerabilities contained within a project's dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries.
-Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/). Additionally, more information about the architecture and ways to extend dependency-check can be found on the [wiki].
+Documentation and links to production binary releases can be found on the [github pages](https://dependency-check.github.io/DependencyCheck). Additionally, more information about the architecture and ways to extend dependency-check can be found on the [wiki].
-## 8.0.0 Upgrade Notice
+## Notice
-8.0.0 contains breaking changes which requires updates to the database. If using
-an externally hosted database the schema will need to be updated. When using the
-embedded H2 database the schema should be upgraded automatically. However, if
-issues arise you may need to purge the database:
+This product uses the NVD API but is not endorsed or certified by the NVD.
-- gradle: `./gradlew dependencyCheckPurge`
-- maven: `mvn org.owasp:dependency-check-maven:8.0.0:purge`
-- cli: `dependency-check.sh --purge`
+
+## Breaking Changes in 11.0.0
+
+- Java 11 is now required to run dependency-check 11.0.0 or higher
+- H2 database upgrade
+
+ 11.0.0 contains breaking changes using the local H2 database. A full download
+ of the NVD data will occur. Note that if you are using a shared data directory
+ the h2 database file is not compatible with older versions of dependency-check.
+ If you run into problems you may need to run a purge:
+
+ - gradle: `./gradlew dependencyCheckPurge`
+ - maven: `mvn org.owasp:dependency-check-maven:9.0.0:purge`
+ - cli: `dependency-check.sh --purge`
+
+## Mandatory Upgrade Notice
+
+**Upgrading to 10.0.2 or later is mandatory**
+
+Older versions of dependency-check are causing numerous, duplicative requests that
+end in processing failures are causing unnecassary load on the NVD API. Dependency-check
+10.0.2 uses an updated `User-Agent` header that will allow the NVD to block calls
+from the older client.
+
+### NVD API Key Highly Recommended
+
+Dependency-check has moved from using the NVD data-feed to the NVD API.
+Users of dependency-check are **highly** encouraged to obtain an NVD API Key; see https://nvd.nist.gov/developers/request-an-api-key
+Without an NVD API Key dependency-check's updates will be **extremely slow**.
+Please see the documentation for the cli, maven, gradle, or ant integrations on
+how to set the NVD API key.
+
+#### The NVD API Key, CI, and Rate Limiting
+
+The NVD API has enforced rate limits. If you are using a single API KEY and
+multiple builds occur you could hit the rate limit and receive 403 errors. In
+a CI environment one must use a caching strategy.
+
+#### Gradle build Environment
+
+With 9.0.0 users may encounter issues with `NoSuchMethodError` exceptions due to
+dependency resolution. If you encounter this issue you will need to pin some of
+the transitive dependencies of dependency-check to specific versions. For example:
+
+/buildSrc/build.gradle
+```groovy
+dependencies {
+ constraints {
+ // org.owasp.dependencycheck needs at least this version of jackson. Other plugins pull in older versions..
+ add("implementation", "com.fasterxml.jackson:jackson-bom:2.16.1")
+
+ // org.owasp.dependencycheck needs these versions. Other plugins pull in older versions..
+ add("implementation", "org.apache.commons:commons-lang3:3.14.0")
+ add("implementation", "org.apache.commons:commons-text:1.11.0")
+ }
+}
+```
## Requirements
+### Java Version
+
+Minimum Java Version: Java 11
+
### Internet Access
OWASP dependency-check requires access to several externally hosted resources.
-For more information see [Internet Access Required](https://jeremylong.github.io/DependencyCheck/data/index.html).
+For more information see [Internet Access Required](https://dependency-check.github.io/DependencyCheck/data/index.html).
### Build Tools
@@ -32,8 +87,8 @@ In order to analyze some technology stacks dependency-check may require other
development tools to be installed. Some of the analysis listed below may be
experimental and require the experimental analyzers to be enabled.
-1. To analyze .NET Assemblies the dotnet 6 run time or SDK must be installed.
- - Assemblies targeting other run times can be analyzed - but 6 is required to run the analysis.
+1. To analyze .NET Assemblies the dotnet 8 run time or SDK must be installed.
+ - Assemblies targeting other run times can be analyzed - but 8 is required to run the analysis.
2. If analyzing GoLang projects `go` must be installed.
3. The analysis of `Elixir` projects requires `mix_audit`.
4. The analysis of `npm`, `pnpm`, and `yarn` projects requires `npm`, `pnpm`, or `yarn` to be installed.
@@ -49,13 +104,13 @@ For instructions on the use of the Jenkins plugin please see the [OWASP Dependen
### Command Line
More detailed instructions can be found on the
-[dependency-check github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-cli/).
-The latest CLI can be downloaded from github in the [releases section](https://github.com/jeremylong/DependencyCheck/releases).
+[dependency-check github pages](https://dependency-check.github.io/DependencyCheck/dependency-check-cli/).
+The latest CLI can be downloaded from github in the [releases section](https://github.com/dependency-check/DependencyCheck/releases).
Downloading the latest release:
```
-$ VERSION=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt)
-$ curl -s "https://github.com/jeremylong/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
+$ VERSION=$(curl -s https://dependency-check.github.io/DependencyCheck/current.txt)
+$ curl -Ls "https://github.com/dependency-check/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
```
On *nix
@@ -78,7 +133,7 @@ $ dependency-check --out . --scan [path to jar files to be scanned]
### Maven Plugin
-More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven).
+More detailed instructions can be found on the [dependency-check-maven github pages](https://dependency-check.github.io/DependencyCheck/dependency-check-maven).
By default, the plugin is tied to the `verify` phase (i.e. `mvn verify`). Alternatively,
one can directly invoke the plugin via `mvn org.owasp:dependency-check-maven:check`.
@@ -110,20 +165,20 @@ The dependency-check plugin can be configured using the following:
### Gradle Plugin
-For instructions on the use of the Gradle Plugin, please see the [dependency-check-gradle github page](http://jeremylong.github.io/DependencyCheck/dependency-check-gradle).
+For instructions on the use of the Gradle Plugin, please see the [dependency-check-gradle github page](https://dependency-check.github.io/DependencyCheck/dependency-check-gradle).
### Ant Task
-For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-ant).
+For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](https://dependency-check.github.io/DependencyCheck/dependency-check-ant).
## Development Prerequisites
For installation to pass, you must have the following components installed:
-* Java: `java -version` 1.8
-* Maven: `mvn -version` 3.5.0 and higher
+* Java: `java -version` 11.0
+* Maven: `mvn -version` 3.6.3 and higher
Tests cases require:
-* dotnet core version 6.0
+* dotnet core version 8.0
* Go: `go version` 1.12 and higher
* Ruby [bundler-audit](https://github.com/rubysec/bundler-audit#install)
* [Yarn](https://classic.yarnpkg.com/en/docs/install/)
@@ -138,7 +193,7 @@ The repository has some large files due to test resources. The team has tried to
However, it is recommended that you perform a shallow clone to save yourself time:
```bash
-git clone --depth 1 https://github.com/jeremylong/DependencyCheck.git
+git clone --depth 1 https://github.com/dependency-check/DependencyCheck.git
```
On *nix
@@ -263,7 +318,7 @@ docker run --rm ^
Building From Source
--------------------
-To build dependency-check (using Java 8) run the command:
+To build dependency-check (using Java 11) run the command:
```
mvn -s settings.xml install
@@ -284,9 +339,9 @@ mvn org.owasp:dependency-check-maven:aggregate -P-test-dependencies -DskipProvid
Building the documentation
--------------------------
-The documentation on the [github pages](http://jeremylong.github.io/DependencyCheck/) is generated from this repository:
+The documentation on the [github pages](https://dependency-check.github.io/DependencyCheck/) is generated from this repository:
- mvn -s settings.xml site site:staging
+ mvn -s settings.xml site site:stage
Once done, point your browser to `./target/staging/index.html`.
@@ -302,11 +357,15 @@ mvn -s settings.xml install
License
-------
-Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/main/LICENSE.txt) file for the full license.
+Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/dependency-check/DependencyCheck/main/LICENSE.txt) file for the full license.
Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt][notices] file for more information.
-Copyright (c) 2012-2023 Jeremy Long. All Rights Reserved.
+This product uses the NVD API but is not endorsed or certified by the NVD.
+
+Copyright (c) 2012-2025 Jeremy Long. All Rights Reserved.
+
+ [wiki]: https://github.com/dependency-check/DependencyCheck/wiki
+ [notices]: https://github.com/dependency-check/DependencyCheck/blob/main/NOTICE.txt
- [wiki]: https://github.com/jeremylong/DependencyCheck/wiki
- [notices]: https://github.com/jeremylong/DependencyCheck/blob/main/NOTICE.txt
+
diff --git a/SECURITY.md b/SECURITY.md
index ffc5f225656..08e36f7633f 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,15 +2,15 @@
## Supported Versions
-| Version | Supported |
-| ---------|--------------------|
-| 8.0.0+ | :white_check_mark: |
-| <= 7.4.4 | :x: |
+| Version | Supported |
+|-----------|--------------------|
+| 12.1.3+ | :white_check_mark: |
+| <= 12.1.2 | :x: |
## Reporting a Vulnerability
If a security vulnerability is identified in dependency-check please
-open an [issue](https://github.com/jeremylong/DependencyCheck/issues/new/choose)
+open an [issue](https://github.com/dependency-check/DependencyCheck/issues/new/choose)
and/or submit a PR to resolve the identified vulnerability.
The team is very responsive to reported vulnerabilities - historically having reported issues resolved in 30 days or less.
diff --git a/ant/README.md b/ant/README.md
index fc971dd1c69..3338cd1f12d 100644
--- a/ant/README.md
+++ b/ant/README.md
@@ -6,7 +6,7 @@ performed are a "best effort" and as such, there could be false positives as wel
vulnerabilities in 3rd party components is a well-known problem and is currently documented in the 2021 OWASP
Top 10 as [A06:2021 – Vulnerable and Outdated Components](https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/).
-Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/index.html).
+Documentation and links to production binary releases can be found on the [github pages](https://dependency-check.github.io/DependencyCheck/dependency-check-ant/index.html).
Copyright & License
@@ -14,6 +14,8 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
-Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/blob/main/LICENSE.txt) file for the full license.
+Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/dependency-check/DependencyCheck/blob/main/LICENSE.txt) file for the full license.
-Dependency-Check-Ant makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/jeremylong/DependencyCheck/blob/main/ant/NOTICE.txt) file for more information.
+Dependency-Check-Ant makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/dependency-check/DependencyCheck/blob/main/ant/NOTICE.txt) file for more information.
+
+
\ No newline at end of file
diff --git a/ant/pom.xml b/ant/pom.xml
index cd3d7a4ac5f..0d8ed742691 100644
--- a/ant/pom.xml
+++ b/ant/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 8.2.2-SNAPSHOT
+ 12.1.9-SNAPSHOTdependency-check-ant
@@ -29,9 +29,9 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
Dependency-Check Ant Taskdependency-check-ant is an Ant Task that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the project's dependencies. The task will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
- scm:git:https://github.com/jeremylong/DependencyCheck.git
- https://github.com/jeremylong/DependencyCheck/tree/main/ant
- scm:git:git@github.com:jeremylong/DependencyCheck.git
+ scm:git:https://github.com/dependency-check/DependencyCheck.git
+ https://github.com/dependency-check/DependencyCheck/tree/main/ant
+ scm:git:git@github.com/dependency-check/DependencyCheck.gitv6.4.1
@@ -89,25 +89,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
-
- copy-test-upgrade-script
- pre-integration-test
-
- copy-resources
-
-
- ${project.build.directory}/test-classes/data
-
-
- ${basedir}/../core/src/test/resources/data
- false
-
- upgrade_4.2.sql
-
-
-
-
- copy-test-resources-1pre-integration-test
@@ -184,26 +165,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
-
- copy-data
- pre-integration-test
-
- copy-resources
-
-
- ${project.build.directory}/test-classes
-
-
- ${basedir}/../src/test/resources
- false
-
- db.cve.zip
- index.cpe.zip
-
-
-
-
-
@@ -252,6 +213,19 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
dependency-check-utils${project.parent.version}
+
+
+ io.github.jeremylong
+ open-vulnerability-clients
+
+
+ org.slf4j
+ slf4j-api
+
+
+ io.github.jeremylong
+ jcs3-slf4j
+ org.owaspdependency-check-core
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
index 270c2b6f84f..97268391d73 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java
@@ -20,6 +20,8 @@
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.concurrent.NotThreadSafe;
import org.apache.tools.ant.BuildException;
@@ -35,14 +37,17 @@
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Vulnerability;
+import org.owasp.dependencycheck.dependency.naming.Identifier;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.SeverityUtil;
import org.slf4j.impl.StaticLoggerBinder;
-//CSOFF: MethodCount
+//CSOFF: MethodCount
/**
* An Ant task definition to execute dependency-check during an Ant build.
*
@@ -89,27 +94,6 @@ public class Check extends Update {
* Sets whether or not the Node Audit Analyzer should use a local cache.
*/
private Boolean nodeAuditSkipDevDependencies;
- /**
- * Whether or not the RetireJS Analyzer is enabled.
- */
- private Boolean retireJsAnalyzerEnabled;
- /**
- * The URL to the RetireJS JSON data.
- */
- private String retireJsUrl;
- /**
- * The user to download URL to the RetireJS JSON data.
- */
- private String retireJsUrlUser;
- /**
- * The password to download URL to the RetireJS JSON data.
- */
- private String retireJsUrlPassword;
- /**
- * Whether or not the RetireJS Analyzer will be updated regardless of the
- * `autoupdate` settings. Defaults to false.
- */
- private Boolean retireJsAnalyzerForceUpdate;
/**
* The list of filters (regular expressions) used by the RetireJS Analyzer
* to exclude files that contain matching content..
@@ -237,13 +221,13 @@ public class Check extends Update {
*/
private Boolean autoUpdate;
/**
- * The report format to be generated (HTML, XML, JUNIT, CSV, JSON, SARIF,
- * JENKINS, ALL). Default is HTML.
+ * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF,
+ * JENKINS, GITLAB, ALL). Default is HTML.
*/
private String reportFormat = "HTML";
/**
- * The report format to be generated (HTML, XML, JUNIT, CSV, JSON, SARIF,
- * JENKINS, ALL). Default is HTML.
+ * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF,
+ * JENKINS, GITLAB, ALL). Default is HTML.
*/
private final List reportFormats = new ArrayList<>();
/**
@@ -282,14 +266,6 @@ public class Check extends Update {
* Whether or not the Archive Analyzer is enabled.
*/
private Boolean archiveAnalyzerEnabled;
- /**
- * Whether or not the Known Exploited Vulnerability Analyzer is enabled.
- */
- private Boolean knownExploitedEnabled;
- /**
- * The URL to the known exploited vulnerabilities JSON datafeed.
- */
- private String knownExploitedUrl;
/**
* Whether or not the .NET Nuspec Analyzer is enabled.
*/
@@ -298,10 +274,18 @@ public class Check extends Update {
* Whether or not the .NET Nuget packages.config file Analyzer is enabled.
*/
private Boolean nugetconfAnalyzerEnabled;
+ /**
+ * Whether or not the Libman Analyzer is enabled.
+ */
+ private Boolean libmanAnalyzerEnabled;
/**
* Whether or not the PHP Composer Analyzer is enabled.
*/
private Boolean composerAnalyzerEnabled;
+ /**
+ * Whether or not the PHP Composer Analyzer will skip "packages-dev".
+ */
+ private Boolean composerAnalyzerSkipDev;
/**
* Whether or not the Perl CPAN File Analyzer is enabled.
*/
@@ -352,6 +336,10 @@ public class Check extends Update {
* Whether or not the CocoaPods Analyzer is enabled.
*/
private Boolean cocoapodsAnalyzerEnabled;
+ /**
+ * Whether or not the Carthage Analyzer is enabled.
+ */
+ private Boolean carthageAnalyzerEnabled;
/**
* Whether or not the Swift package Analyzer is enabled.
@@ -416,9 +404,31 @@ public class Check extends Update {
* The Artifactory bearer token.
*/
private String artifactoryAnalyzerBearerToken;
+ /**
+ * Whether the version check is enabled
+ */
+ private Boolean versionCheckEnabled;
+ /**
+ * whether an unsused suppression rule should get force the build to fail
+ */
+ private boolean failBuildOnUnusedSuppressionRule = false;
+
+ /**
+ * The username to download user-authored suppression files from an HTTP Basic auth protected location.
+ */
+ private String suppressionFileUser;
+ /**
+ * The password to download user-authored suppression files from an HTTP Basic auth protected location.
+ */
+ private String suppressionFilePassword;
+ /**
+ * The token to download user-authored suppression files from an HTTP Bearer auth protected location.
+ */
+ private String suppressionFileBearerToken;
+
+ //region Code copied from org.apache.tools.ant.taskdefs.PathConvert
//The following code was copied Apache Ant PathConvert
- //BEGIN COPY from org.apache.tools.ant.taskdefs.PathConvert
/**
* Path to be converted
*/
@@ -441,28 +451,6 @@ public void add(ResourceCollection rc) {
getPath().add(rc);
}
- /**
- * Add a suppression file.
- *
- * This is called by Ant with the configured {@link SuppressionFile}.
- *
- * @param suppressionFile the suppression file to add.
- */
- public void addConfiguredSuppressionFile(final SuppressionFile suppressionFile) {
- suppressionFiles.add(suppressionFile.getPath());
- }
-
- /**
- * Add a report format.
- *
- * This is called by Ant with the configured {@link ReportFormat}.
- *
- * @param reportFormat the reportFormat to add.
- */
- public void addConfiguredReportFormat(final ReportFormat reportFormat) {
- reportFormats.add(reportFormat.getFormat());
- }
-
/**
* Returns the path. If the path has not been initialized yet, this class is
* synchronized, and will instantiate the path object.
@@ -519,7 +507,7 @@ private void dealWithReferences() throws BuildException {
getPath().add((ResourceCollection) o);
}
}
- // END COPY from org.apache.tools.ant.taskdefs
+ //endregion COPIED from org.apache.tools.ant.taskdefs
/**
* Construct a new DependencyCheckTask.
@@ -531,6 +519,38 @@ public Check() {
StaticLoggerBinder.getSingleton().setTask(this);
}
+ /**
+ * Add a suppression file.
+ *
+ * This is called by Ant with the configured {@link SuppressionFile}.
+ *
+ * @param suppressionFile the suppression file to add.
+ */
+ public void addConfiguredSuppressionFile(final SuppressionFile suppressionFile) {
+ suppressionFiles.add(suppressionFile.getPath());
+ }
+
+ /**
+ * Add a report format.
+ *
+ * This is called by Ant with the configured {@link ReportFormat}.
+ *
+ * @param reportFormat the reportFormat to add.
+ */
+ public void addConfiguredReportFormat(final ReportFormat reportFormat) {
+ reportFormats.add(reportFormat.getFormat());
+ }
+
+ /**
+ * Sets whether the version check is enabled.
+ *
+ * @param versionCheckEnabled a Boolean indicating if the version check is
+ * enabled.
+ */
+ public void setVersionCheckEnabled(Boolean versionCheckEnabled) {
+ this.versionCheckEnabled = versionCheckEnabled;
+ }
+
/**
* Get the value of projectName.
*
@@ -552,15 +572,6 @@ public void setProjectName(String projectName) {
this.projectName = projectName;
}
- /**
- * Get the value of reportOutputDirectory.
- *
- * @return the value of reportOutputDirectory
- */
- public String getReportOutputDirectory() {
- return reportOutputDirectory;
- }
-
/**
* Set the value of reportOutputDirectory.
*
@@ -570,15 +581,6 @@ public void setReportOutputDirectory(String reportOutputDirectory) {
this.reportOutputDirectory = reportOutputDirectory;
}
- /**
- * Get the value of failBuildOnCVSS.
- *
- * @return the value of failBuildOnCVSS
- */
- public float getFailBuildOnCVSS() {
- return failBuildOnCVSS;
- }
-
/**
* Set the value of failBuildOnCVSS.
*
@@ -588,15 +590,6 @@ public void setFailBuildOnCVSS(float failBuildOnCVSS) {
this.failBuildOnCVSS = failBuildOnCVSS;
}
- /**
- * Get the value of junitFailOnCVSS.
- *
- * @return the value of junitFailOnCVSS
- */
- public float getJunitFailOnCVSS() {
- return junitFailOnCVSS;
- }
-
/**
* Set the value of junitFailOnCVSS.
*
@@ -606,15 +599,6 @@ public void setJunitFailOnCVSS(float junitFailOnCVSS) {
this.junitFailOnCVSS = junitFailOnCVSS;
}
- /**
- * Get the value of autoUpdate.
- *
- * @return the value of autoUpdate
- */
- public Boolean isAutoUpdate() {
- return autoUpdate;
- }
-
/**
* Set the value of autoUpdate.
*
@@ -624,15 +608,6 @@ public void setAutoUpdate(Boolean autoUpdate) {
this.autoUpdate = autoUpdate;
}
- /**
- * Get the value of prettyPrint.
- *
- * @return the value of prettyPrint
- */
- public Boolean isPrettyPrint() {
- return prettyPrint;
- }
-
/**
* Set the value of prettyPrint.
*
@@ -664,15 +639,6 @@ public List getReportFormats() {
return this.reportFormats;
}
- /**
- * Gets suppression file paths.
- *
- * @return the suppression files.
- */
- public List getSuppressionFiles() {
- return suppressionFiles;
- }
-
/**
* Set the value of suppressionFile.
*
@@ -683,48 +649,48 @@ public void setSuppressionFile(String suppressionFile) {
}
/**
- * Get the value of hintsFile.
+ * Sets the username to download user-authored suppression files from an HTTP Basic auth protected location.
*
- * @return the value of hintsFile
+ * @param suppressionFileUser The username
*/
- public String getHintsFile() {
- return hintsFile;
+ public void setSuppressionFileUser(String suppressionFileUser) {
+ this.suppressionFileUser = suppressionFileUser;
}
/**
- * Set the value of hintsFile.
+ * Sets the password/token to download user-authored suppression files from an HTTP Basic auth protected location.
*
- * @param hintsFile new value of hintsFile
+ * @param suppressionFilePassword The password/token
*/
- public void setHintsFile(String hintsFile) {
- this.hintsFile = hintsFile;
+ public void setSuppressionFilePassword(String suppressionFilePassword) {
+ this.suppressionFilePassword = suppressionFilePassword;
}
/**
- * Get the value of showSummary.
+ * Sets the token to download user-authored suppression files from an HTTP Bearer auth protected location.
*
- * @return the value of showSummary
+ * @param suppressionFileBearerToken The token
*/
- public boolean isShowSummary() {
- return showSummary;
+ public void setSuppressionFileBearerToken(String suppressionFileBearerToken) {
+ this.suppressionFileBearerToken = suppressionFileBearerToken;
}
/**
- * Set the value of showSummary.
+ * Set the value of hintsFile.
*
- * @param showSummary new value of showSummary
+ * @param hintsFile new value of hintsFile
*/
- public void setShowSummary(boolean showSummary) {
- this.showSummary = showSummary;
+ public void setHintsFile(String hintsFile) {
+ this.hintsFile = hintsFile;
}
/**
- * Get the value of enableExperimental.
+ * Set the value of showSummary.
*
- * @return the value of enableExperimental
+ * @param showSummary new value of showSummary
*/
- public Boolean isEnableExperimental() {
- return enableExperimental;
+ public void setShowSummary(boolean showSummary) {
+ this.showSummary = showSummary;
}
/**
@@ -736,15 +702,6 @@ public void setEnableExperimental(Boolean enableExperimental) {
this.enableExperimental = enableExperimental;
}
- /**
- * Get the value of enableRetired.
- *
- * @return the value of enableRetired
- */
- public Boolean isEnableRetired() {
- return enableRetired;
- }
-
/**
* Set the value of enableRetired.
*
@@ -754,15 +711,6 @@ public void setEnableRetired(Boolean enableRetired) {
this.enableRetired = enableRetired;
}
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isJarAnalyzerEnabled() {
- return jarAnalyzerEnabled;
- }
-
/**
* Sets whether or not the analyzer is enabled.
*
@@ -772,15 +720,6 @@ public void setJarAnalyzerEnabled(Boolean jarAnalyzerEnabled) {
this.jarAnalyzerEnabled = jarAnalyzerEnabled;
}
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isArchiveAnalyzerEnabled() {
- return archiveAnalyzerEnabled;
- }
-
/**
* Sets whether the analyzer is enabled.
*
@@ -790,51 +729,6 @@ public void setArchiveAnalyzerEnabled(Boolean archiveAnalyzerEnabled) {
this.archiveAnalyzerEnabled = archiveAnalyzerEnabled;
}
- /**
- * Returns whether the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isKnownExploitedEnabled() {
- return knownExploitedEnabled;
- }
-
- /**
- * Sets whether the analyzer is enabled.
- *
- * @param knownExploitedEnabled the value of the new setting
- */
- public void setKnownExploitedEnabled(Boolean knownExploitedEnabled) {
- this.knownExploitedEnabled = knownExploitedEnabled;
- }
-
- /**
- * Returns the knownExploitedUrl.
- *
- * @return the knownExploitedUrl
- */
- public String getKnownExploitedUrl() {
- return knownExploitedUrl;
- }
-
- /**
- * Sets the the knownExploitedUrl.
- *
- * @param knownExploitedUrl the URL
- */
- public void setKnownExploitedUrl(String knownExploitedUrl) {
- this.knownExploitedUrl = knownExploitedUrl;
- }
-
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isAssemblyAnalyzerEnabled() {
- return assemblyAnalyzerEnabled;
- }
-
/**
* Sets whether or not the analyzer is enabled.
*
@@ -844,15 +738,6 @@ public void setAssemblyAnalyzerEnabled(Boolean assemblyAnalyzerEnabled) {
this.assemblyAnalyzerEnabled = assemblyAnalyzerEnabled;
}
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isMSBuildAnalyzerEnabled() {
- return msbuildAnalyzerEnabled;
- }
-
/**
* Sets whether or not the analyzer is enabled.
*
@@ -862,24 +747,6 @@ public void setMSBuildAnalyzerEnabled(Boolean msbuildAnalyzerEnabled) {
this.msbuildAnalyzerEnabled = msbuildAnalyzerEnabled;
}
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isNuspecAnalyzerEnabled() {
- return nuspecAnalyzerEnabled;
- }
-
- /**
- * Returns whether or not the analyzer is enabled.
- *
- * @return true if the analyzer is enabled
- */
- public Boolean isNugetconfAnalyzerEnabled() {
- return nugetconfAnalyzerEnabled;
- }
-
/**
* Sets whether or not the analyzer is enabled.
*
@@ -899,12 +766,12 @@ public void setNugetconfAnalyzerEnabled(Boolean nugetconfAnalyzerEnabled) {
}
/**
- * Get the value of composerAnalyzerEnabled.
+ * Sets whether or not the analyzer is enabled.
*
- * @return the value of composerAnalyzerEnabled
+ * @param libmanAnalyzerEnabled the value of the new setting
*/
- public Boolean isComposerAnalyzerEnabled() {
- return composerAnalyzerEnabled;
+ public void setLibmanAnalyzerEnabled(Boolean libmanAnalyzerEnabled) {
+ this.libmanAnalyzerEnabled = libmanAnalyzerEnabled;
}
/**
@@ -917,12 +784,12 @@ public void setComposerAnalyzerEnabled(Boolean composerAnalyzerEnabled) {
}
/**
- * Get the value of cpanfileAnalyzerEnabled.
+ * Set the value of composerAnalyzerSkipDev.
*
- * @return the value of cpanfileAnalyzerEnabled
+ * @param composerAnalyzerSkipDev new value of composerAnalyzerSkipDev
*/
- public Boolean isCpanfileAnalyzerEnabled() {
- return cpanfileAnalyzerEnabled;
+ public void setComposerAnalyzerSkipDev(Boolean composerAnalyzerSkipDev) {
+ this.composerAnalyzerSkipDev = composerAnalyzerSkipDev;
}
/**
@@ -934,15 +801,6 @@ public void setCpanfileAnalyzerEnabled(Boolean cpanfileAnalyzerEnabled) {
this.cpanfileAnalyzerEnabled = cpanfileAnalyzerEnabled;
}
- /**
- * Get the value of autoconfAnalyzerEnabled.
- *
- * @return the value of autoconfAnalyzerEnabled
- */
- public Boolean isAutoconfAnalyzerEnabled() {
- return autoconfAnalyzerEnabled;
- }
-
/**
* Set the value of autoconfAnalyzerEnabled.
*
@@ -952,15 +810,6 @@ public void setAutoconfAnalyzerEnabled(Boolean autoconfAnalyzerEnabled) {
this.autoconfAnalyzerEnabled = autoconfAnalyzerEnabled;
}
- /**
- * Get the value of pipAnalyzerEnabled.
- *
- * @return the value of pipAnalyzerEnabled
- */
- public Boolean isPipAnalyzerEnabled() {
- return pipAnalyzerEnabled;
- }
-
/**
* Set the value of pipAnalyzerEnabled.
*
@@ -970,15 +819,6 @@ public void setPipAnalyzerEnabled(Boolean pipAnalyzerEnabled) {
this.pipAnalyzerEnabled = pipAnalyzerEnabled;
}
- /**
- * Get the value of pipfileAnalyzerEnabled.
- *
- * @return the value of pipfileAnalyzerEnabled
- */
- public Boolean isPipfileAnalyzerEnabled() {
- return pipfileAnalyzerEnabled;
- }
-
/**
* Set the value of pipfileAnalyzerEnabled.
*
@@ -988,15 +828,6 @@ public void setPipfileAnalyzerEnabled(Boolean pipfileAnalyzerEnabled) {
this.pipfileAnalyzerEnabled = pipfileAnalyzerEnabled;
}
- /**
- * Get the value of poetryAnalyzerEnabled.
- *
- * @return the value of poetryAnalyzerEnabled
- */
- public Boolean isPoetryAnalyzerEnabled() {
- return poetryAnalyzerEnabled;
- }
-
/**
* Set the value of poetryAnalyzerEnabled.
*
@@ -1006,15 +837,6 @@ public void setPoetryAnalyzerEnabled(Boolean poetryAnalyzerEnabled) {
this.poetryAnalyzerEnabled = poetryAnalyzerEnabled;
}
- /**
- * Returns if the Bundle Audit Analyzer is enabled.
- *
- * @return if the Bundle Audit Analyzer is enabled.
- */
- public Boolean isBundleAuditAnalyzerEnabled() {
- return bundleAuditAnalyzerEnabled;
- }
-
/**
* Sets if the Bundle Audit Analyzer is enabled.
*
@@ -1025,15 +847,6 @@ public void setBundleAuditAnalyzerEnabled(Boolean bundleAuditAnalyzerEnabled) {
this.bundleAuditAnalyzerEnabled = bundleAuditAnalyzerEnabled;
}
- /**
- * Returns the path to the bundle audit executable.
- *
- * @return the path to the bundle audit executable
- */
- public String getBundleAuditPath() {
- return bundleAuditPath;
- }
-
/**
* Sets the path to the bundle audit executable.
*
@@ -1054,26 +867,6 @@ public void setBundleAuditWorkingDirectory(String bundleAuditWorkingDirectory) {
this.bundleAuditWorkingDirectory = bundleAuditWorkingDirectory;
}
- /**
- * Returns the path to the working directory that the bundle audit
- * executable should be executed from.
- *
- * @return the path to the working directory that the bundle audit
- * executable should be executed from.
- */
- public String getBundleAuditWorkingDirectory() {
- return bundleAuditWorkingDirectory;
- }
-
- /**
- * Returns if the cocoapods analyzer is enabled.
- *
- * @return if the cocoapods analyzer is enabled
- */
- public boolean isCocoapodsAnalyzerEnabled() {
- return cocoapodsAnalyzerEnabled;
- }
-
/**
* Sets whether or not the cocoapods analyzer is enabled.
*
@@ -1084,12 +877,12 @@ public void setCocoapodsAnalyzerEnabled(Boolean cocoapodsAnalyzerEnabled) {
}
/**
- * Returns whether or not the Swift package Analyzer is enabled.
+ * Sets whether or not the Carthage analyzer is enabled.
*
- * @return whether or not the Swift package Analyzer is enabled
+ * @param carthageAnalyzerEnabled the state of the Carthage analyzer
*/
- public Boolean isSwiftPackageManagerAnalyzerEnabled() {
- return swiftPackageManagerAnalyzerEnabled;
+ public void setCarthageAnalyzerEnabled(Boolean carthageAnalyzerEnabled) {
+ this.carthageAnalyzerEnabled = carthageAnalyzerEnabled;
}
/**
@@ -1102,15 +895,6 @@ public void setSwiftPackageManagerAnalyzerEnabled(Boolean swiftPackageManagerAna
this.swiftPackageManagerAnalyzerEnabled = swiftPackageManagerAnalyzerEnabled;
}
- /**
- * Returns whether or not the Swift package resolved Analyzer is enabled.
- *
- * @return whether or not the Swift package resolved Analyzer is enabled
- */
- public Boolean isSwiftPackageResolvedAnalyzerEnabled() {
- return swiftPackageResolvedAnalyzerEnabled;
- }
-
/**
* Sets the enabled state of the swift package manager analyzer.
*
@@ -1121,15 +905,6 @@ public void setSwiftPackageResolvedAnalyzerEnabled(Boolean swiftPackageResolvedA
this.swiftPackageResolvedAnalyzerEnabled = swiftPackageResolvedAnalyzerEnabled;
}
- /**
- * Get the value of opensslAnalyzerEnabled.
- *
- * @return the value of opensslAnalyzerEnabled
- */
- public Boolean isOpensslAnalyzerEnabled() {
- return opensslAnalyzerEnabled;
- }
-
/**
* Set the value of opensslAnalyzerEnabled.
*
@@ -1139,15 +914,6 @@ public void setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) {
this.opensslAnalyzerEnabled = opensslAnalyzerEnabled;
}
- /**
- * Get the value of nodeAnalyzerEnabled.
- *
- * @return the value of nodeAnalyzerEnabled
- */
- public Boolean isNodeAnalyzerEnabled() {
- return nodeAnalyzerEnabled;
- }
-
/**
* Set the value of nodeAnalyzerEnabled.
*
@@ -1157,15 +923,6 @@ public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) {
this.nodeAnalyzerEnabled = nodeAnalyzerEnabled;
}
- /**
- * Get the value of nodeAuditAnalyzerEnabled.
- *
- * @return the value of nodeAuditAnalyzerEnabled
- */
- public Boolean isNodeAuditAnalyzerEnabled() {
- return nodeAuditAnalyzerEnabled;
- }
-
/**
* Set the value of nodeAuditAnalyzerEnabled.
*
@@ -1175,15 +932,6 @@ public void setNodeAuditAnalyzerEnabled(Boolean nodeAuditAnalyzerEnabled) {
this.nodeAuditAnalyzerEnabled = nodeAuditAnalyzerEnabled;
}
- /**
- * Get the value of yarnAuditAnalyzerEnabled.
- *
- * @return the value of yarnAuditAnalyzerEnabled
- */
- public Boolean isYarnAuditAnalyzerEnabled() {
- return yarnAuditAnalyzerEnabled;
- }
-
/**
* Set the value of yarnAuditAnalyzerEnabled.
*
@@ -1193,15 +941,6 @@ public void setYarnAuditAnalyzerEnabled(Boolean yarnAuditAnalyzerEnabled) {
this.yarnAuditAnalyzerEnabled = yarnAuditAnalyzerEnabled;
}
- /**
- * Get the value of pnpmAuditAnalyzerEnabled.
- *
- * @return the value of pnpmAuditAnalyzerEnabled
- */
- public Boolean isPnpmAuditAnalyzerEnabled() {
- return pnpmAuditAnalyzerEnabled;
- }
-
/**
* Set the value of pnpmAuditAnalyzerEnabled.
*
@@ -1211,15 +950,6 @@ public void setPnpmAuditAnalyzerEnabled(Boolean pnpmAuditAnalyzerEnabled) {
this.pnpmAuditAnalyzerEnabled = pnpmAuditAnalyzerEnabled;
}
- /**
- * Get the value of nodeAuditAnalyzerUseCache.
- *
- * @return the value of nodeAuditAnalyzerUseCache
- */
- public Boolean isNodeAuditAnalyzerUseCache() {
- return nodeAuditAnalyzerUseCache;
- }
-
/**
* Set the value of nodeAuditAnalyzerUseCache.
*
@@ -1229,15 +959,6 @@ public void setNodeAuditAnalyzerUseCache(Boolean nodeAuditAnalyzerUseCache) {
this.nodeAuditAnalyzerUseCache = nodeAuditAnalyzerUseCache;
}
- /**
- * Get the value of nodePackageSkipDevDependencies.
- *
- * @return the value of nodePackageSkipDevDependencies
- */
- public Boolean isNodePackageAnalyzerSkipDevDependencies() {
- return nodePackageSkipDevDependencies;
- }
-
/**
* Set the value of nodePackageSkipDevDependencies.
*
@@ -1248,15 +969,6 @@ public void setNodePackageSkipDevDependencies(Boolean nodePackageSkipDevDependen
this.nodePackageSkipDevDependencies = nodePackageSkipDevDependencies;
}
- /**
- * Get the value of nodeAuditSkipDevDependencies.
- *
- * @return the value of nodeAuditSkipDevDependencies
- */
- public Boolean isNodeAuditAnalyzerSkipDevDependencies() {
- return nodeAuditSkipDevDependencies;
- }
-
/**
* Set the value of nodeAuditSkipDevDependencies.
*
@@ -1267,106 +979,6 @@ public void setNodeAuditSkipDevDependencies(Boolean nodeAuditSkipDevDependencies
this.nodeAuditSkipDevDependencies = nodeAuditSkipDevDependencies;
}
- /**
- * Get the value of retireJsAnalyzerEnabled.
- *
- * @return the value of retireJsAnalyzerEnabled
- */
- public Boolean isRetireJsAnalyzerEnabled() {
- return retireJsAnalyzerEnabled;
- }
-
- /**
- * Set the value of retireJsAnalyzerEnabled.
- *
- * @param retireJsAnalyzerEnabled new value of retireJsAnalyzerEnabled
- */
- public void setRetireJsAnalyzerEnabled(Boolean retireJsAnalyzerEnabled) {
- this.retireJsAnalyzerEnabled = retireJsAnalyzerEnabled;
- }
-
- /**
- * Get the value of Retire JS repository URL.
- *
- * @return the value of retireJsUrl
- */
- public String getRetireJsUrl() {
- return retireJsUrl;
- }
-
- /**
- * Set the value of the Retire JS repository URL.
- *
- * @param retireJsUrl new value of retireJsUrl
- */
- public void setRetireJsUrl(String retireJsUrl) {
- this.retireJsUrl = retireJsUrl;
- }
-
- /**
- * Get the value of User Retire JS repository URL.
- *
- * @return the value of retireJsUrlUser
- */
- public String getRetireJsUrlUser() {
- return retireJsUrlUser;
- }
-
- /**
- * Set the value of the User Retire JS repository URL.
- *
- * @param retireJsUrlUser new value of retireJsUrlUser
- */
- public void setRetireJsUrlUser(String retireJsUrlUser) {
- this.retireJsUrlUser = retireJsUrlUser;
- }
-
- /**
- * Get the value of Password Retire JS repository URL.
- *
- * @return the value of retireJsUrlPassword
- */
- public String getRetireJsUrlPassword() {
- return retireJsUrlPassword;
- }
-
- /**
- * Set the value of the Password Retire JS repository URL.
- *
- * @param retireJsUrlPassword new value of retireJsUrlPassword
- */
- public void setRetireJsUrlPassword(String retireJsUrlPassword) {
- this.retireJsUrlPassword = retireJsUrlPassword;
- }
-
- /**
- * Get the value of retireJsAnalyzerEnabled.
- *
- * @return the value of retireJsAnalyzerEnabled
- */
- public Boolean isRetireJsAnalyzerForceUpdate() {
- return retireJsAnalyzerForceUpdate;
- }
-
- /**
- * Set the value of retireJsAnalyzerForceUpdate.
- *
- * @param retireJsAnalyzerForceUpdate new value of
- * retireJsAnalyzerForceUpdate
- */
- public void setRetireJsAnalyzerForceUpdate(Boolean retireJsAnalyzerForceUpdate) {
- this.retireJsAnalyzerForceUpdate = retireJsAnalyzerForceUpdate;
- }
-
- /**
- * Get the value of retirejsFilterNonVulnerable.
- *
- * @return the value of retirejsFilterNonVulnerable
- */
- public Boolean isRetirejsFilterNonVulnerable() {
- return retirejsFilterNonVulnerable;
- }
-
/**
* Set the value of retirejsFilterNonVulnerable.
*
@@ -1377,15 +989,6 @@ public void setRetirejsFilterNonVulnerable(Boolean retirejsFilterNonVulnerable)
this.retirejsFilterNonVulnerable = retirejsFilterNonVulnerable;
}
- /**
- * Gets retire JS Analyzers file content filters.
- *
- * @return retire JS Analyzers file content filters
- */
- public List getRetirejsFilters() {
- return retirejsFilters;
- }
-
/**
* Add a regular expression to the set of retire JS content filters.
*
@@ -1398,15 +1001,6 @@ public void addConfiguredRetirejsFilter(final RetirejsFilter retirejsFilter) {
retirejsFilters.add(retirejsFilter.getRegex());
}
- /**
- * Get the value of rubygemsAnalyzerEnabled.
- *
- * @return the value of rubygemsAnalyzerEnabled
- */
- public Boolean isRubygemsAnalyzerEnabled() {
- return rubygemsAnalyzerEnabled;
- }
-
/**
* Set the value of rubygemsAnalyzerEnabled.
*
@@ -1416,15 +1010,6 @@ public void setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) {
this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled;
}
- /**
- * Get the value of pyPackageAnalyzerEnabled.
- *
- * @return the value of pyPackageAnalyzerEnabled
- */
- public Boolean isPyPackageAnalyzerEnabled() {
- return pyPackageAnalyzerEnabled;
- }
-
/**
* Set the value of pyPackageAnalyzerEnabled.
*
@@ -1434,15 +1019,6 @@ public void setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) {
this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled;
}
- /**
- * Get the value of pyDistributionAnalyzerEnabled.
- *
- * @return the value of pyDistributionAnalyzerEnabled
- */
- public Boolean isPyDistributionAnalyzerEnabled() {
- return pyDistributionAnalyzerEnabled;
- }
-
/**
* Set the value of pyDistributionAnalyzerEnabled.
*
@@ -1453,15 +1029,6 @@ public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabl
this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled;
}
- /**
- * Get the value of mixAuditAnalyzerEnabled.
- *
- * @return the value of mixAuditAnalyzerEnabled
- */
- public Boolean getMixAuditAnalyzerEnabled() {
- return mixAuditAnalyzerEnabled;
- }
-
/**
* Set the value of mixAuditAnalyzerEnabled.
*
@@ -1472,14 +1039,13 @@ public void setMixAuditAnalyzerEnabled(Boolean mixAuditAnalyzerEnabled) {
}
/**
- * Get the value of centralAnalyzerEnabled.
+ * Sets the path to the mix audit executable.
*
- * @return the value of centralAnalyzerEnabled
+ * @param mixAuditPath the path to the bundle audit executable
*/
- public Boolean isCentralAnalyzerEnabled() {
- return centralAnalyzerEnabled;
+ public void setMixAuditPath(String mixAuditPath) {
+ this.mixAuditPath = mixAuditPath;
}
-
/**
* Set the value of centralAnalyzerEnabled.
*
@@ -1489,15 +1055,6 @@ public void setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) {
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
}
- /**
- * Get the value of centralAnalyzerUseCache.
- *
- * @return the value of centralAnalyzerUseCache
- */
- public Boolean isCentralAnalyzerUseCache() {
- return centralAnalyzerUseCache;
- }
-
/**
* Set the value of centralAnalyzerUseCache.
*
@@ -1507,15 +1064,6 @@ public void setCentralAnalyzerUseCache(Boolean centralAnalyzerUseCache) {
this.centralAnalyzerUseCache = centralAnalyzerUseCache;
}
- /**
- * Get the value of nexusAnalyzerEnabled.
- *
- * @return the value of nexusAnalyzerEnabled
- */
- public Boolean isNexusAnalyzerEnabled() {
- return nexusAnalyzerEnabled;
- }
-
/**
* Set the value of nexusAnalyzerEnabled.
*
@@ -1525,15 +1073,6 @@ public void setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) {
this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
}
- /**
- * Get the value of golangDepEnabled.
- *
- * @return the value of golangDepEnabled
- */
- public Boolean isGolangDepEnabled() {
- return golangDepEnabled;
- }
-
/**
* Set the value of golangDepEnabled.
*
@@ -1543,15 +1082,6 @@ public void setGolangDepEnabled(Boolean golangDepEnabled) {
this.golangDepEnabled = golangDepEnabled;
}
- /**
- * Get the value of golangModEnabled.
- *
- * @return the value of golangModEnabled
- */
- public Boolean isGoModDepEnabled() {
- return golangModEnabled;
- }
-
/**
* Set the value of golangModEnabled.
*
@@ -1561,15 +1091,6 @@ public void setGolangModEnabled(Boolean golangModEnabled) {
this.golangModEnabled = golangModEnabled;
}
- /**
- * Get the value of dartAnalyzerEnabled.
- *
- * @return the value of dartAnalyzerEnabled
- */
- public Boolean isDartAnalyzerEnabled() {
- return dartAnalyzerEnabled;
- }
-
/**
* Set the value of dartAnalyzerEnabled.
*
@@ -1579,15 +1100,6 @@ public void setDartAnalyzerEnabled(Boolean dartAnalyzerEnabled) {
this.dartAnalyzerEnabled = dartAnalyzerEnabled;
}
- /**
- * Get the value of pathToYarn.
- *
- * @return the value of pathToYarn
- */
- public String getPathToYarn() {
- return pathToYarn;
- }
-
/**
* Set the value of pathToYarn.
*
@@ -1597,15 +1109,6 @@ public void setPathToYarn(String pathToYarn) {
this.pathToYarn = pathToYarn;
}
- /**
- * Get the value of pathToPnpm.
- *
- * @return the value of pathToPnpm
- */
- public String getPathToPnpm() {
- return pathToPnpm;
- }
-
/**
* Set the value of pathToPnpm.
*
@@ -1615,15 +1118,6 @@ public void setPathToPnpm(String pathToPnpm) {
this.pathToPnpm = pathToPnpm;
}
- /**
- * Get the value of pathToCore.
- *
- * @return the value of pathToCore
- */
- public String getPathToGo() {
- return pathToGo;
- }
-
/**
* Set the value of pathToGo.
*
@@ -1633,15 +1127,6 @@ public void setPathToGo(String pathToGo) {
this.pathToGo = pathToGo;
}
- /**
- * Get the value of nexusUrl.
- *
- * @return the value of nexusUrl
- */
- public String getNexusUrl() {
- return nexusUrl;
- }
-
/**
* Set the value of nexusUrl.
*
@@ -1651,15 +1136,6 @@ public void setNexusUrl(String nexusUrl) {
this.nexusUrl = nexusUrl;
}
- /**
- * Get the value of nexusUser.
- *
- * @return the value of nexusUser
- */
- public String getNexusUser() {
- return nexusUser;
- }
-
/**
* Set the value of nexusUser.
*
@@ -1669,15 +1145,6 @@ public void setNexusUser(String nexusUser) {
this.nexusUser = nexusUser;
}
- /**
- * Get the value of nexusPassword.
- *
- * @return the value of nexusPassword
- */
- public String getNexusPassword() {
- return nexusPassword;
- }
-
/**
* Set the value of nexusPassword.
*
@@ -1687,15 +1154,6 @@ public void setNexusPassword(String nexusPassword) {
this.nexusPassword = nexusPassword;
}
- /**
- * Get the value of nexusUsesProxy.
- *
- * @return the value of nexusUsesProxy
- */
- public Boolean isNexusUsesProxy() {
- return nexusUsesProxy;
- }
-
/**
* Set the value of nexusUsesProxy.
*
@@ -1705,15 +1163,6 @@ public void setNexusUsesProxy(Boolean nexusUsesProxy) {
this.nexusUsesProxy = nexusUsesProxy;
}
- /**
- * Get the value of zipExtensions.
- *
- * @return the value of zipExtensions
- */
- public String getZipExtensions() {
- return zipExtensions;
- }
-
/**
* Set the value of zipExtensions.
*
@@ -1723,15 +1172,6 @@ public void setZipExtensions(String zipExtensions) {
this.zipExtensions = zipExtensions;
}
- /**
- * Get the value of pathToCore.
- *
- * @return the value of pathToCore
- */
- public String getPathToDotnetCore() {
- return pathToCore;
- }
-
/**
* Set the value of pathToCore.
*
@@ -1741,15 +1181,6 @@ public void setPathToDotnetCore(String pathToCore) {
this.pathToCore = pathToCore;
}
- /**
- * Get value of {@link #ossindexAnalyzerEnabled}.
- *
- * @return the value of ossindexAnalyzerEnabled
- */
- public Boolean isOssindexAnalyzerEnabled() {
- return ossindexAnalyzerEnabled;
- }
-
/**
* Set value of {@link #ossindexAnalyzerEnabled}.
*
@@ -1759,15 +1190,6 @@ public void setOssindexAnalyzerEnabled(Boolean ossindexAnalyzerEnabled) {
this.ossindexAnalyzerEnabled = ossindexAnalyzerEnabled;
}
- /**
- * Get value of {@link #ossindexAnalyzerUseCache}.
- *
- * @return the value of ossindexAnalyzerUseCache
- */
- public Boolean isOssindexAnalyzerUseCache() {
- return ossindexAnalyzerUseCache;
- }
-
/**
* Set value of {@link #ossindexAnalyzerUseCache}.
*
@@ -1777,15 +1199,6 @@ public void setOssindexAnalyzerUseCache(Boolean ossindexAnalyzerUseCache) {
this.ossindexAnalyzerUseCache = ossindexAnalyzerUseCache;
}
- /**
- * Get value of {@link #ossindexAnalyzerUrl}.
- *
- * @return the value of ossindexAnalyzerUrl
- */
- public String getOssindexAnalyzerUrl() {
- return ossindexAnalyzerUrl;
- }
-
/**
* Set value of {@link #ossindexAnalyzerUrl}.
*
@@ -1795,15 +1208,6 @@ public void setOssindexAnalyzerUrl(String ossindexAnalyzerUrl) {
this.ossindexAnalyzerUrl = ossindexAnalyzerUrl;
}
- /**
- * Get value of {@link #ossindexAnalyzerUsername}.
- *
- * @return the value of ossindexAnalyzerUsername
- */
- public String getOssindexAnalyzerUsername() {
- return ossindexAnalyzerUsername;
- }
-
/**
* Set value of {@link #ossindexAnalyzerUsername}.
*
@@ -1813,15 +1217,6 @@ public void setOssindexAnalyzerUsername(String ossindexAnalyzerUsername) {
this.ossindexAnalyzerUsername = ossindexAnalyzerUsername;
}
- /**
- * Get value of {@link #ossindexAnalyzerPassword}.
- *
- * @return the value of ossindexAnalyzerPassword
- */
- public String getOssindexAnalyzerPassword() {
- return ossindexAnalyzerPassword;
- }
-
/**
* Set value of {@link #ossindexAnalyzerPassword}.
*
@@ -1831,15 +1226,6 @@ public void setOssindexAnalyzerPassword(String ossindexAnalyzerPassword) {
this.ossindexAnalyzerPassword = ossindexAnalyzerPassword;
}
- /**
- * Get value of {@link #ossIndexAnalyzerWarnOnlyOnRemoteErrors}.
- *
- * @return the value of ossIndexWarnOnlyOnRemoteErrors
- */
- public Boolean getOssIndexWarnOnlyOnRemoteErrors() {
- return ossIndexAnalyzerWarnOnlyOnRemoteErrors;
- }
-
/**
* Set value of {@link #ossIndexAnalyzerWarnOnlyOnRemoteErrors}.
*
@@ -1850,15 +1236,6 @@ public void setOssIndexWarnOnlyOnRemoteErrors(Boolean ossIndexWarnOnlyOnRemoteEr
this.ossIndexAnalyzerWarnOnlyOnRemoteErrors = ossIndexWarnOnlyOnRemoteErrors;
}
- /**
- * Get the value of cmakeAnalyzerEnabled.
- *
- * @return the value of cmakeAnalyzerEnabled
- */
- public Boolean isCmakeAnalyzerEnabled() {
- return cmakeAnalyzerEnabled;
- }
-
/**
* Set the value of cmakeAnalyzerEnabled.
*
@@ -1868,15 +1245,6 @@ public void setCmakeAnalyzerEnabled(Boolean cmakeAnalyzerEnabled) {
this.cmakeAnalyzerEnabled = cmakeAnalyzerEnabled;
}
- /**
- * Returns the value of artifactoryAnalyzerEnabled.
- *
- * @return the value of artifactoryAnalyzerEnabled
- */
- public Boolean getArtifactoryAnalyzerEnabled() {
- return artifactoryAnalyzerEnabled;
- }
-
/**
* Set the value of artifactoryAnalyzerEnabled.
*
@@ -1886,15 +1254,6 @@ public void setArtifactoryAnalyzerEnabled(Boolean artifactoryAnalyzerEnabled) {
this.artifactoryAnalyzerEnabled = artifactoryAnalyzerEnabled;
}
- /**
- * Returns the value of artifactoryAnalyzerUrl.
- *
- * @return the value of artifactoryAnalyzerUrl
- */
- public String getArtifactoryAnalyzerUrl() {
- return artifactoryAnalyzerUrl;
- }
-
/**
* Set the value of artifactoryAnalyzerUrl.
*
@@ -1904,15 +1263,6 @@ public void setArtifactoryAnalyzerUrl(String artifactoryAnalyzerUrl) {
this.artifactoryAnalyzerUrl = artifactoryAnalyzerUrl;
}
- /**
- * Returns the value of artifactoryAnalyzerUseProxy.
- *
- * @return the value of artifactoryAnalyzerUseProxy
- */
- public Boolean getArtifactoryAnalyzerUseProxy() {
- return artifactoryAnalyzerUseProxy;
- }
-
/**
* Set the value of artifactoryAnalyzerUseProxy.
*
@@ -1923,15 +1273,6 @@ public void setArtifactoryAnalyzerUseProxy(Boolean artifactoryAnalyzerUseProxy)
this.artifactoryAnalyzerUseProxy = artifactoryAnalyzerUseProxy;
}
- /**
- * Returns the value of artifactoryAnalyzerParallelAnalysis.
- *
- * @return the value of artifactoryAnalyzerParallelAnalysis
- */
- public Boolean getArtifactoryAnalyzerParallelAnalysis() {
- return artifactoryAnalyzerParallelAnalysis;
- }
-
/**
* Set the value of artifactoryAnalyzerParallelAnalysis.
*
@@ -1942,15 +1283,6 @@ public void setArtifactoryAnalyzerParallelAnalysis(Boolean artifactoryAnalyzerPa
this.artifactoryAnalyzerParallelAnalysis = artifactoryAnalyzerParallelAnalysis;
}
- /**
- * Returns the value of artifactoryAnalyzerUsername.
- *
- * @return the value of artifactoryAnalyzerUsername
- */
- public String getArtifactoryAnalyzerUsername() {
- return artifactoryAnalyzerUsername;
- }
-
/**
* Set the value of artifactoryAnalyzerUsername.
*
@@ -1961,15 +1293,6 @@ public void setArtifactoryAnalyzerUsername(String artifactoryAnalyzerUsername) {
this.artifactoryAnalyzerUsername = artifactoryAnalyzerUsername;
}
- /**
- * Returns the value of artifactoryAnalyzerApiToken.
- *
- * @return the value of artifactoryAnalyzerApiToken
- */
- public String getArtifactoryAnalyzerApiToken() {
- return artifactoryAnalyzerApiToken;
- }
-
/**
* Set the value of artifactoryAnalyzerApiToken.
*
@@ -1980,15 +1303,6 @@ public void setArtifactoryAnalyzerApiToken(String artifactoryAnalyzerApiToken) {
this.artifactoryAnalyzerApiToken = artifactoryAnalyzerApiToken;
}
- /**
- * Returns the value of artifactoryAnalyzerBearerToken.
- *
- * @return the value of artifactoryAnalyzerBearerToken
- */
- public String getArtifactoryAnalyzerBearerToken() {
- return artifactoryAnalyzerBearerToken;
- }
-
/**
* Set the value of artifactoryAnalyzerBearerToken.
*
@@ -1999,6 +1313,16 @@ public void setArtifactoryAnalyzerBearerToken(String artifactoryAnalyzerBearerTo
this.artifactoryAnalyzerBearerToken = artifactoryAnalyzerBearerToken;
}
+ /**
+ * Set the value of failBuildOnUnusedSuppressionRule.
+ *
+ * @param failBuildOnUnusedSuppressionRule new value of
+ * failBuildOnUnusedSuppressionRule
+ */
+ public void setFailBuildOnUnusedSuppressionRule(boolean failBuildOnUnusedSuppressionRule) {
+ this.failBuildOnUnusedSuppressionRule = failBuildOnUnusedSuppressionRule;
+ }
+
//see note on `dealWithReferences()` for information on this suppression
@SuppressWarnings("squid:RedundantThrowsDeclarationCheck")
@Override
@@ -2006,6 +1330,11 @@ protected void executeWithContextClassloader() throws BuildException {
dealWithReferences();
validateConfiguration();
populateSettings();
+ try {
+ Downloader.getInstance().configure(getSettings());
+ } catch (InvalidSettingException e) {
+ throw new BuildException(e);
+ }
try (Engine engine = new Engine(Check.class.getClassLoader(), getSettings())) {
for (Resource resource : getPath()) {
final FileProvider provider = resource.as(FileProvider.class);
@@ -2100,6 +1429,10 @@ protected void populateSettings() throws BuildException {
super.populateSettings();
getSettings().setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
getSettings().setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFiles);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_USER, suppressionFileUser);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_PASSWORD, suppressionFilePassword);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_BEARER_TOKEN, suppressionFileBearerToken);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, versionCheckEnabled);
getSettings().setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
getSettings().setBooleanIfNotNull(Settings.KEYS.PRETTY_PRINT, prettyPrint);
@@ -2122,6 +1455,7 @@ protected void populateSettings() throws BuildException {
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED, swiftPackageManagerAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_RESOLVED_ENABLED, swiftPackageResolvedAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED, cocoapodsAnalyzerEnabled);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_CARTHAGE_ENABLED, carthageAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, bundleAuditAnalyzerEnabled);
getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, bundleAuditPath);
getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_WORKING_DIRECTORY, bundleAuditWorkingDirectory);
@@ -2131,6 +1465,7 @@ protected void populateSettings() throws BuildException {
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIPFILE_ENABLED, pipfileAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_POETRY_ENABLED, poetryAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_SKIP_DEV, composerAnalyzerSkipDev);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_CPANFILE_ENABLED, cpanfileAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_SKIPDEV, nodePackageSkipDevDependencies);
@@ -2139,11 +1474,6 @@ protected void populateSettings() throws BuildException {
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_PNPM_AUDIT_ENABLED, pnpmAuditAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_USE_CACHE, nodeAuditAnalyzerUseCache);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV, nodeAuditSkipDevDependencies);
- getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_ENABLED, retireJsAnalyzerEnabled);
- getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_URL, retireJsUrl);
- getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_USER, retireJsUrlUser);
- getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_PASSWORD, retireJsUrlPassword);
- getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FORCEUPDATE, retireJsAnalyzerForceUpdate);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FILTER_NON_VULNERABLE, retirejsFilterNonVulnerable);
getSettings().setArrayIfNotEmpty(Settings.KEYS.ANALYZER_RETIREJS_FILTERS, retirejsFilters);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_GOLANG_DEP_ENABLED, golangDepEnabled);
@@ -2156,12 +1486,11 @@ protected void populateSettings() throws BuildException {
getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_MIX_AUDIT_PATH, mixAuditPath);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUGETCONF_ENABLED, nugetconfAnalyzerEnabled);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_LIBMAN_ENABLED, libmanAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_USE_CACHE, centralAnalyzerUseCache);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
- getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED, knownExploitedEnabled);
- getSettings().setStringIfNotEmpty(Settings.KEYS.KEV_URL, knownExploitedUrl);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED, msbuildAnalyzerEnabled);
getSettings().setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
@@ -2177,6 +1506,7 @@ protected void populateSettings() throws BuildException {
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_USE_CACHE, ossindexAnalyzerUseCache);
getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, ossIndexAnalyzerWarnOnlyOnRemoteErrors);
getSettings().setFloat(Settings.KEYS.JUNIT_FAIL_ON_CVSS, junitFailOnCVSS);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.FAIL_ON_UNUSED_SUPPRESSION_RULE, failBuildOnUnusedSuppressionRule);
}
/**
@@ -2194,15 +1524,31 @@ private void checkForFailure(Dependency[] dependencies) throws BuildException {
for (Dependency d : dependencies) {
boolean addName = true;
for (Vulnerability v : d.getVulnerabilities()) {
- if ((v.getCvssV2() != null && v.getCvssV2().getScore() >= failBuildOnCVSS)
- || (v.getCvssV3() != null && v.getCvssV3().getBaseScore() >= failBuildOnCVSS)
- || (v.getUnscoredSeverity() != null && SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) >= failBuildOnCVSS)
+ final double cvssV2 = v.getCvssV2() != null && v.getCvssV2().getCvssData() != null
+ && v.getCvssV2().getCvssData().getBaseScore() != null ? v.getCvssV2().getCvssData().getBaseScore() : -1;
+ final double cvssV3 = v.getCvssV3() != null && v.getCvssV3().getCvssData() != null
+ && v.getCvssV3().getCvssData().getBaseScore() != null ? v.getCvssV3().getCvssData().getBaseScore() : -1;
+ final double cvssV4 = v.getCvssV4() != null && v.getCvssV4().getCvssData() != null
+ && v.getCvssV4().getCvssData().getBaseScore() != null ? v.getCvssV4().getCvssData().getBaseScore() : -1;
+ final boolean useUnscored = cvssV2 == -1 && cvssV3 == -1 && cvssV4 == -1;
+ final double unscoredCvss =
+ useUnscored && v.getUnscoredSeverity() != null ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
+
+ if (cvssV2 >= failBuildOnCVSS
+ || cvssV3 >= failBuildOnCVSS
+ || cvssV4 >= failBuildOnCVSS
+ || unscoredCvss >= failBuildOnCVSS
//safety net to fail on any if for some reason the above misses on 0
- || (failBuildOnCVSS <= 0.0f)) {
+ || failBuildOnCVSS <= 0.0f
+ ) {
if (addName) {
addName = false;
- ids.append(NEW_LINE).append(d.getFileName()).append(": ");
- ids.append(v.getName());
+ ids.append(NEW_LINE).append(d.getFileName()).append(" (")
+ .append(Stream.concat(d.getSoftwareIdentifiers().stream(), d.getVulnerableSoftwareIdentifiers().stream())
+ .map(Identifier::getValue)
+ .collect(Collectors.joining(", ")))
+ .append("): ")
+ .append(v.getName());
} else {
ids.append(", ").append(v.getName());
}
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
index b8c902d3861..58cfddf8d44 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
@@ -17,21 +17,18 @@
*/
package org.owasp.dependencycheck.taskdefs;
+import io.github.jeremylong.jcs3.slf4j.Slf4jAdapter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import org.apache.commons.jcs.JCS;
-import org.apache.commons.jcs.access.CacheAccess;
-import org.apache.commons.jcs.engine.CompositeCacheAttributes;
-import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.owasp.dependencycheck.Engine;
-import org.owasp.dependencycheck.data.cache.DataCache;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.xml.pom.Model;
import org.slf4j.impl.StaticLoggerBinder;
/**
@@ -60,11 +57,6 @@ public class Purge extends Task {
*/
private boolean failOnError = true;
- /**
- * The URL to hosted suppressions file with base FP suppressions.
- */
- private String hostedSuppressionsUrl = null;
-
/**
* Construct a new DependencyCheckTask.
*/
@@ -80,15 +72,6 @@ public Settings getSettings() {
return settings;
}
- /**
- * Get the value of dataDirectory.
- *
- * @return the value of dataDirectory
- */
- public String getDataDirectory() {
- return dataDirectory;
- }
-
/**
* Set the value of dataDirectory.
*
@@ -117,34 +100,21 @@ public void setFailOnError(boolean failOnError) {
}
/**
- * Get the value of hostedSuppressionsUrl.
- *
- * @return the value of hostedSuppressionsUrl
- */
- public String getHostedSuppressionsUrl() {
- return hostedSuppressionsUrl;
- }
-
- /**
- * Set the value of hostedSuppressionsUrl.
+ * Sets the
+ * {@link Thread#getContextClassLoader() Thread Context Class Loader} to the
+ * one for this class, and then calls
+ * {@link #executeWithContextClassloader()}. This is done because the JCS
+ * cache needs to have the Thread Context Class Loader set to something that
+ * can resolve it's classes. Other build tools do this by default but Ant
+ * does not.
*
- * @param hostedSuppressionsUrl new value of hostedSuppressionsUrl
- */
- public void setHostedSuppressionsUrl(final String hostedSuppressionsUrl) {
- this.hostedSuppressionsUrl = hostedSuppressionsUrl;
- }
-
- /**
- * Sets the {@link Thread#getContextClassLoader() Thread Context Class Loader} to the one for this class,
- * and then calls {@link #executeWithContextClassloader()}. This is done because the JCS cache needs to have
- * the Thread Context Class Loader set to something that can resolve it's classes. Other build tools do this
- * by default but Ant does not.
- *
- * @throws BuildException throws if there is a problem. See {@link #executeWithContextClassloader()} for details
+ * @throws BuildException throws if there is a problem. See
+ * {@link #executeWithContextClassloader()} for details
*/
@Override
public final void execute() throws BuildException {
- ClassLoader current = Thread.currentThread().getContextClassLoader();
+ muteNoisyLoggers();
+ final ClassLoader current = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
@@ -154,6 +124,21 @@ public final void execute() throws BuildException {
}
}
+ /**
+ * Hacky method of muting the noisy logging from JCS.
+ */
+ private void muteNoisyLoggers() {
+ System.setProperty("jcs.logSystem", "slf4j");
+ Slf4jAdapter.muteLogging(true);
+
+ final String[] noisyLoggers = {
+ "org.apache.hc"
+ };
+ for (String loggerName : noisyLoggers) {
+ System.setProperty("org.slf4j.simpleLogger.log." + loggerName, "error");
+ }
+ }
+
/**
* Executes the dependency-check purge to delete the existing local copy of
* the NVD CVE data.
@@ -164,6 +149,11 @@ public final void execute() throws BuildException {
@SuppressWarnings("squid:RedundantThrowsDeclarationCheck")
protected void executeWithContextClassloader() throws BuildException {
populateSettings();
+ try {
+ Downloader.getInstance().configure(settings);
+ } catch (InvalidSettingException e) {
+ throw new BuildException(e);
+ }
try (Engine engine = new Engine(Engine.Mode.EVIDENCE_PROCESSING, getSettings())) {
engine.purge();
} finally {
@@ -191,7 +181,6 @@ protected void populateSettings() throws BuildException {
}
log(msg, ex, Project.MSG_WARN);
}
- settings.setStringIfNotEmpty(Settings.KEYS.HOSTED_SUPPRESSIONS_URL, hostedSuppressionsUrl);
if (dataDirectory != null) {
settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
} else {
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
index 3cf35c381a8..1cac8153188 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Update.java
@@ -17,14 +17,13 @@
*/
package org.owasp.dependencycheck.taskdefs;
-import java.util.Optional;
-
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
-import org.owasp.dependencycheck.utils.CveUrlParser;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.impl.StaticLoggerBinder;
@@ -40,6 +39,93 @@
@SuppressWarnings("common-java:DuplicatedBlocks")
public class Update extends Purge {
+ /**
+ * The URL to (a mirror of) the RetireJS JSON data.
+ */
+ private String retireJsUrl;
+ /**
+ * The user to download the RetireJS JSON data from an HTTP Basic auth protected location.
+ */
+ private String retireJsUrlUser;
+ /**
+ * The password to download the RetireJS JSON data from an HTTP Basic auth protected location.
+ */
+ private String retireJsUrlPassword;
+ /**
+ * The token to download the RetireJS JSON data from an HTTP Bearer auth protected location.
+ */
+ private String retireJsUrlBearerToken;
+ /**
+ * Whether or not the RetireJS JSON repository will be updated regardless of the
+ * `autoupdate` settings. Defaults to false.
+ */
+ private Boolean retireJsForceUpdate;
+ /**
+ * Whether or not the Known Exploited Vulnerability Analyzer is enabled.
+ */
+ private Boolean knownExploitedEnabled;
+ /**
+ * The URL to the known exploited vulnerabilities JSON datafeed.
+ */
+ private String knownExploitedUrl;
+ /**
+ * The number of hours before checking for updates for the known exploited vulnerabilities JSON datafeed.
+ */
+ private Integer knownExploitedValidForHours;
+ /**
+ * The user to download the known exploited vulnerabilities JSON datafeed from an HTTP Basic auth protected location.
+ */
+ private String knownExploitedUser;
+ /**
+ * The password to download the known exploited vulnerabilities JSON datafeed from an HTTP Basic auth protected location.
+ */
+ private String knownExploitedPassword;
+ /**
+ * The token to download the known exploited vulnerabilities JSON datafeed from an HTTP Bearer auth protected location.
+ */
+ private String knownExploitedBearerToken;
+ /**
+ * The NVD API endpoint.
+ */
+ private String nvdApiEndpoint;
+ /**
+ * The NVD API Key.
+ */
+ private String nvdApiKey;
+ /**
+ * The maximum number of retry requests for a single call to the NVD API.
+ */
+ private Integer nvdMaxRetryCount;
+ /**
+ * The number of hours to wait before checking for new updates from the NVD.
+ */
+ private Integer nvdValidForHours;
+ /**
+ * The NVD API Data Feed URL.
+ */
+ private String nvdDatafeedUrl;
+ /**
+ * The username to download the NVD Data feed from an HTTP Basic auth protected location.
+ */
+ private String nvdUser;
+ /**
+ * The password to download the NVD Data feed from an HTTP Basic auth protected location.
+ */
+ private String nvdPassword;
+ /**
+ * The token to download the NVD Data feed from an HTTP Bearer auth protected location.
+ */
+ private String nvdBearerToken;
+ /**
+ * The time in milliseconds to wait between downloading NVD API data.
+ */
+ private Integer nvdApiDelay;
+
+ /**
+ * The number of records per page of NVD API data.
+ */
+ private Integer nvdApiResultsPerPage;
+
/**
* The Proxy Server.
*/
@@ -89,38 +175,45 @@ public class Update extends Purge {
*/
private String databasePassword;
/**
- * The URL for the modified NVD CVE JSON file.
- */
- private String cveUrlModified;
- /**
- * Base Data Mirror URL for CVE JSON files.
+ * The number of hours to wait before re-checking hosted suppressions file
+ * for updates.
*/
- private String cveUrlBase;
+ private Integer hostedSuppressionsValidForHours;
/**
- * The wait time in milliseconds between downloads from the NVD.
+ * The userid for the hostedSuppressions file.
+ *
+ * Only needs configuration if you customized the hostedSuppressionsUrl to a custom server that requires Basic Auth
*/
- private String cveWaitTime;
+ private String hostedSuppressionsUser;
/**
- * The number of hours to wait before re-checking for updates.
+ * The password for the hostedSuppressions file.
+ *
+ * Only needs configuration if you customized the hostedSuppressionsUrl to a custom server that requires Basic Auth
*/
- private Integer cveValidForHours;
+ private String hostedSuppressionsPassword;
/**
- * The number of hours to wait before re-checking hosted suppressions file for updates.
+ * The (Bearer authentication) API Token for the hostedSuppressions file.
+ *
+ * Only needs configuration if you customized the hostedSuppressionsUrl to a custom server that requires Bearer Auth
*/
- private Integer hostedSuppressionsValidForHours;
+ private String hostedSuppressionsBearerToken;
/**
- * Whether the hosted suppressions file will be updated regardless of the `autoupdate` settings. Defaults to false.
+ * Whether the hosted suppressions file will be updated regardless of the
+ * `autoupdate` settings. Defaults to false.
*/
private Boolean hostedSuppressionsForceUpdate;
/**
* Whether the hosted suppressions file will be used. Defaults to true.
*/
private Boolean hostedSuppressionsEnabled;
-
/**
- * Specify the first year of NVD CVE data to download; default is 2002.
+ * The URL to hosted suppressions file with base FP suppressions.
*/
- private Integer cveStartYear;
+ private String hostedSuppressionsUrl = null;
+ /**
+ * Whether or not the RetireJS Analyzer is enabled.
+ */
+ private Boolean retireJsAnalyzerEnabled;
/**
* Construct a new UpdateTask.
@@ -133,174 +226,181 @@ public Update() {
}
/**
- * Get the value of proxyServer.
+ * Set the value of nvdApiEndpoint.
*
- * @return the value of proxyServer
+ * @param nvdApiEndpoint new value of nvdApiEndpoint
*/
- public String getProxyServer() {
- return proxyServer;
+ public void setNvdApiEndpoint(String nvdApiEndpoint) {
+ this.nvdApiEndpoint = nvdApiEndpoint;
}
/**
- * Set the value of proxyServer.
+ * Set the value of nvdApiKey.
*
- * @param server new value of proxyServer
+ * @param nvdApiKey new value of nvdApiKey
*/
- public void setProxyServer(String server) {
- this.proxyServer = server;
+ public void setNvdApiKey(String nvdApiKey) {
+ this.nvdApiKey = nvdApiKey;
}
/**
- * Get the value of proxyPort.
+ * Set the value of nvdMaxRetryCount.
*
- * @return the value of proxyPort
+ * @param nvdMaxRetryCount new value of nvdMaxRetryCount
*/
- public String getProxyPort() {
- return proxyPort;
+ public void setNvdMaxRetryCount(Integer nvdMaxRetryCount) {
+ if (nvdMaxRetryCount > 0) {
+ this.nvdMaxRetryCount = nvdMaxRetryCount;
+ } else {
+ throw new BuildException("Invalid setting: `nvdMaxRetryCount` must be greater than zero");
+ }
}
/**
- * Set the value of proxyPort.
+ * Set the value of nvdValidForHours.
*
- * @param proxyPort new value of proxyPort
+ * @param nvdValidForHours new value of nvdValidForHours
*/
- public void setProxyPort(String proxyPort) {
- this.proxyPort = proxyPort;
+ public void setNvdValidForHours(int nvdValidForHours) {
+ if (nvdValidForHours >= 0) {
+ this.nvdValidForHours = nvdValidForHours;
+ } else {
+ throw new BuildException("Invalid setting: `nvdValidForHours` must be 0 or greater");
+ }
}
/**
- * Get the value of proxyUsername.
+ * Set the value of nvdDatafeedUrl.
*
- * @return the value of proxyUsername
+ * @param nvdDatafeedUrl new value of nvdDatafeedUrl
*/
- public String getProxyUsername() {
- return proxyUsername;
+ public void setNvdDatafeedUrl(String nvdDatafeedUrl) {
+ this.nvdDatafeedUrl = nvdDatafeedUrl;
}
/**
- * Set the value of proxyUsername.
+ * Set the value of nvdUser.
*
- * @param proxyUsername new value of proxyUsername
+ * @param nvdUser new value of nvdUser
*/
- public void setProxyUsername(String proxyUsername) {
- this.proxyUsername = proxyUsername;
+ public void setNvdUser(String nvdUser) {
+ this.nvdUser = nvdUser;
}
/**
- * Get the value of proxyPassword.
+ * Set the value of nvdPassword.
*
- * @return the value of proxyPassword
+ * @param nvdPassword new value of nvdPassword
*/
- public String getProxyPassword() {
- return proxyPassword;
+ public void setNvdPassword(String nvdPassword) {
+ this.nvdPassword = nvdPassword;
}
/**
- * Set the value of proxyPassword.
- *
- * @param proxyPassword new value of proxyPassword
+ * Sets the token to download the NVD Data feed from an HTTP Bearer auth protected location.
+ * @param nvdBearerToken The bearer token
*/
- public void setProxyPassword(String proxyPassword) {
- this.proxyPassword = proxyPassword;
+ public void setNvdBearerToken(String nvdBearerToken) {
+ this.nvdBearerToken = nvdBearerToken;
}
/**
- * Get the value of nonProxyHosts.
+ * Set the value of nvdApiDelay.
*
- * @return the value of nonProxyHosts
+ * @param nvdApiDelay new value of nvdApiDelay
*/
- public String getNonProxyHosts() {
- return nonProxyHosts;
+ public void setNvdApiDelay(Integer nvdApiDelay) {
+ this.nvdApiDelay = nvdApiDelay;
}
/**
- * Set the value of nonProxyHosts.
+ * Set the value of nvdApiResultsPerPage.
*
- * @param nonProxyHosts new value of nonProxyHosts
+ * @param nvdApiResultsPerPage new value of nvdApiResultsPerPage
*/
- public void setNonProxyHosts(String nonProxyHosts) {
- this.nonProxyHosts = nonProxyHosts;
+ public void setNvdApiResultsPerPage(Integer nvdApiResultsPerPage) {
+ this.nvdApiResultsPerPage = nvdApiResultsPerPage;
}
/**
- * Get the value of connectionTimeout.
+ * Set the value of proxyServer.
*
- * @return the value of connectionTimeout
+ * @param server new value of proxyServer
*/
- public String getConnectionTimeout() {
- return connectionTimeout;
+ public void setProxyServer(String server) {
+ this.proxyServer = server;
}
/**
- * Set the value of connectionTimeout.
+ * Set the value of proxyPort.
*
- * @param connectionTimeout new value of connectionTimeout
+ * @param proxyPort new value of proxyPort
*/
- public void setConnectionTimeout(String connectionTimeout) {
- this.connectionTimeout = connectionTimeout;
+ public void setProxyPort(String proxyPort) {
+ this.proxyPort = proxyPort;
}
/**
- * Get the value of readTimeout.
+ * Set the value of proxyUsername.
*
- * @return the value of readTimeout
+ * @param proxyUsername new value of proxyUsername
*/
- public String getReadTimeout() {
- return readTimeout;
+ public void setProxyUsername(String proxyUsername) {
+ this.proxyUsername = proxyUsername;
}
/**
- * Set the value of readTimeout.
+ * Set the value of proxyPassword.
*
- * @param readTimeout new value of readTimeout
+ * @param proxyPassword new value of proxyPassword
*/
- public void setReadTimeout(String readTimeout) {
- this.readTimeout = readTimeout;
+ public void setProxyPassword(String proxyPassword) {
+ this.proxyPassword = proxyPassword;
}
/**
- * Get the value of databaseDriverName.
+ * Set the value of nonProxyHosts.
*
- * @return the value of databaseDriverName
+ * @param nonProxyHosts new value of nonProxyHosts
*/
- public String getDatabaseDriverName() {
- return databaseDriverName;
+ public void setNonProxyHosts(String nonProxyHosts) {
+ this.nonProxyHosts = nonProxyHosts;
}
/**
- * Set the value of databaseDriverName.
+ * Set the value of connectionTimeout.
*
- * @param databaseDriverName new value of databaseDriverName
+ * @param connectionTimeout new value of connectionTimeout
*/
- public void setDatabaseDriverName(String databaseDriverName) {
- this.databaseDriverName = databaseDriverName;
+ public void setConnectionTimeout(String connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
}
/**
- * Get the value of databaseDriverPath.
+ * Set the value of readTimeout.
*
- * @return the value of databaseDriverPath
+ * @param readTimeout new value of readTimeout
*/
- public String getDatabaseDriverPath() {
- return databaseDriverPath;
+ public void setReadTimeout(String readTimeout) {
+ this.readTimeout = readTimeout;
}
/**
- * Set the value of databaseDriverPath.
+ * Set the value of databaseDriverName.
*
- * @param databaseDriverPath new value of databaseDriverPath
+ * @param databaseDriverName new value of databaseDriverName
*/
- public void setDatabaseDriverPath(String databaseDriverPath) {
- this.databaseDriverPath = databaseDriverPath;
+ public void setDatabaseDriverName(String databaseDriverName) {
+ this.databaseDriverName = databaseDriverName;
}
/**
- * Get the value of connectionString.
+ * Set the value of databaseDriverPath.
*
- * @return the value of connectionString
+ * @param databaseDriverPath new value of databaseDriverPath
*/
- public String getConnectionString() {
- return connectionString;
+ public void setDatabaseDriverPath(String databaseDriverPath) {
+ this.databaseDriverPath = databaseDriverPath;
}
/**
@@ -312,15 +412,6 @@ public void setConnectionString(String connectionString) {
this.connectionString = connectionString;
}
- /**
- * Get the value of databaseUser.
- *
- * @return the value of databaseUser
- */
- public String getDatabaseUser() {
- return databaseUser;
- }
-
/**
* Set the value of databaseUser.
*
@@ -330,15 +421,6 @@ public void setDatabaseUser(String databaseUser) {
this.databaseUser = databaseUser;
}
- /**
- * Get the value of databasePassword.
- *
- * @return the value of databasePassword
- */
- public String getDatabasePassword() {
- return databasePassword;
- }
-
/**
* Set the value of databasePassword.
*
@@ -349,151 +431,157 @@ public void setDatabasePassword(String databasePassword) {
}
/**
- * Set the value of cveUrlModified.
+ * Set the value of hostedSuppressionsValidForHours.
*
- * @param cveUrlModified new value of cveUrlModified
+ * @param hostedSuppressionsValidForHours new value of
+ * hostedSuppressionsValidForHours
*/
- public void setCveUrlModified(String cveUrlModified) {
- this.cveUrlModified = cveUrlModified;
+ public void setHostedSuppressionsValidForHours(final Integer hostedSuppressionsValidForHours) {
+ this.hostedSuppressionsValidForHours = hostedSuppressionsValidForHours;
}
- /**
- * Get the value of cveUrlModified.
- *
- * @return the value of cveUrlModified
- */
- public String getCveUrlModified() {
- return cveUrlModified;
+ public void setHostedSuppressionsUser(String hostedSuppressionsUser) {
+ this.hostedSuppressionsUser = hostedSuppressionsUser;
+ }
+
+ public void setHostedSuppressionsPassword(String hostedSuppressionsPassword) {
+ this.hostedSuppressionsPassword = hostedSuppressionsPassword;
+ }
+
+ public void setHostedSuppressionsBearerToken(String hostedSuppressionsBearerToken) {
+ this.hostedSuppressionsBearerToken = hostedSuppressionsBearerToken;
}
/**
- * Get the value of cveUrlBase.
+ * Set the value of hostedSuppressionsForceUpdate.
*
- * @return the value of cveUrlBase
+ * @param hostedSuppressionsForceUpdate new value of
+ * hostedSuppressionsForceUpdate
*/
- public String getCveUrlBase() {
- return cveUrlBase;
+ public void setHostedSuppressionsForceUpdate(final Boolean hostedSuppressionsForceUpdate) {
+ this.hostedSuppressionsForceUpdate = hostedSuppressionsForceUpdate;
}
/**
- * Set the value of cveUrlBase.
+ * Set the value of hostedSuppressionsEnabled.
*
- * @param cveUrlBase new value of cveUrlBase
+ * @param hostedSuppressionsEnabled new value of hostedSuppressionsEnabled
*/
- public void setCveUrlBase(String cveUrlBase) {
- this.cveUrlBase = cveUrlBase;
+ public void setHostedSuppressionsEnabled(Boolean hostedSuppressionsEnabled) {
+ this.hostedSuppressionsEnabled = hostedSuppressionsEnabled;
}
/**
- * Get the value of cveUrlBase.
+ * Set the value of hostedSuppressionsUrl.
*
- * @return the value of cveUrlBase
+ * @param hostedSuppressionsUrl new value of hostedSuppressionsUrl
*/
- public String getCveWaitTime() {
- return cveWaitTime;
+ public void setHostedSuppressionsUrl(final String hostedSuppressionsUrl) {
+ this.hostedSuppressionsUrl = hostedSuppressionsUrl;
}
/**
- * Set the value of cveWaitTime.
+ * Sets the the knownExploitedUrl.
*
- * @param cveWaitTime new value of cveWaitTime
+ * @param knownExploitedUrl the URL
*/
- public void setCveWaitTime(String cveWaitTime) {
- this.cveWaitTime = cveWaitTime;
+ public void setKnownExploitedUrl(String knownExploitedUrl) {
+ this.knownExploitedUrl = knownExploitedUrl;
+ }
+
+ public void setKnownExploitedValidForHours(Integer knownExploitedValidForHours) {
+ this.knownExploitedValidForHours = knownExploitedValidForHours;
}
/**
- * Get the value of cveValidForHours.
+ * Sets the user for downloading the knownExploitedUrl from a HTTP Basic auth protected location.
*
- * @return the value of cveValidForHours
+ * @param knownExploitedUser the user
*/
- public Integer getCveValidForHours() {
- return cveValidForHours;
+ public void setKnownExploitedUser(String knownExploitedUser) {
+ this.knownExploitedUser = knownExploitedUser;
}
/**
- * Set the value of cveValidForHours.
+ * Sets the password for downloading the knownExploitedUrl from a HTTP Basic auth protected location..
*
- * @param cveValidForHours new value of cveValidForHours
+ * @param knownExploitedPassword the password
*/
- public void setCveValidForHours(Integer cveValidForHours) {
- this.cveValidForHours = cveValidForHours;
+ public void setKnownExploitedPassword(String knownExploitedPassword) {
+ this.knownExploitedPassword = knownExploitedPassword;
}
/**
- * Get the value of cveStartYear.
+ * Sets the token for downloading the knownExploitedUrl from an HTTP Bearer auth protected location..
*
- * @return the value of cveStartYear
+ * @param knownExploitedBearerToken the token
*/
- public Integer getCveStartYear() {
- return cveStartYear;
+ public void setKnownExploitedBearerToken(String knownExploitedBearerToken) {
+ this.knownExploitedBearerToken = knownExploitedBearerToken;
}
/**
- * Set the value of cveStartYear.
+ * Sets whether the analyzer is enabled.
*
- * @param cveStartYear new value of cveStartYear
+ * @param knownExploitedEnabled the value of the new setting
*/
- public void setCveStartYear(Integer cveStartYear) {
- if (cveStartYear != null && cveStartYear < 2002) {
- log("Invalid Configuration: cveStartYear must be 2002 or greater", Project.MSG_ERR);
- this.cveStartYear = 2002;
- } else {
- this.cveStartYear = cveStartYear;
- }
+ public void setKnownExploitedEnabled(Boolean knownExploitedEnabled) {
+ this.knownExploitedEnabled = knownExploitedEnabled;
}
/**
- * Get the value of hostedSuppressionsValidForHours.
+ * Set the value of the Retire JS repository URL.
*
- * @return the value of hostedSuppressionsValidForHours
+ * @param retireJsUrl new value of retireJsUrl
*/
- public Integer getHostedSuppressionsValidForHours() {
- return hostedSuppressionsValidForHours;
+ public void setRetireJsUrl(String retireJsUrl) {
+ this.retireJsUrl = retireJsUrl;
}
/**
- * Set the value of hostedSuppressionsValidForHours.
+ * Sets the user to download the RetireJS JSON data from an HTTP Basic auth protected location.
*
- * @param hostedSuppressionsValidForHours new value of hostedSuppressionsValidForHours
+ * @param retireJsUrlUser new value of retireJsUrlUser
*/
- public void setHostedSuppressionsValidForHours(final Integer hostedSuppressionsValidForHours) {
- this.hostedSuppressionsValidForHours = hostedSuppressionsValidForHours;
+ public void setRetireJsUrlUser(String retireJsUrlUser) {
+ this.retireJsUrlUser = retireJsUrlUser;
}
/**
- * Get the value of hostedSuppressionsForceUpdate.
+ * Sets the password to download the RetireJS JSON data from an HTTP Basic auth protected location.
*
- * @return the value of hostedSuppressionsForceUpdate
+ * @param retireJsUrlPassword new value of retireJsUrlPassword
*/
- public Boolean isHostedSuppressionsForceUpdate() {
- return hostedSuppressionsForceUpdate;
+ public void setRetireJsUrlPassword(String retireJsUrlPassword) {
+ this.retireJsUrlPassword = retireJsUrlPassword;
}
/**
- * Set the value of hostedSuppressionsForceUpdate.
+ * Sets the token to download the RetireJS JSON data from an HTTP Bearer auth protected location.
*
- * @param hostedSuppressionsForceUpdate new value of hostedSuppressionsForceUpdate
+ * @param retireJsUrlBearerToken new value of retireJsUrlBearerToken
*/
- public void setHostedSuppressionsForceUpdate(final Boolean hostedSuppressionsForceUpdate) {
- this.hostedSuppressionsForceUpdate = hostedSuppressionsForceUpdate;
+ public void setRetireJsUrlBearerToken(String retireJsUrlBearerToken) {
+ this.retireJsUrlBearerToken = retireJsUrlBearerToken;
}
/**
- * Get the value of hostedSuppressionsEnabled.
+ * Set the value of retireJsForceUpdate.
*
- * @return the value of hostedSuppressionsEnabled
+ * @param retireJsForceUpdate new value of
+ * retireJsForceUpdate
*/
- public Boolean isHostedSuppressionsEnabled() {
- return hostedSuppressionsEnabled;
+ public void setRetireJsForceUpdate(Boolean retireJsForceUpdate) {
+ this.retireJsForceUpdate = retireJsForceUpdate;
}
+
/**
- * Set the value of hostedSuppressionsEnabled.
+ * Set the value of retireJsAnalyzerEnabled.
*
- * @param hostedSuppressionsEnabled new value of hostedSuppressionsEnabled
+ * @param retireJsAnalyzerEnabled new value of retireJsAnalyzerEnabled
*/
- public void setHostedSuppressionsEnabled(Boolean hostedSuppressionsEnabled) {
- this.hostedSuppressionsEnabled = hostedSuppressionsEnabled;
+ public void setRetireJsAnalyzerEnabled(Boolean retireJsAnalyzerEnabled) {
+ this.retireJsAnalyzerEnabled = retireJsAnalyzerEnabled;
}
/**
@@ -508,6 +596,11 @@ public void setHostedSuppressionsEnabled(Boolean hostedSuppressionsEnabled) {
@Override
protected void executeWithContextClassloader() throws BuildException {
populateSettings();
+ try {
+ Downloader.getInstance().configure(getSettings());
+ } catch (InvalidSettingException e) {
+ throw new BuildException(e);
+ }
try (Engine engine = new Engine(Update.class.getClassLoader(), getSettings())) {
engine.doUpdates();
} catch (UpdateException ex) {
@@ -551,27 +644,37 @@ protected void populateSettings() throws BuildException {
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
getSettings().setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
- final String cveModifiedJson = Optional.ofNullable(cveUrlModified)
- .filter(url -> !url.isEmpty())
- .orElseGet(this::getDefaultCveUrlModified);
- getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_JSON, cveModifiedJson);
- getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_BASE_JSON, cveUrlBase);
- getSettings().setStringIfNotEmpty(Settings.KEYS.CVE_DOWNLOAD_WAIT_TIME, cveWaitTime);
- getSettings().setIntIfNotNull(Settings.KEYS.CVE_START_YEAR, cveStartYear);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.KEV_URL, knownExploitedUrl);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.KEV_USER, knownExploitedUser);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.KEV_PASSWORD, knownExploitedPassword);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.KEV_BEARER_TOKEN, knownExploitedBearerToken);
+ getSettings().setIntIfNotNull(Settings.KEYS.KEV_CHECK_VALID_FOR_HOURS, knownExploitedValidForHours);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED, knownExploitedEnabled);
+
+ getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_URL, retireJsUrl);
+ getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_USER, retireJsUrlUser);
+ getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_PASSWORD, retireJsUrlPassword);
+ getSettings().setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_BEARER_TOKEN, retireJsUrlBearerToken);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FORCEUPDATE, retireJsForceUpdate);
+ getSettings().setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_ENABLED, retireJsAnalyzerEnabled);
+
+ getSettings().setStringIfNotEmpty(Settings.KEYS.HOSTED_SUPPRESSIONS_URL, hostedSuppressionsUrl);
getSettings().setIntIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, hostedSuppressionsValidForHours);
+ getSettings().setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_USER, hostedSuppressionsUser);
+ getSettings().setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_PASSWORD, hostedSuppressionsPassword);
+ getSettings().setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_BEARER_TOKEN, hostedSuppressionsBearerToken);
getSettings().setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE, hostedSuppressionsForceUpdate);
getSettings().setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED, hostedSuppressionsEnabled);
- if (cveValidForHours != null) {
- if (cveValidForHours >= 0) {
- getSettings().setInt(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
- } else {
- throw new BuildException("Invalid setting: `cpeValidForHours` must be 0 or greater");
- }
- }
- }
- private String getDefaultCveUrlModified() {
- return CveUrlParser.newInstance(getSettings())
- .getDefaultCveUrlModified(cveUrlBase);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, nvdApiKey);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_ENDPOINT, nvdApiEndpoint);
+ getSettings().setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, nvdApiDelay);
+ getSettings().setIntIfNotNull(Settings.KEYS.NVD_API_RESULTS_PER_PAGE, nvdApiResultsPerPage);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, nvdDatafeedUrl);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_USER, nvdUser);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_PASSWORD, nvdPassword);
+ getSettings().setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_BEARER_TOKEN, nvdBearerToken);
+ getSettings().setIntIfNotNull(Settings.KEYS.NVD_API_MAX_RETRY_COUNT, nvdMaxRetryCount);
+ getSettings().setIntIfNotNull(Settings.KEYS.NVD_API_VALID_FOR_HOURS, nvdValidForHours);
}
}
diff --git a/ant/src/main/resources/task.properties b/ant/src/main/resources/task.properties
index 03c72cdc675..89625759080 100644
--- a/ant/src/main/resources/task.properties
+++ b/ant/src/main/resources/task.properties
@@ -1,2 +1,2 @@
# the path to the data directory
-data.directory=data/7.0
+data.directory=data/11.0
diff --git a/ant/src/site/markdown/config-purge.md b/ant/src/site/markdown/config-purge.md
index 5006865fe81..e048190e5bb 100644
--- a/ant/src/site/markdown/config-purge.md
+++ b/ant/src/site/markdown/config-purge.md
@@ -6,7 +6,7 @@ the rare circumstance that the local H2 database becomes corrupt.
```xml
-
+
```
@@ -14,15 +14,8 @@ Configuration: dependency-check-purge Task
--------------------
The following properties can be set on the dependency-check-purge task.
-Property | Description | Default Value
-----------------------|------------------------------------------------------------------------|------------------
-dataDirectory | Data directory that is used to store the local copy of the NVD | data
-failOnError | Whether the build should fail if there is an error executing the purge | true
+| Property | Description | Default Value |
+|---------------|----------------------------------------------------------------------------|--------------------------------------------------|
+| dataDirectory | Data directory that is used to store the local caches and NVD CVE database | `/data/11.0` |
+| failOnError | Whether the build should fail if there is an error executing the purge | true |
-Advanced Configuration
-====================
-The following properties can be configured in the plugin. However, they are less frequently changed.
-
-Property | Description | Default Value
-----------------------|--------------------------------------------------------------------------------------------------|------------------
-hostedSuppressionsUrl | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://jeremylong.github.io/DependencyCheck/suppressions/publishedSuppressions.xml
diff --git a/ant/src/site/markdown/config-update.md b/ant/src/site/markdown/config-update.md
index c3b776a0ec3..9d86a179987 100644
--- a/ant/src/site/markdown/config-update.md
+++ b/ant/src/site/markdown/config-update.md
@@ -4,12 +4,12 @@ The dependency-check-update task downloads and updates the local copy of the NVD
There are several reasons that one may want to use this task; primarily, creating
an update that will be run only once a day or once every few days (but not greater
than 7 days) and then use the `autoUpdate="false"` setting on individual
-dependency-check scans. See [Internet Access Required](https://jeremylong.github.io/DependencyCheck/data/index.html)
+dependency-check scans. See [Internet Access Required](https://dependency-check.github.io/DependencyCheck/data/index.html)
for more information on why this task would be used.
```xml
-
+
```
@@ -17,35 +17,54 @@ Configuration: dependency-check-update Task
--------------------
The following properties can be set on the dependency-check-update task.
-Property | Description | Default Value
-----------------------|-------------------------------------------------------------------------|------------------
-proxyServer | The Proxy Server. |
-proxyPort | The Proxy Port. |
-proxyUsername | Defines the proxy user name. |
-proxyPassword | Defines the proxy password. |
-nonProxyHosts | Defines the hosts that will not be proxied. |
-connectionTimeout | The URL Connection Timeout (in milliseconds). | 10000
-readtimeout | The URL Read Timeout (in milliseconds). | 60000
-failOnError | Whether the build should fail if there is an error executing the update | true
+| Property | Description | Default Value |
+|-------------------------|------------------------------------------------------------------------------------------------|--------------------------------------------------|
+| dataDirectory | Data directory that is used to store the local caches and NVD CVE database | `/data/11.0` |
+| failOnError | Whether the build should fail if there is an error executing the update | true |
+| proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. | |
+| proxyPort | The Proxy Port. | |
+| proxyUsername | Defines the proxy user name. | |
+| proxyPassword | Defines the proxy password. | |
+| nonProxyHosts | Defines the hosts that will not be proxied. | |
+| connectionTimeout | The URL Connection Timeout (in milliseconds). | 10000 |
+| readtimeout | The URL Read Timeout (in milliseconds). | 60000 |
+| retireJsAnalyzerEnabled | Sets whether the RetireJS Analyzer update and analyzer are enabled. | true |
Advanced Configuration
====================
-The following properties can be configured in the plugin. However, they are less frequently changed. One exception
-may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
+The following properties can be configured in the plugin. However, they are less frequently changed.
-Property | Description | Default Value
----------------------|----------------------------------------------------------------------------------------------------------------------|------------------
-cveUrlModified | URL for the modified CVE JSON data feed. When mirroring the NVD you must mirror the *.json.gz and the *.meta files. Optional if your custom cveUrlBase is just a domain name change. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz
-cveUrlBase | Base URL for each year's CVE JSON data feed, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz
-cveWaitTime | The time in milliseconds to wait between downloads from the NVD. | 4000
-cveStartYear | The first year of NVD CVE data to download from the NVD. | 2002
-dataDirectory | Data directory that is used to store the local copy of the NVD. This should generally not be changed. | data
-databaseDriverName | The name of the database driver. Example: org.h2.Driver. |
-databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
-connectionString | The connection string used to connect to the database. See using a [database server](../data/database.html). |
-databaseUser | The username used when connecting to the database. |
-databasePassword | The password used when connecting to the database. |
-hostedSuppressionsEnabled | Whether the hosted suppression file will be used. | true
-hostedSuppressionsUrl | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://jeremylong.github.io/DependencyCheck/suppressions/publishedSuppressions.xml
-hostedSuppressionsValidForHours | Sets the number of hours to wait before checking for new updates of the hosted suppressions file | 2
-hostedSuppressionsForceUpdate | Sets whether the hosted suppressions file should update regardless of the `autoupdate` and validForHours settings | false
\ No newline at end of file
+| Property | Description | Default Value |
+|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
+| nvdApiKey | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key | |
+| nvdApiEndpoint | The NVD API endpoint URL; setting this is uncommon. | https://services.nvd.nist.gov/rest/json/cves/2.0 |
+| nvdMaxRetryCount | The maximum number of retry requests for a single call to the NVD API. | 10 |
+| nvdApiDelay | The number of milliseconds to wait between calls to the NVD API. | 3500 with an NVD API Key or 8000 without an API Key |
+| nvdApiResultsPerPage | The number records for a single page from NVD API (must be <=2000). | 2000 |
+| nvdDatafeedUrl | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/open-vulnerability-cli/blob/main/README.md#mirroring-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | |
+| nvdUser | Credentials used for basic authentication for the NVD API Data feed. | |
+| nvdPassword | Credentials used for basic authentication for the NVD API Data feed. | |
+| nvdValidForHours | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | 4 |
+| databaseDriverName | The database driver full classname; note, only needs to be set if the driver is not JDBC4 compliant or the JAR is outside of the class path. | |
+| databaseDriverPath | The path to the database driver JAR file; only needs to be set if the driver is not in the class path. | |
+| connectionString | The connection string used to connect to the database. See using a [database server](../data/database.html). | |
+| databaseUser | The username used when connecting to the database. | |
+| databasePassword | The password used when connecting to the database. | |
+| hostedSuppressionsEnabled | Whether the hosted suppression file will be used. | true |
+| hostedSuppressionsUrl | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml |
+| hostedSuppressionsUser | The user for a Basic-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsPassword | The password/token for a Basic-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsValidForHours | Sets the number of hours to wait before checking for new updates of the hosted suppressions file | 2 |
+| hostedSuppressionsForceUpdate | Sets whether the hosted suppressions file should update regardless of the `autoupdate` and validForHours settings | false |
+| retireJsForceUpdate | Sets whether the RetireJS repository should update regardless of the `autoupdate` setting. | false |
+| retireJsUrl | The URL to a mirrored copy of the RetireJS repository for internet-constrained environments | https://raw.githubusercontent.com/Retirejs/retire.js/main/repository/jsrepository.json |
+| retireJsUrlUser | The user for a Basic-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| retireJsUrlPassword | The password/token for a Basic-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| retireJsUrlBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| knownExploitedEnabled | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | true |
+| knownExploitedUrl | Sets URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
+| knownExploitedUser | The user for a Basic-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedPassword | The password/token for a Basic-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedValidForHours | Sets the number of hours to wait before checking for new updates of the CISA Known Exploited Vulnerabilities JSON data feed | 24 |
diff --git a/ant/src/site/markdown/configuration.md b/ant/src/site/markdown/configuration.md
index 155cfe1518c..2eeb1a5b566 100644
--- a/ant/src/site/markdown/configuration.md
+++ b/ant/src/site/markdown/configuration.md
@@ -3,22 +3,26 @@ Configuration
Once dependency-check-ant has been [installed](index.html) the defined tasks can be used.
* dependency-check - the primary task used to check the project dependencies. Configuration options are below.
-* dependency-check-purge - deletes the local copy of the NVD; this should rarely be used (if ever). See the [purge configuration](config-purge.html) for more information.
-* dependency-check-update - downloads and updates the local copy of the NVD. See the [update configuration](config-update.html) for more information.
+* dependency-check-purge - deletes the local copy of the NVD; this should rarely be used (if ever). See
+ the [purge configuration](config-purge.html) for more information.
+* dependency-check-update - downloads and updates the local copy of the NVD. See
+ the [update configuration](config-update.html) for more information.
To configure the dependency-check task you can add it to a target and include a
file based [resource collection](http://ant.apache.org/manual/Types/resources.html#collection)
-such as a [FileSet](http://ant.apache.org/manual/Types/fileset.html), [DirSet](http://ant.apache.org/manual/Types/dirset.html),
+such as
+a [FileSet](http://ant.apache.org/manual/Types/fileset.html), [DirSet](http://ant.apache.org/manual/Types/dirset.html),
or [FileList](http://ant.apache.org/manual/Types/filelist.html) that includes
the project's dependencies.
```xml
+
-
-
+
+
@@ -30,36 +34,37 @@ Configuration: dependency-check Task
--------------------
The following properties can be set on the dependency-check task.
-Property | Description | Default Value
-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------
-autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
-cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD | 4
-failOnError | Whether the build should fail if there is an error executing the dependency-check analysis | true
-failBuildOnCVSS | Specifies if the build should be failed if a CVSS score equal to or above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. More information on CVSS scores can be found at the [NVD](https://nvd.nist.gov/vuln-metrics/cvss)| 11
-junitFailOnCVSS | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. | 0
-prettyPrint | Whether the XML and JSON formatted reports should be pretty printed. | false
-projectName | The name of the project being scanned. | Dependency-Check
-reportFormat | The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF, ALL). | HTML
-reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
-hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) |
-proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. |
-proxyPort | The Proxy Port. |
-proxyUsername | Defines the proxy user name. |
-proxyPassword | Defines the proxy password. |
-nonProxyHosts | Defines the hosts that will not be proxied. |
-connectionTimeout | The URL Connection Timeout. |
-enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false
-enableRetired | Enable the [retired analyzers](../analyzers/index.html). If not enabled the retired analyzers (see below) will not be loaded or used. | false
-suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). The parameter value can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/jeremylong/DependencyCheck/issues/1878#issuecomment-487533799) |
-junitFailOnCVSS | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. | 0
+| Property | Description | Default Value |
+|----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|
+| autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true |
+| failBuildOnCVSS | Specifies if the build should be failed if a CVSS score equal to or above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. More information on CVSS scores can be found at the [NVD](https://nvd.nist.gov/vuln-metrics/cvss) | 11 |
+| junitFailOnCVSS | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. | 0 |
+| prettyPrint | Whether the XML and JSON formatted reports should be pretty printed. | false |
+| projectName | The name of the project being scanned. | Dependency-Check |
+| reportFormat | The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB, ALL). | HTML |
+| reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target' |
+| hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) | |
+| dataDirectory | Data directory that is used to store the local caches and NVD CVE database | `/data/11.0` |
+| failOnError | Whether the build should fail if there is an error executing the dependency-check analysis | true |
+| proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. | |
+| proxyPort | The Proxy Port. | |
+| proxyUsername | Defines the proxy user name. | |
+| proxyPassword | Defines the proxy password. | |
+| nonProxyHosts | Defines the hosts that will not be proxied. | |
+| connectionTimeout | The URL Connection Timeout (in milliseconds). | 10000 |
+| readtimeout | The URL Read Timeout (in milliseconds). | 60000 |
+| enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false |
+| enableRetired | Enable the [retired analyzers](../analyzers/index.html). If not enabled the retired analyzers (see below) will not be loaded or used. | false |
+| suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). The parameter value can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/dependency-check/DependencyCheck/issues/1878#issuecomment-487533799) | |
+| failBuildOnUnusedSuppressionRule | Specifies that if any unused suppression rule is found, the build will fail. | false |
+| junitFailOnCVSS | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. | 0 |
The following nested elements can be set on the dependency-check task.
-Element | Property | Description | Default Value
-------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------
-suppressionFile | path | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). Element can be specified multiple times. The parameter value can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/jeremylong/DependencyCheck/issues/1878#issuecomment-487533799) | |
-reportFormat | format | The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF, ALL). Element can be specified multiple times. |
-
+| Element | Property | Description | Default Value |
+|-----------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
+| suppressionFile | path | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). Element can be specified multiple times. The parameter value can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/dependency-check/DependencyCheck/issues/1878#issuecomment-487533799) | |
+| reportFormat | format | The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB, ALL). Element can be specified multiple times. | |
Analyzer Configuration
====================
@@ -69,92 +74,115 @@ Note, that specific analyzers will automatically disable themselves if no file
types that they support are detected - so specifically disabling them may not
be needed.
-Property | Description | Default Value
-------------------------------------|------------------------------------------------------------------------------------------------------------|------------------
-archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
-zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
-jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
-centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. **Disabling this analyzer for Ant builds is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
-centralAnalyzerUseCache | Sets whether the Central Analyer will cache results. Cached results expire after 30 days. | true
-dartAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Dart Analyzer will be used. | true
-knownExploitedEnabled | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | true
-knownExploitedUrl | Sets URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
-ossIndexAnalyzerEnabled | Sets whether the [OSS Index Analyzer](../analyzers/oss-index-analyzer.html) will be enabled. This analyzer requires an internet connection. | true
-ossindexAnalyzerUseCache | Sets whether the OSS Index Analyzer will cache results. Cached results expire after 24 hours. | true
-ossindexAnalyzerUsername | Sets the username for OSS Index - note an account with OSS Index is not required. |
-ossindexAnalyzerPassword | Sets the password for OSS Index. |
-ossIndexAnalyzerWarnOnlyOnRemoteErrors | Whether we should only warn about Sonatype OSS Index remote errors instead of failing completely. |
-nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used (requires Nexus Pro). This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
-nexusUrl | Defines the Nexus web service endpoint (example http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. |
-nexusUser | The username to authenticate to the Nexus Server's web service end point. If not set the Nexus Analyzer will use an unauthenticated connection. |
-nexusPassword | The password to authenticate to the Nexus Server's web service end point. If not set the Nexus Analyzer will use an unauthenticated connection. |
-nexusUsesProxy | Whether the defined proxy should be used when connecting to Nexus. | true
-artifactoryAnalyzerEnabled | Sets whether Artifactory analyzer will be used | false
-artifactoryAnalyzerUrl | The Artifactory server URL. |Â
-artifactoryAnalyzerUseProxy | Whether Artifactory should be accessed through a proxy or not. | false
-artifactoryAnalyzerParallelAnalysis | Whether the Artifactory analyzer should be run in parallel or not |Â true
-artifactoryAnalyzerUsername | The user name (only used with API token) to connect to Artifactory instance |
-artifactoryAnalyzerApiToken | The API token to connect to Artifactory instance, only used if the username or the API key are not defined by artifactoryAnalyzerServerId,artifactoryAnalyzerUsername or artifactoryAnalyzerApiToken |
-artifactoryAnalyzerBearerToken | The bearer token to connect to Artifactory instance |
-pyDistributionAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. `enableExperimental` must be set to true. | true
-pyPackageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. `enableExperimental` must be set to true. | true
-rubygemsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. `enableExperimental` must be set to true. | true
-opensslAnalyzerEnabled | Sets whether the openssl Analyzer should be used. | true
-cmakeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) CMake Analyzer should be used. `enableExperimental` must be set to true. | true
-autoconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) autoconf Analyzer should be used. `enableExperimental` must be set to true. | true
-pipAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) pip Analyzer should be used. `enableExperimental` must be set to true. | true
-pipfileAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Pipfile Analyzer should be used. `enableExperimental` must be set to true. | true
-poetryAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Poetry Analyzer should be used. `enableExperimental` must be set to true. | true
-composerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. `enableExperimental` must be set to true. | true
-cpanfileAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Perl CPAN File Analyzer should be used. `enableExperimental` must be set to true. | true
-nodeAnalyzerEnabled | Sets whether the [retired](../analyzers/index.html) Node.js Analyzer should be used. | true
-nodeAuditAnalyzerEnabled | Sets whether the Node Audit Analyzer should be used. This analyzer requires an internet connection. | true
-nodeAuditAnalyzerUseCache | Sets whether the Node Audit Analyzer will cache results. Cached results expire after 24 hours. | true
-nodeAuditSkipDevDependencies | Sets whether the Node Audit Analyzer will skip devDependencies. | false
-nodePackageSkipDevDependencies | Sets whether the Node Package Analyzer will skip devDependencies. | false
-yarnAuditAnalyzerEnabled | Sets whether the Yarn Audit Analyzer should be used. This analyzer requires yarn and an internet connection. Use `nodeAuditSkipDevDependencies` to skip dev dependencies. | true
-pnpmAuditAnalyzerEnabled | Sets whether the Pnpm Audit Analyzer should be used. This analyzer requires pnpm and an internet connection. Use `nodeAuditSkipDevDependencies` to skip dev dependencies. | true
-pathToYarn | The path to `yarn`. |
-pathToPnpm | The path to `pnpm`. |
-retireJsAnalyzerEnabled | Sets whether the RetireJS Analyzer should be used. | true
-retireJsForceUpdate | Sets whether the RetireJS Analyzer should update regardless of the `autoupdate` setting. | false
-retirejsFilterNonVulnerable | Configures the RetireJS Analyzer to remove non-vulnerable JS dependencies from the report. | false
-retirejsFilter | A nested configuration that can be specified multple times; The regex defined is used to filter JS files based on content. |
-retireJsUrl | The URL to the Retire JS repository. | https://raw.githubusercontent.com/Retirejs/retire.js/main/repository/jsrepository.json
-nuspecAnalyzerEnabled | Sets whether the .NET Nuget Nuspec Analyzer will be used. | true
-nugetconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) .NET Nuget packages.config Analyzer will be used. `enableExperimental` must be set to true. | true
-cocoapodsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer should be used. `enableExperimental` must be set to true. | true
-mixAuditAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Mix Audit Analyzer should be used. `enableExperimental` must be set to true. | true
-mixAuditPath | Sets the path to the mix_audit executable; only used if mix audit analyzer is enabled and experimental analyzers are enabled. |
-bundleAuditAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Bundle Audit Analyzer should be used. `enableExperimental` must be set to true. | true
-bundleAuditPath | Sets the path to the bundle audit executable; only used if bundle audit analyzer is enabled and experimental analyzers are enabled. |
-swiftPackageManagerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Swift Package Analyzer should be used. `enableExperimental` must be set to true. | true
-swiftPackageResolvedAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Swift Package Resolved should be used. `enableExperimental` must be set to true. | true
-assemblyAnalyzerEnabled | Sets whether the .NET Assembly Analyzer should be used. | true
-msbuildAnalyzerEnabled | Sets whether the MSBuild Analyzer should be used. | true
-pathToCore | The path to dotnet core .NET assembly analysis on non-windows systems. |
-golangDepEnabled | Sets whether the [experimental](../analyzers/index.html) Golang Dependency Analyzer should be used. `enableExperimental` must be set to true. | true
-golangModEnabled | Sets whether the [experimental](../analyzers/index.html) Goland Module Analyzer should be used; requires `go` to be installed. `enableExperimental` must be set to true. | true
-pathToGo | The path to `go`. |
+| Property | Description | Default Value |
+|----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
+| archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true |
+| zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | |
+| jarAnalyzer | Sets whether the Jar Analyzer will be used. | true |
+| centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. **Disabling this analyzer for Ant builds is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true |
+| centralAnalyzerUseCache | Sets whether the Central Analyer will cache results. Cached results expire after 30 days. | true |
+| dartAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Dart Analyzer will be used. | true |
+| knownExploitedEnabled | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | true |
+| knownExploitedUrl | Sets URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
+| ossIndexAnalyzerEnabled | Sets whether the [OSS Index Analyzer](../analyzers/oss-index-analyzer.html) will be enabled. This analyzer requires an internet connection. | true |
+| ossindexAnalyzerUseCache | Sets whether the OSS Index Analyzer will cache results. Cached results expire after 24 hours. | true |
+| ossindexAnalyzerUsername | Sets the username for OSS Index - note an account with OSS Index is not required. | |
+| ossindexAnalyzerPassword | Sets the password for OSS Index. | |
+| ossIndexAnalyzerWarnOnlyOnRemoteErrors | Whether we should only warn about Sonatype OSS Index remote errors instead of failing completely. | |
+| nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is an alternative to the Central or Artifactory Analyzers, allowing retrieval from Sonatype Nexus installations. | true |
+| nexusUrl | Defines the Nexus web service endpoint (example http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | |
+| nexusUser | The username to authenticate to the Nexus Server's web service end point. If not set the Nexus Analyzer will use an unauthenticated connection. | |
+| nexusPassword | The password to authenticate to the Nexus Server's web service end point. If not set the Nexus Analyzer will use an unauthenticated connection. | |
+| nexusUsesProxy | Whether the defined proxy should be used when connecting to Nexus. | true |
+| artifactoryAnalyzerEnabled | Sets whether Artifactory analyzer will be used | false |
+| artifactoryAnalyzerUrl | The Artifactory server URL. | |
+| artifactoryAnalyzerUseProxy | Whether Artifactory should be accessed through a proxy or not. | false |
+| artifactoryAnalyzerParallelAnalysis | Whether the Artifactory analyzer should be run in parallel or not | true |
+| artifactoryAnalyzerUsername | The user name (only used with API token) to connect to Artifactory instance | |
+| artifactoryAnalyzerApiToken | The API token to connect to Artifactory instance, only used if the username or the API key are not defined by artifactoryAnalyzerServerId,artifactoryAnalyzerUsername or artifactoryAnalyzerApiToken | |
+| artifactoryAnalyzerBearerToken | The bearer token to connect to Artifactory instance | |
+| pyDistributionAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. `enableExperimental` must be set to true. | true |
+| pyPackageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. `enableExperimental` must be set to true. | true |
+| rubygemsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. `enableExperimental` must be set to true. | true |
+| opensslAnalyzerEnabled | Sets whether the openssl Analyzer should be used. | true |
+| cmakeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) CMake Analyzer should be used. `enableExperimental` must be set to true. | true |
+| autoconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) autoconf Analyzer should be used. `enableExperimental` must be set to true. | true |
+| pipAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) pip Analyzer should be used. `enableExperimental` must be set to true. | true |
+| pipfileAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Pipfile Analyzer should be used. `enableExperimental` must be set to true. | true |
+| poetryAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Poetry Analyzer should be used. `enableExperimental` must be set to true. | true |
+| composerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. `enableExperimental` must be set to true. | true |
+| composerAnalyzerSkipDev | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should skip "packages-dev" | false |
+| cpanfileAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Perl CPAN File Analyzer should be used. `enableExperimental` must be set to true. | true |
+| nodeAnalyzerEnabled | Sets whether the [retired](../analyzers/index.html) Node.js Analyzer should be used. | true |
+| nodeAuditAnalyzerEnabled | Sets whether the Node Audit Analyzer should be used. This analyzer requires an internet connection. | true |
+| nodeAuditAnalyzerUseCache | Sets whether the Node Audit Analyzer will cache results. Cached results expire after 24 hours. | true |
+| nodeAuditSkipDevDependencies | Sets whether the Node Audit Analyzer will skip devDependencies. | false |
+| nodePackageSkipDevDependencies | Sets whether the Node Package Analyzer will skip devDependencies. | false |
+| yarnAuditAnalyzerEnabled | Sets whether the Yarn Audit Analyzer should be used. This analyzer requires yarn and an internet connection. Use `nodeAuditSkipDevDependencies` to skip dev dependencies. | true |
+| pnpmAuditAnalyzerEnabled | Sets whether the Pnpm Audit Analyzer should be used. This analyzer requires pnpm and an internet connection. Use `nodeAuditSkipDevDependencies` to skip dev dependencies. | true |
+| pathToYarn | The path to `yarn`. | |
+| pathToPnpm | The path to `pnpm`. | |
+| retireJsAnalyzerEnabled | Sets whether the RetireJS Analyzer update and analyzer are enabled. | true |
+| retirejsFilterNonVulnerable | Configures the RetireJS Analyzer to remove non-vulnerable JS dependencies from the report. | false |
+| retirejsFilter | A nested configuration that can be specified multple times; The regex defined is used to filter JS files based on content. | |
+| nuspecAnalyzerEnabled | Sets whether the .NET Nuget Nuspec Analyzer will be used. | true |
+| nugetconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) .NET Nuget packages.config Analyzer will be used. `enableExperimental` must be set to true. | true |
+| libmanAnalyzerEnabled | Sets whether the Libman Analyzer will be used. | true |
+| cocoapodsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer should be used. `enableExperimental` must be set to true. | true |
+| carthageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Carthage Analyzer should be used. `enableExperimental` must be set to true. | true |
+| mixAuditAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Mix Audit Analyzer should be used. `enableExperimental` must be set to true. | true |
+| mixAuditPath | Sets the path to the mix_audit executable; only used if mix audit analyzer is enabled and experimental analyzers are enabled. | |
+| bundleAuditAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Bundle Audit Analyzer should be used. `enableExperimental` must be set to true. | true |
+| bundleAuditPath | Sets the path to the bundle audit executable; only used if bundle audit analyzer is enabled and experimental analyzers are enabled. | |
+| swiftPackageManagerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Swift Package Analyzer should be used. `enableExperimental` must be set to true. | true |
+| swiftPackageResolvedAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Swift Package Resolved should be used. `enableExperimental` must be set to true. | true |
+| assemblyAnalyzerEnabled | Sets whether the .NET Assembly Analyzer should be used. | true |
+| msbuildAnalyzerEnabled | Sets whether the MSBuild Analyzer should be used. | true |
+| pathToCore | The path to dotnet core .NET assembly analysis on non-windows systems. | |
+| golangDepEnabled | Sets whether the [experimental](../analyzers/index.html) Golang Dependency Analyzer should be used. `enableExperimental` must be set to true. | true |
+| golangModEnabled | Sets whether the [experimental](../analyzers/index.html) Goland Module Analyzer should be used; requires `go` to be installed. `enableExperimental` must be set to true. | true |
+| pathToGo | The path to `go`. | |
+| versionCheckEnabled | Whether dependency-check should check if a new version of dependency-check-maven exists. | true |
Advanced Configuration
====================
-The following properties can be configured in the plugin. However, they are less frequently changed. One exception
-may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
+The following properties can be configured in the plugin. However, they are less frequently changed.
-Property | Description | Default Value
----------------------|--------------------------------------------------------------------------|------------------
-cveUrlModified | URL for the modified CVE JSON data feed. When mirroring the NVD you must mirror the *.json.gz and the *.meta files. Optional if your custom cveUrlBase is just a domain name change. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz
-cveUrlBase | Base URL for each year's CVE JSON data feed, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz
-cveWaitTime | The time in milliseconds to wait between downloads from the NVD. | 4000
-cveStartYear | The first year of NVD CVE data to download from the NVD. | 2002
-dataDirectory | Data directory that is used to store the local copy of the NVD. This should generally not be changed. | data
-databaseDriverName | The name of the database driver. Example: org.h2.Driver. |
-databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. |
-connectionString | The connection string used to connect to the database. See using a [database server](../data/database.html). |
-databaseUser | The username used when connecting to the database. |
-databasePassword | The password used when connecting to the database. |
-hostedSuppressionsEnabled | Whether the hosted suppression file will be used. | true
-hostedSuppressionsUrl | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://jeremylong.github.io/DependencyCheck/suppressions/publishedSuppressions.xml
-hostedSuppressionsValidForHours | Sets the number of hours to wait before checking for new updates of the hosted suppressions file | 2
-hostedSuppressionsForceUpdate | Sets whether the hosted suppressions file should update regardless of the `autoupdate` and validForHours settings | false
\ No newline at end of file
+| Property | Description | Default Value |
+|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
+| nvdApiKey | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key | |
+| nvdApiEndpoint | The NVD API endpoint URL; setting this is uncommon. | https://services.nvd.nist.gov/rest/json/cves/2.0 |
+| nvdMaxRetryCount | The maximum number of retry requests for a single call to the NVD API. | 10 |
+| nvdApiDelay | The number of milliseconds to wait between calls to the NVD API. | 3500 with an NVD API Key or 8000 without an API Key |
+| nvdApiResultsPerPage | The number records for a single page from NVD API (must be <=2000). | 2000 |
+| nvdDatafeedUrl | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/open-vulnerability-cli/blob/main/README.md#mirroring-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | |
+| nvdUser | Credentials used for basic authentication for the NVD API Data feed. | |
+| nvdPassword | Credentials used for basic authentication for the NVD API Data feed. | |
+| nvdValidForHours | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | 4 |
+| databaseDriverName | The database driver full classname; note, only needs to be set if the driver is not JDBC4 compliant or the JAR is outside of the class path. | |
+| databaseDriverPath | The path to the database driver JAR file; only needs to be set if the driver is not in the class path. | |
+| connectionString | The connection string used to connect to the database. See using a [database server](../data/database.html). | |
+| databaseUser | The username used when connecting to the database. | |
+| databasePassword | The password used when connecting to the database. | |
+| hostedSuppressionsEnabled | Whether the hosted suppression file will be used. | true |
+| hostedSuppressionsUrl | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml |
+| hostedSuppressionsUser | The user for a Basic-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsPassword | The password/token for a Basic-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the hosted suppressions file for internet-constrained environments | |
+| hostedSuppressionsValidForHours | Sets the number of hours to wait before checking for new updates of the hosted suppressions file | 2 |
+| hostedSuppressionsForceUpdate | Sets whether the hosted suppressions file should update regardless of the `autoupdate` and validForHours settings | false |
+| retireJsForceUpdate | Sets whether the RetireJS repository should update regardless of the `autoupdate` setting. | false |
+| retireJsUrl | The URL to a mirrored copy of the RetireJS repository for internet-constrained environments | https://raw.githubusercontent.com/Retirejs/retire.js/main/repository/jsrepository.json |
+| retireJsUrlUser | The user for a Basic-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| retireJsUrlPassword | The password/token for a Basic-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| retireJsUrlBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the RetireJS repository for internet-constrained environments | |
+| suppressionFileUser | The user for Basic-auth-protected suppression files hosted on a webserver | |
+| suppressionFilePassword | The password/token for Basic-auth-protected suppression files hosted on a webserver | |
+| suppressionFileBearerToken | The bearer token for Bearer-auth-protected suppression files hosted on a webserver | |
+| knownExploitedEnabled | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | true |
+| knownExploitedUrl | Sets URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
+| knownExploitedUser | The user for a Basic-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedPassword | The password/token for a Basic-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedBearerToken | The bearer token for a Bearer-auth-protected mirrored copy of the CISA Known Exploited Vulnerabilities JSON data feed for internet-constrained environments | |
+| knownExploitedValidForHours | Sets the number of hours to wait before checking for new updates of the CISA Known Exploited Vulnerabilities JSON data feed | 24 |
+
\ No newline at end of file
diff --git a/ant/src/site/markdown/index.md.vm b/ant/src/site/markdown/index.md.vm
index a0b18eb03ce..77f85c1bd90 100644
--- a/ant/src/site/markdown/index.md.vm
+++ b/ant/src/site/markdown/index.md.vm
@@ -7,12 +7,12 @@ identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
Installation
====================
-1. Import the GPG key used to sign all Dependency Check releases: `gpg --keyserver hkp://keys.gnupg.net --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED`.
-2. Download dependency-check-ant from [github here](https://github.com/jeremylong/DependencyCheck/releases/download/v${project.version}/dependency-check-ant-${project.version}-release.zip) and the associated GPG signature file from the [GitHub release](https://github.com/jeremylong/DependencyCheck/releases/download/v${project.version}/dependency-check-ant-${project.version}-release.zip.asc).
+1. Import the GPG key used to sign all Dependency Check releases: `gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED`.
+2. Download dependency-check-ant from [github here](https://github.com/dependency-check/DependencyCheck/releases/download/v${project.version}/dependency-check-ant-${project.version}-release.zip) and the associated GPG signature file from the [GitHub release](https://github.com/dependency-check/DependencyCheck/releases/download/v${project.version}/dependency-check-ant-${project.version}-release.zip.asc).
3. Verify the cryptographic integrity of your download: `gpg --verify dependency-check-ant-${project.version}-release.zip.asc`.
4. Unzip the archive
5. Add the taskdef to your build.xml:
-
+#[[
```xml
@@ -26,6 +26,7 @@ Installation
```
+]]#
6. Use the defined taskdefs:
* [dependency-check](configuration.html) - the primary task used to check the project dependencies.
* [dependency-check-purge](config-purge.html) - deletes the local copy of the NVD; this should rarely be used (if ever).
@@ -34,7 +35,10 @@ Installation
It is important to understand that the first time this task is executed it may
take 10 minutes or more as it downloads and processes the data from the National
-Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov
+Vulnerability Database (NVD) hosted by NIST: https://nvd.nist.gov.
After the first batch download, as long as the task is executed at least once every
seven days the update will only take a few seconds.
+
+The Dependency-Check team strongly recommends to [mirror the NVD database](../data/mirrornvd.html) for any operational
+integration. If not done, any service disruption of the NVD database will make the usage of Dependency-Check difficult.
diff --git a/ant/src/site/site.xml b/ant/src/site/site.xml
index 3712590ed84..797f326f273 100644
--- a/ant/src/site/site.xml
+++ b/ant/src/site/site.xml
@@ -16,11 +16,11 @@ limitations under the License.
Copyright (c) 2013 Jeremy Long. All Rights Reserved.
-->
-
+
- OWASP dependency-check-ant
- OWASP dependency-check-ant
- ./images/dc-ant.svg
+
@@ -31,5 +31,6 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+
]]>
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskIT.java b/ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskIT.java
index a020d72092e..67b23f4819f 100644
--- a/ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskIT.java
+++ b/ant/src/test/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTaskIT.java
@@ -17,29 +17,28 @@
*/
package org.owasp.dependencycheck.taskdefs;
-import java.io.File;
-
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildFileRule;
import org.apache.tools.ant.types.LogLevel;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
-import static org.junit.Assert.assertTrue;
+import java.io.File;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*
* @author Jeremy Long
*/
-public class DependencyCheckTaskIT extends BaseDBTestCase {
+class DependencyCheckTaskIT extends BaseDBTestCase {
- @Rule
- public final BuildFileRule buildFileRule = new BuildFileRule();
+ private final BuildFileRule buildFileRule = new BuildFileRule();
- @Before
+ @BeforeEach
@Override
public void setUp() throws Exception {
super.setUp();
@@ -47,17 +46,28 @@ public void setUp() throws Exception {
buildFileRule.configureProject(buildFile, LogLevel.VERBOSE.getLevel());
}
+ @AfterEach
+ @Override
+ public void tearDown() throws Exception {
+ if (buildFileRule.getProject() != null) {
+ if (this.buildFileRule.getProject().getTargets().containsKey("tearDown")) {
+ this.buildFileRule.getProject().executeTarget("tearDown");
+ }
+ }
+ super.tearDown();
+ }
+
/**
* Test of addFileSet method, of class DependencyCheckTask.
*/
@Test
- public void testAddFileSet() throws Exception {
+ void testAddFileSet() throws Exception {
File report = new File("target/dependency-check-report.html");
if (report.exists() && !report.delete()) {
throw new Exception("Unable to delete 'target/dependency-check-report.html' prior to test.");
}
buildFileRule.executeTarget("test.fileset");
- assertTrue("DependencyCheck report was not generated", report.exists());
+ assertTrue(report.exists(), "DependencyCheck report was not generated");
}
/**
@@ -66,7 +76,7 @@ public void testAddFileSet() throws Exception {
* @throws Exception
*/
@Test
- public void testAddFileList() throws Exception {
+ void testAddFileList() throws Exception {
File report = new File("target/dependency-check-report.xml");
if (report.exists()) {
if (!report.delete()) {
@@ -75,7 +85,7 @@ public void testAddFileList() throws Exception {
}
buildFileRule.executeTarget("test.filelist");
- assertTrue("DependencyCheck report was not generated", report.exists());
+ assertTrue(report.exists(), "DependencyCheck report was not generated");
}
/**
@@ -84,7 +94,7 @@ public void testAddFileList() throws Exception {
* @throws Exception
*/
@Test
- public void testAddDirSet() throws Exception {
+ void testAddDirSet() throws Exception {
File report = new File("target/dependency-check-report.csv");
if (report.exists()) {
if (!report.delete()) {
@@ -92,11 +102,11 @@ public void testAddDirSet() throws Exception {
}
}
buildFileRule.executeTarget("test.dirset");
- assertTrue("DependencyCheck report was not generated", report.exists());
+ assertTrue(report.exists(), "DependencyCheck report was not generated");
}
@Test
- public void testNestedReportFormat() throws Exception {
+ void testNestedReportFormat() throws Exception {
File reportHTML = new File("target/dependency-check-report.html");
File reportCSV = new File("target/dependency-check-report.csv");
if (reportCSV.exists()) {
@@ -110,38 +120,37 @@ public void testNestedReportFormat() throws Exception {
}
}
buildFileRule.executeTarget("test.formatNested");
- assertTrue("DependencyCheck CSV report was not generated", reportCSV.exists());
- assertTrue("DependencyCheck HTML report was not generated", reportHTML.exists());
+ assertTrue(reportCSV.exists(), "DependencyCheck CSV report was not generated");
+ assertTrue(reportHTML.exists(), "DependencyCheck HTML report was not generated");
}
@Test
- public void testNestedBADReportFormat() throws Exception {
- try {
- buildFileRule.executeTarget("test.formatBADNested");
- Assert.fail("Should have had a buildExceotion for a bad format attribute");
- } catch (BuildException e) {
- assertTrue("Message did not have BAD, unexpected exception: " + e.getMessage(), e.getMessage().contains("BAD is not a legal value for this attribute"));
- }
+ void testNestedBADReportFormat() {
+ BuildException e = assertThrows(BuildException.class,
+ () -> buildFileRule.executeTarget("test.formatBADNested"),
+ "Should have had a buildException for a bad format attribute");
+ assertTrue(e.getMessage().contains("BAD is not a legal value for this attribute"),
+ "Message did not have BAD, unexpected exception: " + e.getMessage());
}
/**
* Test of getFailBuildOnCVSS method, of class DependencyCheckTask.
*/
@Test
- public void testGetFailBuildOnCVSS() {
- Exception exception = Assert.assertThrows(BuildException.class, () -> buildFileRule.executeTarget("failCVSS"));
+ void testGetFailBuildOnCVSS() {
+ Exception exception = assertThrows(BuildException.class, () -> buildFileRule.executeTarget("failCVSS"));
String expectedMessage = String.format("One or more dependencies were identified with vulnerabilities that "
+ "have a CVSS score greater than or equal to '%.1f':", 3.0f);
- Assert.assertTrue(exception.getMessage().contains(expectedMessage));
+ assertTrue(exception.getMessage().contains(expectedMessage));
}
/**
* Test the DependencyCheckTask where a CVE is suppressed.
*/
@Test
- public void testSuppressingCVE() {
+ void testSuppressingCVE() {
// GIVEN an ant task with a vulnerability
final String antTaskName = "suppression";
@@ -157,7 +166,7 @@ public void testSuppressingCVE() {
// THEN the ant task executed without error
final File report = new File("target/suppression-report.html");
- assertTrue("Expected the DependencyCheck report to be generated", report.exists());
+ assertTrue(report.exists(), "Expected the DependencyCheck report to be generated");
}
/**
@@ -165,7 +174,7 @@ public void testSuppressingCVE() {
* exception with a warning.
*/
@Test
- public void testSuppressingSingle() {
+ void testSuppressingSingle() {
// GIVEN an ant task with a vulnerability using the legacy property
final String antTaskName = "suppression-single";
// WHEN executing the ant task
@@ -173,7 +182,7 @@ public void testSuppressingSingle() {
// THEN the ant task executed without error
final File report = new File("target/suppression-single-report.html");
- assertTrue("Expected the DependencyCheck report to be generated", report.exists());
+ assertTrue(report.exists(), "Expected the DependencyCheck report to be generated");
}
/**
@@ -181,7 +190,7 @@ public void testSuppressingSingle() {
* exception with a warning.
*/
@Test
- public void testSuppressingMultiple() {
+ void testSuppressingMultiple() {
// GIVEN an ant task with a vulnerability using multiple was to configure the suppression file
final String antTaskName = "suppression-multiple";
// WHEN executing the ant task
@@ -189,14 +198,14 @@ public void testSuppressingMultiple() {
// THEN the ant task executed without error
final File report = new File("target/suppression-multiple-report.html");
- assertTrue("Expected the DependencyCheck report to be generated", report.exists());
+ assertTrue(report.exists(), "Expected the DependencyCheck report to be generated");
}
/**
* Test the DependencyCheckTask retireJS configuration.
*/
@Test
- public void testRetireJsConfiguration() {
+ void testRetireJsConfiguration() {
// GIVEN an ant task with a vulnerability using multiple was to configure the suppression file
final String antTaskName = "retireJS";
@@ -205,6 +214,6 @@ public void testRetireJsConfiguration() {
// THEN the ant task executed without error
final File report = new File("target/retirejs-report.html");
- assertTrue("Expected the DependencyCheck report to be generated", report.exists());
+ assertTrue(report.exists(), "Expected the DependencyCheck report to be generated");
}
}
diff --git a/ant/src/test/java/org/owasp/dependencycheck/taskdefs/UpdateTest.java b/ant/src/test/java/org/owasp/dependencycheck/taskdefs/UpdateTest.java
deleted file mode 100644
index 27b77fc031c..00000000000
--- a/ant/src/test/java/org/owasp/dependencycheck/taskdefs/UpdateTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.owasp.dependencycheck.taskdefs;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-
-import org.junit.Test;
-import org.owasp.dependencycheck.BaseTest;
-import org.owasp.dependencycheck.utils.Settings;
-
-public class UpdateTest extends BaseTest {
-
- @Test
- public void testPopulateSettingsShouldSetDefaultValueToCveUrlModified() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Update update = new Update();
- update.setCveUrlModified(null);
- update.setCveUrlBase("https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz");
-
- // When
- update.populateSettings();
-
- // Then
- String output = update.getSettings().getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to a default of the same model", output, is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldSetDefaultValueToCveUrlModifiedWhenCveUrlModifiedIsEmpty() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Update update = new Update();
- update.setCveUrlModified("");
- update.setCveUrlBase("https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz");
-
- // When
- update.populateSettings();
-
- // Then
- String output = update.getSettings().getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to a default of the same model when arg is empty", output,
- is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldNotSetDefaultValueToCveUrlModifiedWhenValueIsExplicitelySet() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Update update = new Update();
- update.setCveUrlModified("https://another-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz");
- update.setCveUrlBase("https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/some-unusual-file-name-%d.json.gz");
-
- // When
- update.populateSettings();
-
- // Then
- String output = update.getSettings().getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://another-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to the specified value", output, is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldNotSetDefaultValueToCveUrlModifiedWhenUnknownValueIsSet() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Update update = new Update();
- update.setCveUrlModified(null);
- update.setCveUrlBase("https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/some-unusual-file-name-%d.json.gz");
-
- // When
- update.populateSettings();
-
- // Then
- String output = update.getSettings().getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must not be set when name is not the same as from the nvd datasource", output,
- is(expectedOutput));
- }
-
-}
diff --git a/archetype/pom.xml b/archetype/pom.xml
index 6d2a53031bc..75c34eea3f7 100644
--- a/archetype/pom.xml
+++ b/archetype/pom.xml
@@ -20,30 +20,23 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 8.2.2-SNAPSHOT
+ 12.1.9-SNAPSHOTdependency-check-pluginDependency-Check Plugin Archetypejar
- 2023-03-23T10:32:22Z
+ 2025-10-13T14:24:18Z
- scm:git:https://github.com/jeremylong/DependencyCheck.git
- https://github.com/jeremylong/DependencyCheck/tree/main/archetype
- scm:git:git@github.com:jeremylong/DependencyCheck.git
+ scm:git:https://github.com/dependency-check/DependencyCheck.git
+ https://github.com/dependency-check/DependencyCheck/tree/main/archetype
+ scm:git:git@github.com/dependency-check/DependencyCheck.gitHEAD
-
- org.codehaus.mojo
- animal-sniffer-maven-plugin
-
- true
-
- org.apache.maven.pluginsmaven-resources-plugin
diff --git a/archetype/src/main/resources/archetype-resources/pom.xml b/archetype/src/main/resources/archetype-resources/pom.xml
index 712babfeabf..44343deafab 100644
--- a/archetype/src/main/resources/archetype-resources/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/pom.xml
@@ -4,17 +4,20 @@
\${groupId}\${artifactId}\${version}
-
+
\${artifactId}jar
-
+
The Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txt
-
+
+
+ ${maven.compiler.release}
+ org.owasp
@@ -34,10 +37,22 @@
${slf4j.version}provided
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.12.2
+ test
+ org.junit.jupiterjunit-jupiter-engine
- 5.8.2
+ 5.12.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.12.2test
diff --git a/archetype/src/main/resources/archetype-resources/src/test/java/__analyzerName__Test.java b/archetype/src/main/resources/archetype-resources/src/test/java/__analyzerName__Test.java
index 89942160280..69ecf2c8b16 100644
--- a/archetype/src/main/resources/archetype-resources/src/test/java/__analyzerName__Test.java
+++ b/archetype/src/main/resources/archetype-resources/src/test/java/__analyzerName__Test.java
@@ -13,43 +13,45 @@
*/
package ${package};
-import java.io.File;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.AfterAll;
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
+import java.io.File;
+
+import static org.junit.jupiter.api.Assertions.*;
+
/**
* Test cases for ${analyzerName}
*/
-public class ${analyzerName}Test {
-
+class ${analyzerName}Test {
+
Settings settings = null;
-
- public ${analyzerName}Test() {
+
+ ${analyzerName}Test() {
}
-
+
@BeforeAll
- public static void setUpClass() {
+ static void setUpClass() {
}
-
+
@AfterAll
- public static void tearDownClass() {
+ static void tearDownClass() {
}
-
+
@BeforeEach
- public void setUp() {
+ void setUp() {
settings = new Settings();
}
@AfterEach
- public void tearDown() {
+ void tearDown() {
settings.cleanup();
}
@@ -57,7 +59,7 @@ public void tearDown() {
* Test of accept method, of class ${analyzerName}.
*/
@Test
- public void testAccept() {
+ void testAccept() {
File pathname = new File("test.file");
${analyzerName} instance = new ${analyzerName}();
boolean expResult = true;
@@ -69,13 +71,13 @@ public void testAccept() {
* Test of analyze method, of class ${analyzerName}.
*/
@Test
- public void testAnalyze() throws Exception {
+ void testAnalyze() throws Exception {
//The engine is generally null for most analyzer test cases but can be instantiated if needed.
Engine engine = null;
${analyzerName} instance = new ${analyzerName}();
instance.initialize(settings);
instance.prepare(engine);
-
+
File file = new File(${analyzerName}.class.getClassLoader().getResource("test.file").toURI().getPath());
Dependency dependency = new Dependency(file);
@@ -87,7 +89,7 @@ public void testAnalyze() throws Exception {
* Test of getName method, of class ${analyzerName}.
*/
@Test
- public void testGetName() {
+ void testGetName() {
${analyzerName} instance = new ${analyzerName}();
String expResult = "${analyzerName}";
String result = instance.getName();
@@ -98,7 +100,7 @@ public void testGetName() {
* Test of getAnalysisPhase method, of class ${analyzerName}.
*/
@Test
- public void testGetAnalysisPhase() {
+ void testGetAnalysisPhase() {
${analyzerName} instance = new ${analyzerName}();
AnalysisPhase expResult = AnalysisPhase.INFORMATION_COLLECTION;
AnalysisPhase result = instance.getAnalysisPhase();
@@ -109,7 +111,7 @@ public void testGetAnalysisPhase() {
* Test of initialize method, of class ${analyzerName}.
*/
@Test
- public void testInitialize() throws Exception {
+ void testInitialize() throws Exception {
${analyzerName} instance = new ${analyzerName}();
instance.initialize(settings);
}
@@ -118,7 +120,7 @@ public void testInitialize() throws Exception {
* Test of close method, of class ${analyzerName}.
*/
@Test
- public void testClose() throws Exception {
+ void testClose() throws Exception {
${analyzerName} instance = new ${analyzerName}();
instance.close();
}
@@ -127,7 +129,7 @@ public void testClose() throws Exception {
* Test of supportsParallelProcessing method, of class ${analyzerName}.
*/
@Test
- public void testSupportsParallelProcessing() {
+ void testSupportsParallelProcessing() {
${analyzerName} instance = new ${analyzerName}();
boolean expResult = true;
boolean result = instance.supportsParallelProcessing();
@@ -138,7 +140,7 @@ public void testSupportsParallelProcessing() {
* Test of isEnabled method, of class ${analyzerName}.
*/
@Test
- public void testIsEnabled() {
+ void testIsEnabled() {
${analyzerName} instance = new ${analyzerName}();
boolean expResult = true;
boolean result = instance.isEnabled();
diff --git a/archetype/src/site/site.xml b/archetype/src/site/site.xml
index dac56d5b9a6..17e1defd4b7 100644
--- a/archetype/src/site/site.xml
+++ b/archetype/src/site/site.xml
@@ -16,11 +16,11 @@ limitations under the License.
Copyright (c) 2017 Jeremy Long. All Rights Reserved.
-->
-
-
- OWASP dependency-check-plugin
- OWASP dependency-check-plugin
- /images/dc.svg
+
+
+
@@ -29,6 +29,7 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
-
+
+
]]>
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/build-docker.sh b/build-docker.sh
index 355a6ab0da4..297ecc4cbd7 100755
--- a/build-docker.sh
+++ b/build-docker.sh
@@ -1,18 +1,27 @@
-#!/bin/bash -e
+#!/bin/bash
+set -euo pipefail
VERSION=$(mvn -q \
-Dexec.executable="echo" \
-Dexec.args='${project.version}' \
--non-recursive \
- org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
+ org.codehaus.mojo:exec-maven-plugin:3.5.1:exec)
FILE=./cli/target/dependency-check-$VERSION-release.zip
-if [ -f "$FILE" ]; then
- docker build . --build-arg VERSION=$VERSION -t owasp/dependency-check:$VERSION
- if [[ ! $VERSION = *"SNAPSHOT"* ]]; then
- docker tag owasp/dependency-check:$VERSION owasp/dependency-check:latest
- fi
-else
+if [ ! -f "$FILE" ]; then
echo "$FILE does not exist - run 'mvn package' first"
exit 1
fi
+
+if ! docker info -f '{{ .DriverStatus }}' | grep "driver-type io.containerd.snapshotter" >/dev/null; then
+ echo "Docker Engine is not running with the containerd snapshotter - this is currently needed to build and test ODC multi-platform images using docker buildx."
+ echo "If using Docker Desktop, enable \"Use containerd for pulling and storing images\" per https://docs.docker.com/desktop/settings-and-maintenance/settings/#general"
+ echo "For more technical information on Docker Engine, see https://docs.docker.com/engine/storage/containerd/"
+ exit 1
+fi
+
+extra_tag_args="$([[ ! $VERSION = *"SNAPSHOT"* ]] && echo "--tag owasp/dependency-check:latest" || echo "")"
+
+docker buildx build --pull --load --platform linux/amd64,linux/arm64 . \
+ --build-arg VERSION=$VERSION \
+ --tag owasp/dependency-check:$VERSION ${extra_tag_args}
diff --git a/cli/README.md b/cli/README.md
index cead8821808..7ab25b589d9 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -5,7 +5,7 @@ performed are a "best effort" and as such, there could be false positives as wel
vulnerabilities in 3rd party components is a well-known problem and is currently documented in the 2021 OWASP
Top 10 as [A06:2021 – Vulnerable and Outdated Components](https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/).
-Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-cli/index.html).
+Documentation and links to production binary releases can be found on the [github pages](https://dependency-check.github.io/DependencyCheck/dependency-check-cli/index.html).
Copyright & License
@@ -13,6 +13,8 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
-Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/blob/main/cli/LICENSE.txt) file for the full license.
+Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/dependency-check/DependencyCheck/blob/main/cli/LICENSE.txt) file for the full license.
-Dependency-Check Command Line makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/jeremylong/DependencyCheck/blob/main/cli/NOTICE.txt) file for more information.
+Dependency-Check Command Line makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/dependency-check/DependencyCheck/blob/main/cli/NOTICE.txt) file for more information.
+
+
\ No newline at end of file
diff --git a/cli/pom.xml b/cli/pom.xml
index e422f6799ad..d6979f56739 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 8.2.2-SNAPSHOT
+ 12.1.9-SNAPSHOTdependency-check-cli
@@ -29,9 +29,9 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
Dependency-Check Command Linedependency-check-cli is an command line tool that uses dependency-check-core to detect publicly disclosed vulnerabilities associated with the scanned project dependencies. The tool will generate a report listing the dependency, any identified Common Platform Enumeration (CPE) identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
- scm:git:https://github.com/jeremylong/DependencyCheck.git
- https://github.com/jeremylong/DependencyCheck/tree/main/cli
- scm:git:git@github.com:jeremylong/DependencyCheck.git
+ scm:git:https://github.com/dependency-check/DependencyCheck.git
+ https://github.com/dependency-check/DependencyCheck/tree/main/cli
+ scm:git:git@github.com/dependency-check/DependencyCheck.gitv6.4.1
@@ -92,16 +92,43 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
plugins/*true${project.basedir}/src/main/conf/unixBinTemplate
+
+ --enable-native-access=ALL-UNNAMED -XX:+IgnoreUnrecognizedVMOptionsassemble
+ packageassemble
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ fix-windows-shell-script
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+ org.apache.maven.pluginsmaven-assembly-plugin
@@ -152,6 +179,15 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
org.slf4jslf4j-api
+
+ io.github.jeremylong
+ jcs3-slf4j
+
+
+
+ io.github.jeremylong
+ open-vulnerability-clients
+ org.apache.antant
diff --git a/cli/src/main/java/org/owasp/dependencycheck/App.java b/cli/src/main/java/org/owasp/dependencycheck/App.java
index c1a702bf8c3..57a0355bf45 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/App.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/App.java
@@ -22,9 +22,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.commons.cli.ParseException;
import org.apache.tools.ant.DirectoryScanner;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
@@ -32,9 +33,10 @@
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.apache.tools.ant.types.LogLevel;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
+import org.owasp.dependencycheck.dependency.naming.Identifier;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
-import org.owasp.dependencycheck.utils.CveUrlParser;
+import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
@@ -46,6 +48,7 @@
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
+import io.github.jeremylong.jcs3.slf4j.Slf4jAdapter;
import java.util.TreeSet;
import org.owasp.dependencycheck.utils.SeverityUtil;
@@ -81,6 +84,10 @@ public class App {
*/
@SuppressWarnings("squid:S4823")
public static void main(String[] args) {
+ System.setProperty("jcs.logSystem", "slf4j");
+ if (!LOGGER.isDebugEnabled()) {
+ Slf4jAdapter.muteLogging(true);
+ }
final int exitCode;
final App app = new App();
exitCode = app.run(args);
@@ -138,6 +145,7 @@ public int run(String[] args) {
} else {
try {
populateSettings(cli);
+ Downloader.getInstance().configure(settings);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage());
LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
@@ -159,6 +167,7 @@ public int run(String[] args) {
try {
populateSettings(cli);
settings.setBoolean(Settings.KEYS.AUTO_UPDATE, true);
+ Downloader.getInstance().configure(settings);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage());
LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
@@ -179,6 +188,7 @@ public int run(String[] args) {
} else if (cli.isRunScan()) {
try {
populateSettings(cli);
+ Downloader.getInstance().configure(settings);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage(), ex);
LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
@@ -303,26 +313,38 @@ private int determineReturnCode(Engine engine, float cvssFailScore) {
for (Dependency d : engine.getDependencies()) {
boolean addName = true;
for (Vulnerability v : d.getVulnerabilities()) {
- final float cvssV2 = v.getCvssV2() != null ? v.getCvssV2().getScore() : -1;
- final float cvssV3 = v.getCvssV3() != null ? v.getCvssV3().getBaseScore() : -1;
- final float unscoredCvss = v.getUnscoredSeverity() != null ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
+ final double cvssV2 = v.getCvssV2() != null && v.getCvssV2().getCvssData() != null
+ && v.getCvssV2().getCvssData().getBaseScore() != null ? v.getCvssV2().getCvssData().getBaseScore() : -1;
+ final double cvssV3 = v.getCvssV3() != null && v.getCvssV3().getCvssData() != null
+ && v.getCvssV3().getCvssData().getBaseScore() != null ? v.getCvssV3().getCvssData().getBaseScore() : -1;
+ final double cvssV4 = v.getCvssV4() != null && v.getCvssV4().getCvssData() != null
+ && v.getCvssV4().getCvssData().getBaseScore() != null ? v.getCvssV4().getCvssData().getBaseScore() : -1;
+ final boolean useUnscored = cvssV2 == -1 && cvssV3 == -1 && cvssV4 == -1;
+ final double unscoredCvss = (useUnscored && v.getUnscoredSeverity() != null) ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
if (cvssV2 >= cvssFailScore
|| cvssV3 >= cvssFailScore
+ || cvssV4 >= cvssFailScore
|| unscoredCvss >= cvssFailScore
//safety net to fail on any if for some reason the above misses on 0
|| (cvssFailScore <= 0.0f)) {
- float score = 0.0f;
- if (cvssV3 >= 0.0f) {
+ double score = 0.0;
+ if (cvssV4 >= 0.0) {
+ score = cvssV4;
+ } else if (cvssV3 >= 0.0) {
score = cvssV3;
- } else if (cvssV2 >= 0.0f) {
+ } else if (cvssV2 >= 0.0) {
score = cvssV2;
- } else if (unscoredCvss >= 0.0f) {
+ } else if (unscoredCvss >= 0.0) {
score = unscoredCvss;
}
if (addName) {
addName = false;
- ids.append(NEW_LINE).append(d.getFileName()).append(": ");
+ ids.append(NEW_LINE).append(d.getFileName()).append(" (")
+ .append(Stream.concat(d.getSoftwareIdentifiers().stream(), d.getVulnerableSoftwareIdentifiers().stream())
+ .map(Identifier::getValue)
+ .collect(Collectors.joining(", ")))
+ .append("): ");
ids.append(v.getName()).append('(').append(score).append(')');
} else {
ids.append(", ").append(v.getName()).append('(').append(score).append(')');
@@ -358,7 +380,11 @@ private Set scanAntStylePaths(List antStylePaths, int symLinkDepth
String include = file.replace('\\', '/');
final File baseDir;
final int pos = getLastFileSeparator(include);
- final String tmpBase = include.substring(0, pos);
+ String tmpBase = include.substring(0, pos);
+ //fix for windows style paths scanning c:/temp.
+ if (tmpBase.endsWith(":")) {
+ tmpBase += "/";
+ }
final String tmpInclude = include.substring(pos + 1);
if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0
|| new File(include).isFile()) {
@@ -475,12 +501,14 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.getStringArgument(CliParser.ARGUMENT.CONNECTION_READ_TIMEOUT));
settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE,
cli.getStringArgument(CliParser.ARGUMENT.HINTS_FILE));
- settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS,
- cli.getIntegerValue(CliParser.ARGUMENT.CVE_VALID_FOR_HOURS));
- settings.setIntIfNotNull(Settings.KEYS.CVE_START_YEAR,
- cli.getIntegerValue(CliParser.ARGUMENT.CVE_START_YEAR));
settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE,
cli.getStringArguments(CliParser.ARGUMENT.SUPPRESSION_FILES));
+ settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_USER,
+ cli.getStringArgument(CliParser.ARGUMENT.SUPPRESSION_FILE_USER));
+ settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_PASSWORD,
+ cli.getStringArgument(CliParser.ARGUMENT.SUPPRESSION_FILE_PASSWORD));
+ settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE_BEARER_TOKEN,
+ cli.getStringArgument(CliParser.ARGUMENT.SUPPRESSION_FILE_BEARER_TOKEN));
//File Type Analyzer Settings
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED,
cli.hasOption(CliParser.ARGUMENT.EXPERIMENTAL));
@@ -500,6 +528,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL_USER));
settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_PASSWORD,
cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL_PASSWORD));
+ settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_BEARER_TOKEN,
+ cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL_BEARER_TOKEN));
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FORCEUPDATE,
cli.hasOption(CliParser.ARGUMENT.RETIRE_JS_FORCEUPDATE));
settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FILTERS,
@@ -508,6 +538,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.hasOption(CliParser.ARGUMENT.RETIREJS_FILTER_NON_VULNERABLE));
settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_JAR, Settings.KEYS.ANALYZER_JAR_ENABLED));
+ settings.setBoolean(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED,
+ !cli.isDisabled(CliParser.ARGUMENT.DISABLE_VERSION_CHECK, Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_MSBUILD, Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED,
@@ -516,6 +548,12 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_KEV, Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED));
settings.setStringIfNotNull(Settings.KEYS.KEV_URL,
cli.getStringArgument(CliParser.ARGUMENT.KEV_URL));
+ settings.setStringIfNotNull(Settings.KEYS.KEV_USER,
+ cli.getStringArgument(CliParser.ARGUMENT.KEV_USER));
+ settings.setStringIfNotNull(Settings.KEYS.KEV_PASSWORD,
+ cli.getStringArgument(CliParser.ARGUMENT.KEV_PASSWORD));
+ settings.setStringIfNotNull(Settings.KEYS.KEV_BEARER_TOKEN,
+ cli.getStringArgument(CliParser.ARGUMENT.KEV_BEARER_TOKEN));
settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_PY_DIST, Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED,
@@ -548,6 +586,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_OPENSSL, Settings.KEYS.ANALYZER_OPENSSL_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_COMPOSER, Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED));
+ settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_SKIP_DEV,
+ cli.hasOption(CliParser.ARGUMENT.COMPOSER_LOCK_SKIP_DEV));
settings.setBoolean(Settings.KEYS.ANALYZER_CPANFILE_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_CPAN, Settings.KEYS.ANALYZER_CPANFILE_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_GOLANG_DEP_ENABLED,
@@ -574,6 +614,8 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_SWIFT_RESOLVED, Settings.KEYS.ANALYZER_SWIFT_PACKAGE_RESOLVED_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_COCOAPODS, Settings.KEYS.ANALYZER_COCOAPODS_ENABLED));
+ settings.setBoolean(Settings.KEYS.ANALYZER_CARTHAGE_ENABLED,
+ !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CARTHAGE, Settings.KEYS.ANALYZER_CARTHAGE_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_RUBYGEMS, Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED));
settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED,
@@ -591,6 +633,14 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.hasOption(CliParser.ARGUMENT.DISABLE_NODE_AUDIT_SKIPDEV));
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED,
cli.hasOption(CliParser.ARGUMENT.ENABLE_NEXUS));
+ settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_URL,
+ cli.getStringArgument(CliParser.ARGUMENT.CENTRAL_URL));
+ settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_USER,
+ cli.getStringArgument(CliParser.ARGUMENT.CENTRAL_USERNAME));
+ settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_PASSWORD,
+ cli.getStringArgument(CliParser.ARGUMENT.CENTRAL_PASSWORD));
+ settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_BEARER_TOKEN,
+ cli.getStringArgument(CliParser.ARGUMENT.CENTRAL_BEARER_TOKEN));
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_URL,
cli.getStringArgument(CliParser.ARGUMENT.OSSINDEX_URL));
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_USER,
@@ -645,24 +695,33 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.getStringArgument(CliParser.ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS));
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_DOTNET_PATH,
cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_CORE));
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_BASE_JSON,
- cli.getStringArgument(CliParser.ARGUMENT.CVE_BASE_URL));
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_DOWNLOAD_WAIT_TIME,
- cli.getStringArgument(CliParser.ARGUMENT.CVE_DOWNLOAD_WAIT_TIME));
- final String cveModifiedJson = Optional.ofNullable(cli.getStringArgument(CliParser.ARGUMENT.CVE_MODIFIED_URL))
- .filter(arg -> !arg.isEmpty())
- .orElseGet(() -> getDefaultCveUrlModified(cli));
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_JSON,
- cveModifiedJson);
-
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_USER,
- cli.getStringArgument(CliParser.ARGUMENT.CVE_USER));
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_PASSWORD,
- cli.getStringArgument(CliParser.ARGUMENT.CVE_PASSWORD, Settings.KEYS.CVE_PASSWORD));
+ String key = cli.getStringArgument(CliParser.ARGUMENT.NVD_API_KEY);
+ if (key != null) {
+ if ((key.startsWith("\"") && key.endsWith("\"") || (key.startsWith("'") && key.endsWith("'")))) {
+ key = key.substring(1, key.length() - 1);
+ }
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, key);
+ }
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_ENDPOINT,
+ cli.getStringArgument(CliParser.ARGUMENT.NVD_API_ENDPOINT));
+ settings.setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_DELAY));
+ settings.setIntIfNotNull(Settings.KEYS.NVD_API_RESULTS_PER_PAGE, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_RESULTS_PER_PAGE));
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_URL));
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_USER, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_USER));
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_PASSWORD, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_PASSWORD));
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_BEARER_TOKEN, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_BEARER_TOKEN));
+ settings.setIntIfNotNull(Settings.KEYS.NVD_API_MAX_RETRY_COUNT, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_MAX_RETRY_COUNT));
+ settings.setIntIfNotNull(Settings.KEYS.NVD_API_VALID_FOR_HOURS, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_VALID_FOR_HOURS));
settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_URL,
cli.getStringArgument(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_URL));
+ settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_USER,
+ cli.getStringArgument(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_USER));
+ settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_PASSWORD,
+ cli.getStringArgument(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_PASSWORD));
+ settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_BEARER_TOKEN,
+ cli.getStringArgument(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_BEARER_TOKEN));
settings.setBoolean(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED,
!cli.isDisabled(CliParser.ARGUMENT.DISABLE_HOSTED_SUPPRESSIONS, Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED));
settings.setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE,
@@ -671,11 +730,6 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
cli.getIntegerValue(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS));
}
- private String getDefaultCveUrlModified(CliParser cli) {
- return CveUrlParser.newInstance(settings)
- .getDefaultCveUrlModified(cli.getStringArgument(CliParser.ARGUMENT.CVE_BASE_URL));
- }
-
//CSON: MethodLength
/**
* Creates a file appender and adds it to logback.
diff --git a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
index c34e734f8cd..eb833f8c6b5 100644
--- a/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
+++ b/cli/src/main/java/org/owasp/dependencycheck/CliParser.java
@@ -64,7 +64,7 @@ public final class CliParser {
/**
* The supported reported formats.
*/
- private static final String SUPPORTED_FORMATS = "HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, or ALL";
+ private static final String SUPPORTED_FORMATS = "HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB or ALL";
/**
* Constructs a new CLI Parser object with the configured settings.
@@ -114,26 +114,49 @@ private CommandLine parseArgs(String[] args) throws ParseException {
*/
private void validateArgs() throws FileNotFoundException, ParseException {
if (isUpdateOnly() || isRunScan()) {
- String value = line.getOptionValue(ARGUMENT.CVE_VALID_FOR_HOURS);
+
+ String value = line.getOptionValue(ARGUMENT.NVD_API_VALID_FOR_HOURS);
if (value != null) {
try {
final int i = Integer.parseInt(value);
if (i < 0) {
- throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
+ throw new ParseException("Invalid Setting: nvdValidForHours must be a number greater than or equal to 0.");
}
} catch (NumberFormatException ex) {
- throw new ParseException("Invalid Setting: cveValidForHours must be a number greater than or equal to 0.");
+ throw new ParseException("Invalid Setting: nvdValidForHours must be a number greater than or equal to 0.");
}
}
- value = line.getOptionValue(ARGUMENT.CVE_START_YEAR);
+ value = line.getOptionValue(ARGUMENT.NVD_API_MAX_RETRY_COUNT);
if (value != null) {
try {
final int i = Integer.parseInt(value);
- if (i < 2002) {
- throw new ParseException("Invalid Setting: cveStartYear must be a number greater than or equal to 2002.");
+ if (i <= 0) {
+ throw new ParseException("Invalid Setting: nvdMaxRetryCount must be a number greater than 0.");
}
} catch (NumberFormatException ex) {
- throw new ParseException("Invalid Setting: cveStartYear must be a number greater than or equal to 2002.");
+ throw new ParseException("Invalid Setting: nvdMaxRetryCount must be a number greater than 0.");
+ }
+ }
+ value = line.getOptionValue(ARGUMENT.NVD_API_DELAY);
+ if (value != null) {
+ try {
+ final int i = Integer.parseInt(value);
+ if (i < 0) {
+ throw new ParseException("Invalid Setting: nvdApiDelay must be a number greater than or equal to 0.");
+ }
+ } catch (NumberFormatException ex) {
+ throw new ParseException("Invalid Setting: nvdApiDelay must be a number greater than or equal to 0.");
+ }
+ }
+ value = line.getOptionValue(ARGUMENT.NVD_API_RESULTS_PER_PAGE);
+ if (value != null) {
+ try {
+ final int i = Integer.parseInt(value);
+ if (i <= 0 || i > 2000) {
+ throw new ParseException("Invalid Setting: nvdApiResultsPerPage must be a number in the range [1, 2000].");
+ }
+ } catch (NumberFormatException ex) {
+ throw new ParseException("Invalid Setting: nvdApiResultsPerPage must be a number in the range [1, 2000].");
}
}
}
@@ -149,18 +172,12 @@ private void validateArgs() throws FileNotFoundException, ParseException {
if (!isValidFormat(validating)
&& !isValidFilePath(validating, "format")) {
final String msg = String.format("An invalid 'format' of '%s' was specified. "
- + "Supported output formats are %s, and custom template files.",
+ + "Supported output formats are %s, and custom template files.",
validating, SUPPORTED_FORMATS);
throw new ParseException(msg);
}
}
}
- final String base = getStringArgument(ARGUMENT.CVE_BASE_URL);
- final String modified = getStringArgument(ARGUMENT.CVE_MODIFIED_URL);
- if ((base != null && modified == null) || (base == null && modified != null)) {
- final String msg = "If one of the CVE URLs is specified they must all be specified; please add the missing CVE URL.";
- throw new ParseException(msg);
- }
if (line.hasOption(ARGUMENT.SYM_LINK_DEPTH)) {
try {
final int i = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH));
@@ -304,14 +321,14 @@ private void addStandardOptions(final Options options) {
//This is an option group because it can be specified more then once.
options.addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.SCAN_SHORT, ARGUMENT.SCAN, "path",
- "The path to scan - this option can be specified multiple times. Ant style paths are supported (e.g. 'path/**/*.jar'); "
- + "if using Ant style paths it is highly recommended to quote the argument value.")))
+ "The path to scan - this option can be specified multiple times. Ant style paths are supported (e.g. 'path/**/*.jar'); "
+ + "if using Ant style paths it is highly recommended to quote the argument value.")))
.addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.EXCLUDE, "pattern", "Specify an exclusion pattern. This option "
+ "can be specified multiple times and it accepts Ant style exclusions.")))
.addOption(newOptionWithArg(ARGUMENT.PROJECT, "name", "The name of the project being scanned."))
.addOption(newOptionWithArg(ARGUMENT.OUT_SHORT, ARGUMENT.OUT, "path",
"The folder to write reports to. This defaults to the current directory. It is possible to set this to a specific "
- + "file name if the format argument is not set to ALL."))
+ + "file name if the format argument is not set to ALL."))
.addOption(newOptionWithArg(ARGUMENT.OUTPUT_FORMAT_SHORT, ARGUMENT.OUTPUT_FORMAT, "format",
"The report format (" + SUPPORTED_FORMATS + "). The default is HTML. Multiple format parameters can be specified."))
.addOption(newOption(ARGUMENT.PRETTY_PRINT, "When specified the JSON and XML report formats will be pretty printed."))
@@ -324,10 +341,12 @@ private void addStandardOptions(final Options options) {
"The file path to write verbose logging information."))
.addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.SUPPRESSION_FILES, "file",
"The file path to the suppression XML file. This can be specified more then once to utilize multiple suppression files")))
+ .addOption(newOption(ARGUMENT.DISABLE_VERSION_CHECK, "Disables the dependency-check version check"))
.addOption(newOption(ARGUMENT.EXPERIMENTAL, "Enables the experimental analyzers."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_KEY, "apiKey", "The API Key to access the NVD API."))
.addOption(newOptionWithArg(ARGUMENT.FAIL_ON_CVSS, "score",
"Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; "
- + "since the CVSS scores are 0-10, by default the build will never fail."))
+ + "since the CVSS scores are 0-10, by default the build will never fail."))
.addOption(newOptionWithArg(ARGUMENT.FAIL_JUNIT_ON_CVSS, "score",
"Specifies the CVSS score that is considered a failure when generating the junit report. The default is 0."));
}
@@ -344,16 +363,30 @@ private void addAdvancedOptions(final Options options) {
options
.addOption(newOption(ARGUMENT.UPDATE_ONLY,
"Only update the local NVD data cache; no scan will be executed."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_BASE_URL, "url",
- "Base URL for each year’s CVE files (json.gz), the %d will be replaced with the year."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_MODIFIED_URL, "url",
- "URL for the modified CVE (json.gz)."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_DOWNLOAD_WAIT_TIME, "milliseconds",
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_DELAY, "milliseconds",
"Time in milliseconds to wait between downloading from the NVD."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_USER, "user",
- "Credentials for basic authentication to the CVE data."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_PASSWORD, "password",
- "Credentials for basic authentication to the CVE data."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_RESULTS_PER_PAGE, "count",
+ "The number records for a single page from NVD API (must be <=2000)."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_ENDPOINT, "endpoint",
+ "The NVD API Endpoint - setting this is rare."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_URL, "url",
+ "The URL to the NVD API Datafeed."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_USER, "user",
+ "Credentials for basic authentication to the NVD API Datafeed."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_PASSWORD, "password",
+ "Credentials for basic authentication to the NVD API Datafeed."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_BEARER_TOKEN, "token",
+ "Credentials for bearer authentication to the NVD API Datafeed."))
+ .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_USER, "user",
+ "Credentials for basic authentication to web-hosted suppression files."))
+ .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_PASSWORD, "password",
+ "Credentials for basic authentication to web-hosted suppression files."))
+ .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_BEARER_TOKEN, "token",
+ "Credentials for bearer authentication to web-hosted suppression files."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_MAX_RETRY_COUNT, "count",
+ "The maximum number of retry requests for a single call to the NVD API."))
+ .addOption(newOptionWithArg(ARGUMENT.NVD_API_VALID_FOR_HOURS, "hours",
+ "The number of hours to wait before checking for new updates from the NVD."))
.addOption(newOptionWithArg(ARGUMENT.PROXY_PORT, "port",
"The proxy port to use when downloading resources."))
.addOption(newOptionWithArg(ARGUMENT.PROXY_SERVER, "server",
@@ -364,7 +397,7 @@ private void addAdvancedOptions(final Options options) {
"The proxy password to use when downloading resources."))
.addOption(newOptionWithArg(ARGUMENT.NON_PROXY_HOSTS, "list",
"The proxy exclusion list: hostnames (or patterns) for which proxy should not be used. "
- + "Use pipe, comma or colon as list separator."))
+ + "Use pipe, comma or colon as list separator."))
.addOption(newOptionWithArg(ARGUMENT.CONNECTION_TIMEOUT_SHORT, ARGUMENT.CONNECTION_TIMEOUT, "timeout",
"The connection timeout (in milliseconds) to use when downloading resources."))
.addOption(newOptionWithArg(ARGUMENT.CONNECTION_READ_TIMEOUT, "timeout",
@@ -381,19 +414,27 @@ private void addAdvancedOptions(final Options options) {
"The database driver name."))
.addOption(newOptionWithArg(ARGUMENT.DB_DRIVER_PATH, "path",
"The path to the database driver; note, this does not need to be set unless the JAR is "
- + "outside of the classpath."))
+ + "outside of the classpath."))
.addOption(newOptionWithArg(ARGUMENT.SYM_LINK_DEPTH, "depth",
"Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed."))
.addOption(newOptionWithArg(ARGUMENT.PATH_TO_BUNDLE_AUDIT, "path",
"The path to bundle-audit for Gem bundle analysis."))
.addOption(newOptionWithArg(ARGUMENT.PATH_TO_BUNDLE_AUDIT_WORKING_DIRECTORY, "path",
"The path to working directory that the bundle-audit command should be executed from when "
- + "doing Gem bundle analysis."))
+ + "doing Gem bundle analysis."))
+ .addOption(newOptionWithArg(ARGUMENT.CENTRAL_URL, "url",
+ "Alternative URL for Maven Central Search. If not set the public Sonatype Maven Central will be used."))
+ .addOption(newOptionWithArg(ARGUMENT.CENTRAL_USERNAME, "username",
+ "Credentials for basic auth towards the --centralUrl."))
+ .addOption(newOptionWithArg(ARGUMENT.CENTRAL_PASSWORD, "password",
+ "Credentials for basic auth towards the --centralUrl"))
+ .addOption(newOptionWithArg(ARGUMENT.CENTRAL_BEARER_TOKEN, "token",
+ "Token for bearer auth towards the --centralUrl"))
.addOption(newOptionWithArg(ARGUMENT.OSSINDEX_URL, "url",
"Alternative URL for the OSS Index. If not set the public Sonatype OSS Index will be used."))
.addOption(newOptionWithArg(ARGUMENT.OSSINDEX_USERNAME, "username",
"The username to authenticate to Sonatype's OSS Index. If not set the Sonatype OSS Index "
- + "Analyzer will use an unauthenticated connection."))
+ + "Analyzer will use an unauthenticated connection."))
.addOption(newOptionWithArg(ARGUMENT.OSSINDEX_PASSWORD, "password", ""
+ "The password to authenticate to Sonatype's OSS Index. If not set the Sonatype OSS "
+ "Index Analyzer will use an unauthenticated connection."))
@@ -402,11 +443,13 @@ private void addAdvancedOptions(final Options options) {
.addOption(newOption(ARGUMENT.RETIRE_JS_FORCEUPDATE, "Force the RetireJS Analyzer to update "
+ "even if autoupdate is disabled"))
.addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL, "url",
- "The Retire JS Respository URL"))
+ "The Retire JS Repository URL"))
.addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_USER, "username",
- "The password to authenticate to Retire JS Respository URL"))
+ "The password to authenticate to Retire JS Repository URL"))
.addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_PASSWORD, "password",
- "The password to authenticate to Retire JS Respository URL"))
+ "The password to authenticate to Retire JS Repository URL"))
+ .addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_BEARER_TOKEN, "token",
+ "The password to authenticate to Retire JS Repository URL"))
.addOption(newOption(ARGUMENT.RETIREJS_FILTER_NON_VULNERABLE, "Specifies that the Retire JS "
+ "Analyzer should filter out non-vulnerable JS files from the report."))
.addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_PARALLEL_ANALYSIS, "true/false",
@@ -427,29 +470,25 @@ private void addAdvancedOptions(final Options options) {
"The path to the `yarn` executable."))
.addOption(newOptionWithArg(ARGUMENT.PATH_TO_PNPM, "path",
"The path to the `pnpm` executable."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_VALID_FOR_HOURS, "hours",
- "The number of hours to wait before checking for new updates from the NVD."))
- .addOption(newOptionWithArg(ARGUMENT.CVE_START_YEAR, "year",
- "The first year to retrieve NVD CVE data for; default is 2002."))
.addOption(newOptionWithArg(ARGUMENT.RETIREJS_FILTERS, "pattern",
"Specify Retire JS content filter used to exclude files from analysis based on their content; "
- + "most commonly used to exclude based on your applications own copyright line. This "
- + "option can be specified multiple times."))
+ + "most commonly used to exclude based on your applications own copyright line. This "
+ + "option can be specified multiple times."))
.addOption(newOptionWithArg(ARGUMENT.NEXUS_URL, "url",
"The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). If not "
- + "set the Nexus Analyzer will be disabled."))
+ + "set the Nexus Analyzer will be disabled."))
.addOption(newOptionWithArg(ARGUMENT.NEXUS_USERNAME, "username",
"The username to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus "
- + "Analyzer will use an unauthenticated connection."))
+ + "Analyzer will use an unauthenticated connection."))
.addOption(newOptionWithArg(ARGUMENT.NEXUS_PASSWORD, "password",
"The password to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus "
- + "Analyzer will use an unauthenticated connection."))
+ + "Analyzer will use an unauthenticated connection."))
//TODO remove as this should be covered by non-proxy hosts
.addOption(newOptionWithArg(ARGUMENT.NEXUS_USES_PROXY, "true/false",
"Whether or not the configured proxy should be used when connecting to Nexus."))
.addOption(newOptionWithArg(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS, "extensions",
"A comma separated list of additional extensions to be scanned as ZIP files (ZIP, EAR, WAR "
- + "are already treated as zip files)"))
+ + "are already treated as zip files)"))
.addOption(newOptionWithArg(ARGUMENT.PROP_SHORT, ARGUMENT.PROP, "file", "A property file to load."))
.addOption(newOptionWithArg(ARGUMENT.PATH_TO_CORE, "path", "The path to dotnet core."))
.addOption(newOptionWithArg(ARGUMENT.HINTS_FILE, "file", "The file path to the hints XML file."))
@@ -459,6 +498,12 @@ private void addAdvancedOptions(final Options options) {
.addOption(newOption(ARGUMENT.DISABLE_ARCHIVE, "Disable the Archive Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_KEV, "Disable the Known Exploited Vulnerability Analyzer."))
.addOption(newOptionWithArg(ARGUMENT.KEV_URL, "url", "The url to the CISA Known Exploited Vulnerabilities JSON data feed"))
+ .addOption(newOptionWithArg(ARGUMENT.KEV_USER, "user", "The user for basic authentication towards the CISA Known Exploited "
+ + "Vulnerabilities JSON data feed"))
+ .addOption(newOptionWithArg(ARGUMENT.KEV_PASSWORD, "password", "The password for basic authentication towards the CISA Known "
+ + "Exploited Vulnerabilities JSON data feed"))
+ .addOption(newOptionWithArg(ARGUMENT.KEV_BEARER_TOKEN, "token", "The token for bearer authentication towards the CISA Known "
+ + "Exploited Vulnerabilities JSON data feed"))
.addOption(newOption(ARGUMENT.DISABLE_ASSEMBLY, "Disable the .NET Assembly Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_PY_DIST, "Disable the Python Distribution Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_CMAKE, "Disable the Cmake Analyzer."))
@@ -472,6 +517,7 @@ private void addAdvancedOptions(final Options options) {
.addOption(newOption(ARGUMENT.DISABLE_PIP, "Disable the pip Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_PIPFILE, "Disable the Pipfile Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_COMPOSER, "Disable the PHP Composer Analyzer."))
+ .addOption(newOption(ARGUMENT.COMPOSER_LOCK_SKIP_DEV, "Configures the PHP Composer Analyzer to skip packages-dev"))
.addOption(newOption(ARGUMENT.DISABLE_CPAN, "Disable the Perl CPAN file Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_POETRY, "Disable the Poetry Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_GOLANG_MOD, "Disable the Golang Mod Analyzer."))
@@ -485,6 +531,7 @@ private void addAdvancedOptions(final Options options) {
.addOption(newOption(ARGUMENT.DISABLE_OSSINDEX, "Disable the Sonatype OSS Index Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_OSSINDEX_CACHE, "Disallow the OSS Index Analyzer from caching results"))
.addOption(newOption(ARGUMENT.DISABLE_COCOAPODS, "Disable the CocoaPods Analyzer."))
+ .addOption(newOption(ARGUMENT.DISABLE_CARTHAGE, "Disable the Carthage Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_SWIFT, "Disable the swift package Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_SWIFT_RESOLVED, "Disable the swift package resolved Analyzer."))
.addOption(newOption(ARGUMENT.DISABLE_GO_DEP, "Disable the Golang Package Analyzer."))
@@ -501,11 +548,17 @@ private void addAdvancedOptions(final Options options) {
.addOption(newOption(ARGUMENT.PURGE_NVD, "Purges the local NVD data cache"))
.addOption(newOption(ARGUMENT.DISABLE_HOSTED_SUPPRESSIONS, "Disable the usage of the hosted suppressions file"))
.addOption(newOption(ARGUMENT.HOSTED_SUPPRESSIONS_FORCEUPDATE, "Force the hosted suppressions file to update even"
- + " if autoupdate is disabled"))
+ + " if autoupdate is disabled"))
.addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, "hours",
- "The number of hours to wait before checking for new updates of the the hosted suppressions file."))
+ "The number of hours to wait before checking for new updates of the the hosted suppressions file."))
.addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_URL, "url",
- "The URL for a mirrored hosted suppressions file"));
+ "The URL for a mirrored hosted suppressions file"))
+ .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_USER, "user",
+ "The user for basic auth to a mirrored hosted suppressions file"))
+ .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_PASSWORD, "password",
+ "The password for basic auth to a mirrored hosted suppressions file"))
+ .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_BEARER_TOKEN, "token",
+ "The token for bearer auth to a mirrored hosted suppressions file"));
}
@@ -733,8 +786,8 @@ public void printHelp() {
addAdvancedOptions(options);
}
final String helpMsg = String.format("%n%s"
- + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
- + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
+ + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
+ + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
settings.getString(Settings.KEYS.APPLICATION_NAME, "DependencyCheck"),
settings.getString(Settings.KEYS.APPLICATION_NAME, "DependencyCheck"));
@@ -1014,6 +1067,11 @@ public static class ARGUMENT {
* should not be automatically updated.
*/
public static final String DISABLE_AUTO_UPDATE = "noupdate";
+ /**
+ * The long CLI argument name specifying that the version check should
+ * not be performed.
+ */
+ public static final String DISABLE_VERSION_CHECK = "disableVersionCheck";
/**
* The short CLI argument name specifying that the CPE/CVE/etc. data
* should not be automatically updated.
@@ -1121,17 +1179,59 @@ public static class ARGUMENT {
*/
public static final String DATA_DIRECTORY = "data";
/**
- * The CLI argument name for setting the URL for the CVE Data Files.
+ * The CLI argument name for setting the URL for the NVD API Endpoint.
*/
- public static final String CVE_MODIFIED_URL = "cveUrlModified";
+ public static final String NVD_API_ENDPOINT = "nvdApiEndpoint";
/**
- * The CLI argument name for setting the URL for the CVE Data Files.
+ * The CLI argument name for setting the URL for the NVD API Key.
*/
- public static final String CVE_BASE_URL = "cveUrlBase";
+ public static final String NVD_API_KEY = "nvdApiKey";
/**
- * The time in milliseconds to wait between downloading NVD CVE data.
+ * The CLI argument name for setting the maximum number of retry
+ * requests for a single call to the NVD API.
*/
- public static final String CVE_DOWNLOAD_WAIT_TIME = "cveDownloadWait";
+ public static final String NVD_API_MAX_RETRY_COUNT = "nvdMaxRetryCount";
+ /**
+ * The CLI argument name for setting the number of hours to wait before
+ * checking for new updates from the NVD.
+ */
+ public static final String NVD_API_VALID_FOR_HOURS = "nvdValidForHours";
+ /**
+ * The CLI argument name for the NVD API Data Feed URL.
+ */
+ public static final String NVD_API_DATAFEED_URL = "nvdDatafeed";
+ /**
+ * The username for basic auth to the CVE data.
+ */
+ public static final String NVD_API_DATAFEED_USER = "nvdUser";
+ /**
+ * The password for basic auth to the CVE data.
+ */
+ public static final String NVD_API_DATAFEED_PASSWORD = "nvdPassword";
+ /**
+ * The token for bearer auth to the CVE data.
+ */
+ public static final String NVD_API_DATAFEED_BEARER_TOKEN = "nvdBearerToken";
+ /**
+ * The username for basic auth to web-hosted suppression files.
+ */
+ public static final String SUPPRESSION_FILE_USER = "suppressionUser";
+ /**
+ * The passwored for basic auth to web-hosted suppression files.
+ */
+ public static final String SUPPRESSION_FILE_PASSWORD = "suppressionPassword";
+ /**
+ * The toke for bearer auth to web-hosted suppression files.
+ */
+ public static final String SUPPRESSION_FILE_BEARER_TOKEN = "suppressionBearerToken";
+ /**
+ * The time in milliseconds to wait between downloading NVD API data.
+ */
+ public static final String NVD_API_DELAY = "nvdApiDelay";
+ /**
+ * The number records for a single page from NVD API.
+ */
+ public static final String NVD_API_RESULTS_PER_PAGE = "nvdApiResultsPerPage";
/**
* The short CLI argument name for setting the location of the data
* directory.
@@ -1160,24 +1260,6 @@ public static class ARGUMENT {
* The CLI argument name for setting the location of the hint file.
*/
public static final String HINTS_FILE = "hints";
- /**
- * The CLI argument name for setting the number of hours to wait before
- * checking for new updates from the NVD.
- */
- public static final String CVE_VALID_FOR_HOURS = "cveValidForHours";
- /**
- * The CLI argument name for setting the first year to retrieve NVD
- * data.
- */
- public static final String CVE_START_YEAR = "cveStartYear";
- /**
- * The username for basic auth to the CVE data.
- */
- public static final String CVE_USER = "cveUser";
- /**
- * The password for basic auth to the CVE data.
- */
- public static final String CVE_PASSWORD = "cvePassword";
/**
* Disables the Jar Analyzer.
*/
@@ -1198,6 +1280,18 @@ public static class ARGUMENT {
* The URL to the CISA Known Exploited Vulnerability JSON datafeed.
*/
public static final String KEV_URL = "kevURL";
+ /**
+ * The user for basic auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
+ */
+ public static final String KEV_USER = "kevUser";
+ /**
+ * The password for basic auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
+ */
+ public static final String KEV_PASSWORD = "kevPassword";
+ /**
+ * The token for bearer auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
+ */
+ public static final String KEV_BEARER_TOKEN = "kevBearerToken";
/**
* Disables the Python Distribution Analyzer.
*/
@@ -1218,6 +1312,10 @@ public static class ARGUMENT {
* Disables the PHP Composer Analyzer.
*/
public static final String DISABLE_COMPOSER = "disableComposer";
+ /**
+ * Whether the PHP Composer Analyzer skips dev packages.
+ */
+ public static final String COMPOSER_LOCK_SKIP_DEV = "composerSkipDev";
/**
* Disables the Perl CPAN File Analyzer.
*/
@@ -1274,6 +1372,10 @@ public static class ARGUMENT {
* Disables the cocoapods analyzer.
*/
public static final String DISABLE_COCOAPODS = "disableCocoapodsAnalyzer";
+ /**
+ * Disables the Carthage analyzer.
+ */
+ public static final String DISABLE_CARTHAGE = "disableCarthageAnalyzer";
/**
* Disables the swift package manager analyzer.
*/
@@ -1310,6 +1412,22 @@ public static class ARGUMENT {
* Disables the Central Analyzer's ability to cache results locally.
*/
public static final String DISABLE_CENTRAL_CACHE = "disableCentralCache";
+ /**
+ * The alternative URL for Maven Central Search.
+ */
+ public static final String CENTRAL_URL = "centralUrl";
+ /**
+ * The username for basic authentication to the alternative Maven Central Search.
+ */
+ public static final String CENTRAL_USERNAME = "centralUsername";
+ /**
+ * The password for basic authentication to the alternative Maven Central Search.
+ */
+ public static final String CENTRAL_PASSWORD = "centralPassword";
+ /**
+ * The token for bearer authentication to the alternative Maven Central Search.
+ */
+ public static final String CENTRAL_BEARER_TOKEN = "centralBearerToken";
/**
* Disables the Nexus Analyzer.
*/
@@ -1385,13 +1503,17 @@ public static class ARGUMENT {
*/
public static final String RETIREJS_URL = "retireJsUrl";
/**
- * The username to the retire JS repository.
+ * The username for basic auth to the retire JS repository.
*/
public static final String RETIREJS_URL_USER = "retireJsUrlUser";
/**
- * The password to the retire JS repository.
+ * The password for basic auth to the retire JS repository.
*/
public static final String RETIREJS_URL_PASSWORD = "retireJsUrlPass";
+ /**
+ * The token for bearer auth to the retire JS repository.
+ */
+ public static final String RETIREJS_URL_BEARER_TOKEN = "retireJsUrlBearerToken";
/**
* The URL of the nexus server.
*/
@@ -1523,21 +1645,36 @@ public static class ARGUMENT {
*/
public static final String FAIL_JUNIT_ON_CVSS = "junitFailOnCVSS";
/**
- * The CLI argument to set the number of hours to wait before re-checking hosted suppressions file for updates.
+ * The CLI argument to set the number of hours to wait before
+ * re-checking hosted suppressions file for updates.
*/
public static final String DISABLE_HOSTED_SUPPRESSIONS = "disableHostedSuppressions";
/**
- * The CLI argument to set the number of hours to wait before re-checking hosted suppressions file for updates.
+ * The CLI argument to set the number of hours to wait before
+ * re-checking hosted suppressions file for updates.
*/
public static final String HOSTED_SUPPRESSIONS_VALID_FOR_HOURS = "hostedSuppressionsValidForHours";
/**
- * The CLI argument to set Whether the hosted suppressions file will update regardless of the `noupdate` argument.
+ * The CLI argument to set Whether the hosted suppressions file will
+ * update regardless of the `noupdate` argument.
*/
public static final String HOSTED_SUPPRESSIONS_FORCEUPDATE = "hostedSuppressionsForceUpdate";
/**
- * The CLI argument to set the location of a mirrored hosted suppressions
- * file .
+ * The CLI argument to set the location of a mirrored hosted
+ * suppressions file .
*/
public static final String HOSTED_SUPPRESSIONS_URL = "hostedSuppressionsUrl";
+ /**
+ * The username for basic auth to a mirrored hosted suppressions file.
+ */
+ public static final String HOSTED_SUPPRESSIONS_USER = "hostedSuppressionsUser";
+ /**
+ * The passwored for basic auth to a mirrored hosted suppressions file.
+ */
+ public static final String HOSTED_SUPPRESSIONS_PASSWORD = "hostedSuppressionsPassword";
+ /**
+ * The toke for bearer auth to a mirrored hosted suppressions file.
+ */
+ public static final String HOSTED_SUPPRESSIONS_BEARER_TOKEN = "hostedSuppressionsBearerToken";
}
}
diff --git a/cli/src/main/resources/completion-for-dependency-check.sh b/cli/src/main/resources/completion-for-dependency-check.sh
index 76af9d41d9a..09ffff27370 100755
--- a/cli/src/main/resources/completion-for-dependency-check.sh
+++ b/cli/src/main/resources/completion-for-dependency-check.sh
@@ -19,13 +19,6 @@ _odc_completions()
--bundleAuditWorkingDirectory
-c --connectiontimeout
--connectionString
- --cveUrlBase
- --cveUrlModified
- --cveValidForHours
- --cveStartYear
- --cveUser
- --cvePassword
- --cveDownloadWait
-d --data
--dbDriverName
--dbDriverPath
@@ -39,6 +32,7 @@ _odc_completions()
--disableCentralCache
--disableCmake
--disableCocoapodsAnalyzer
+ --disableCarthageAnalyzer
--disableComposer
--disableDart
--disableFileName
@@ -94,6 +88,12 @@ _odc_completions()
--nodeAuditSkipDevDependencies
--nodePackageSkipDevDependencies
--nonProxyHosts
+ --nvdApiKey
+ --nvdDatafeed
+ --nvdUser
+ --nvdPassword
+ --nvdApiDelay
+ --nvdValidForHours
-o --out
--ossIndexPassword
--ossIndexUsername
diff --git a/cli/src/main/resources/logback.xml b/cli/src/main/resources/logback.xml
index c7adf1499db..da49803591a 100644
--- a/cli/src/main/resources/logback.xml
+++ b/cli/src/main/resources/logback.xml
@@ -9,9 +9,12 @@
[%level] %msg%n
-
+
+
+
+
-
\ No newline at end of file
+
diff --git a/cli/src/site/markdown/arguments.md b/cli/src/site/markdown/arguments.md
index 0cb8d1baf3c..28f99c21090 100644
--- a/cli/src/site/markdown/arguments.md
+++ b/cli/src/site/markdown/arguments.md
@@ -3,122 +3,142 @@ Command Line Arguments
The following table lists the command line arguments:
-| Short | Argument Name | Parameter | Description | Requirement |
-|-------|------------------------|-----------------|----------------------------------------|-------------|
-| | \-\-project | \ | The name of the project being scanned. | Optional |
-| \-s | \-\-scan | \ | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. 'directory/**/*.jar'); if using an Ant style path it is highly recommended that you use single quotes around the path so that the shell itself does not automatically perform replacements (see [issue #1812](https://github.com/jeremylong/DependencyCheck/issues/1812). | Required |
-| | \-\-exclude | \ | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**). | Optional |
-| | \-\-symLink | \ | The depth that symbolic links will be followed; the default is 0 meaning symbolic links will not be followed. | Optional |
-| \-o | \-\-out | \ | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional |
-| \-f | \-\-format | \ | The output format to write to (XML, HTML, CSV, JSON, JUNIT, SARIF, ALL). Multiple formats can be specified by specifying the parameter multiple times. The default is HTML. | Required |
-| | \-\-junitFailOnCVSS | \ | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. The default is 0. | Optional |
-| | \-\-prettyPrint | | When specified the JSON and XML report formats will be pretty printed. | Optional |
-| | \-\-failOnCVSS | \ | If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified. | Optional |
-| \-l | \-\-log | \ | The file path to write verbose logging information. | Optional |
-| \-n | \-\-noupdate | | Disables the automatic updating of the NVD-CVE, hosted-suppressions and RetireJS data. | Optional |
-| | \-\-suppression | \ | The file paths to the suppression XML files; used to suppress [false positives](../general/suppression.html). This can be specified more than once to utilize multiple suppression files. The argument can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/jeremylong/DependencyCheck/issues/1878#issuecomment-487533799) | Optional |
-| \-h | \-\-help | | Print the help message. | Optional |
-| | \-\-advancedHelp | | Print the advanced help message. | Optional |
-| \-v | \-\-version | | Print the version information. | Optional |
-| | \-\-cveValidForHours | \ | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | Optional |
-| | \-\-enableExperimental | | Enable the [experimental analyzers](../analyzers/index.html). If not set the analyzers marked as experimental below will not be loaded or used. | Optional |
-| | \-\-enableRetired | | Enable the [retired analyzers](../analyzers/index.html). If not set the analyzers marked as retired below will not be loaded or used. | Optional |
+| Short | Argument Name | Parameter | Description | Requirement |
+|-------|------------------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
+| | \-\-project | \ | The name of the project being scanned. | Optional |
+| \-s | \-\-scan | \ | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. 'directory/**/*.jar'); if using an Ant style path it is highly recommended that you use single quotes around the path so that the shell itself does not automatically perform replacements (see [issue #1812](https://github.com/dependency-check/DependencyCheck/issues/1812). | Required |
+| | \-\-exclude | \ | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**). | Optional |
+| | \-\-symLink | \ | The depth that symbolic links will be followed; the default is 0 meaning symbolic links will not be followed. | Optional |
+| \-o | \-\-out | \ | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional |
+| \-f | \-\-format | \ | The output format to write to (HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB, ALL). Multiple formats can be specified by specifying the parameter multiple times. The default is HTML. | Required |
+| | \-\-junitFailOnCVSS | \ | If using the JUNIT report format the junitFailOnCVSS sets the CVSS score threshold that is considered a failure. The default is 0. | Optional |
+| | \-\-prettyPrint | | When specified the JSON and XML report formats will be pretty printed. | Optional |
+| | \-\-failOnCVSS | \ | If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified. | Optional |
+| \-l | \-\-log | \ | The file path to write verbose logging information. | Optional |
+| \-n | \-\-noupdate | | Disables the automatic updating of the NVD-CVE, hosted-suppressions and RetireJS data. | Optional |
+| | \-\-suppression | \ | The file paths to the suppression XML files; used to suppress [false positives](../general/suppression.html). This can be specified more than once to utilize multiple suppression files. The argument can be a local file path, a URL to a suppression file, or even a reference to a file on the class path (see https://github.com/dependency-check/DependencyCheck/issues/1878#issuecomment-487533799) | Optional |
+| \-h | \-\-help | | Print the help message. | Optional |
+| | \-\-advancedHelp | | Print the advanced help message. | Optional |
+| \-v | \-\-version | | Print the version information. | Optional |
+| | \-\-enableExperimental | | Enable the [experimental analyzers](../analyzers/index.html). If not set the analyzers marked as experimental below will not be loaded or used. | Optional |
+| | \-\-enableRetired | | Enable the [retired analyzers](../analyzers/index.html). If not set the analyzers marked as retired below will not be loaded or used. | Optional |
Advanced Options
================
-| Short | Argument Name | Parameter | Description | Default Value |
-|-------|---------------------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
-| | \-\-cveUrlModified | \ | URL for the modified CVE JSON data feed. When mirroring the NVD you must mirror the *.json.gz and the *.meta files. Optional if your custom cveUrlBase is just a domain name change. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz |
-| | \-\-cveUrlBase | \ | Base URL for each year's CVE JSON data feed, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz |
-| | \-\-cveUser | \ | Credentials used for basic authentication for the CVE data. | |
-| | \-\-cvePassword | \ | Credentials used for basic authentication for the CVE data. | |
-| | \-\-cveStartYear | \ | The first year of NVD CVE data to retrieve. | 2002 |
-| | \-\-cveDownloadWait | \| The number of milliseconds to wait between NVD CVE download. | 4000 |
-| | \-\-hints | \ | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) | |
-| \-P | \-\-propertyfile | \ | Specifies a file that contains properties to use instead of application defaults. The key values used in the properties file are not the same as the arguments listed on this page; use the keys here: https://github.com/jeremylong/DependencyCheck/blob/main/core/src/main/resources/dependencycheck.properties | |
-| | \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. | |
-| | \-\-disableKnownExploited | | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | |
-| | \-\-kevURL | \ | URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
-| | \-\-disableFileName | | Disables the File Name Analyzer; in generally, this should not be disabled. | |
-| | \-\-disablePyDist | | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | |
-| | \-\-disablePyPkg | | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | |
-| | \-\-disableMSBuild | | Sets whether the MS Build Project Analyzer will be used. | |
-| | \-\-disableNodeJS | | Sets whether the Node.js Package Analyzer will be used. | |
-| | \-\-disableYarnAudit | | Sets whether the yarn Audit Analyzer will be used. This analyzer requires an internet connection and that yarn is installed. Use `--nodeAuditSkipDevDependencies` to skip dev dependencies. | |
-| | \-\-yarn | \ | The path to `yarn`. | |
-| | \-\-disablePnpmAudit | | Sets whether the pnpm Audit Analyzer will be used. This analyzer requires an internet connection and that pnpm is installed. Use `--nodeAuditSkipDevDependencies` to skip dev dependencies. | |
-| | \-\-pnpm | \ | The path to `pnpm`. | |
-| | \-\-disableNodeAudit | | Sets whether the Node Audit Analyzer will be used. This analyzer requires an internet connection. | |
-| | \-\-disableNodeAuditCache | | When the argument is present the Node Audit Analyzer will not cache results. By default the results are cached for 24 hours. | |
-| | \-\-nodeAuditSkipDevDependencies | | Configures the Node Audit Analyzer to skip devDependencies. | |
-| | \-\-nodePackageSkipDevDependencies | | Configures the Node Package Analyzer to skip devDependencies. | |
-| | \-\-disableRetireJS | | Sets whether the RetireJS Analyzer will be used. | |
-| | \-\-retireJsForceUpdate | | Sets whether the RetireJS Analyzer will update regardless of the `noupdate` argument. | false |
-| | \-\-retireJsUrl | \ | The URL to the Retire JS repository. | https://raw.githubusercontent.com/Retirejs/retire.js/master/repository/jsrepository.json |
-| | \-\-retirejsFilter | \ | The RetireJS Analyzers content filter used to exclude JS files when the content contains the given regular expression; this option can be specified multiple times. | |
-| | \-\-retirejsFilterNonVulnerable | | Specifies that the Retire JS Analyzer should filter out non-vulnerable JS files from the report. | |
-| | \-\-retirejsUser | \ | Credentials used for basic authentication for the RetireJS data. | |
-| | \-\-retirejsPassword | \ | Credentials used for basic authentication for the RetireJS data. | |
-| | \-\-disableRubygems | | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | |
-| | \-\-disableBundleAudit | | Sets whether the [experimental](../analyzers/index.html) Ruby Bundler Audit Analyzer will be used. | |
-| | \-\-disableCocoapodsAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer will be used. | |
-| | \-\-disableSwiftPackageManagerAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Swift Package Manager Analyzer will be used. | |
-| | \-\-disableSwiftPackageResolvedAnalyzer| | Sets whether the [experimental](../analyzers/index.html) Swift Package Resolved Analyzer will be used. | |
-| | \-\-disableAutoconf | | Sets whether the [experimental](../analyzers/index.html) Autoconf Analyzer will be used. | |
-| | \-\-disableOpenSSL | | Sets whether the OpenSSL Analyzer will be used. | |
-| | \-\-disableCmake | | Sets whether the [experimental](../analyzers/index.html) Cmake Analyzer will be disabled. | |
-| | \-\-disableArchive | | Sets whether the Archive Analyzer will be disabled. | |
-| | \-\-zipExtensions | \ | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | |
-| | \-\-disableJar | | Sets whether the Jar Analyzer will be disabled. | |
-| | \-\-disableComposer | | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer will be disabled. | |
-| | \-\-disableCpan | | Sets whether the [experimental](../analyzers/index.html) Perl CPAN File Analyzer will be disabled. | |
-| | \-\-disableDart | | Sets whether the [experimental](../analyzers/index.html) Dart Analyzer will be disabled. | |
-| | \-\-disableOssIndex | | Sets whether the [OSS Index Analyzer](../analyzers/oss-index-analyzer.html) will be disabled. This analyzer requires an internet connection. | |
-| | \-\-disableOssIndexCache | | When the argument is present the OSS Index Analyzer will not cache results. By default results are cached for 24 hours. | |
-| | \-\-ossIndexUsername | \ | The optional username to connect to Sonatype's OSS Index. | |
-| | \-\-ossIndexPassword | \ | The optional password to connect to Sonatype's OSS Index. | |
-| | \-\-ossIndexRemoteErrorWarnOnly | \ | Whether we should only warn about Sonatype OSS Index remote errors instead of failing completely. | |
-| | \-\-ossIndexUrl | \ | Alternative URL for the OSS Index. If not set the public Sonatype OSS Index will be used. | https://ossindex.sonatype.org |
-| | \-\-disableCentral | | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Artifactory or Nexus Analyzer. | |
-| | \-\-disableCentralCache | | When the argument is present the Central Analyzer will not cache results locally. By default results are cached locally for 30 days. | |
-| | \-\-enableNexus | | Sets whether the Nexus Analyzer will be used (requires Nexus v2 or Pro v3). You can configure the Nexus URL to utilize an internally hosted Nexus server. | |
-| | \-\-enableArtifactory | | Sets whether Artifactory analyzer will be used | |
-| | \-\-artifactoryUrl | \ | The Artifactory server URL. |Â |
-| | \-\-artifactoryUseProxy | \ | Whether Artifactory should be accessed through a proxy or not. | false |
-| | \-\-artifactoryParallelAnalysis | \ | Whether the Artifactory analyzer should be run in parallel or not |Â true |
-| | \-\-artifactoryUsername | \ | The user name (only used with API token) to connect to Artifactory instance | |
-| | \-\-artifactoryApiToken | \ | The API token to connect to Artifactory instance, only used if the username or the API key are not defined by artifactoryAnalyzerServerId, artifactoryAnalyzerUsername or artifactoryAnalyzerApiToken. | |
-| | \-\-artifactoryBearerToken | \ | The bearer token to connect to Artifactory instance | |
-| | \-\-nexus | \ | The url to the Nexus Server's web service end point (example: http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | |
-| | \-\-nexusUser | \ | The username to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus Analyzer will use an unauthenticated connection. | |
-| | \-\-nexusPass | \ | The password to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus Analyzer will use an unauthenticated connection. | |
-| | \-\-nexusUsesProxy | \ | Whether or not the defined proxy should be used when connecting to Nexus. | true |
-| | \-\-disableNuspec | | Sets whether the .NET Nuget Nuspec Analyzer will be used. | |
-| | \-\-disableNugetconf | | Sets whether the [experimental](../analyzers/index.html) .NET Nuget packages.config Analyzer will be used. | |
-| | \-\-disableAssembly | | Sets whether the .NET Assembly Analyzer should be used. | |
-| | \-\-dotnet | \ | The path to dotnet core for .NET Assembly analysis on non-windows systems. | |
-| | \-\-disableGolangDep | | Sets whether the [experimental](../analyzers/index.html) Go Dependency Analyzer should be used. | |
-| | \-\-disableGolangMod | | Sets whether the [experimental](../analyzers/index.html) Go Mod Analyzer should be used. | |
-| | \-\-disableMixAudit | | Sets whether the [experimental](../analyzers/index.html) Elixir mix audit Analyze should be used. | |
-| | \-\-disablePoetry | | Sets whether the [experimental](../analyzers/index.html) Poetry Analyzer should be used. | |
-| | \-\-go | \ | The path to `go` executable for the Go Mode Analyzer; only necassary if `go` is not on the path. | |
-| | \-\-bundleAudit | | The path to the bundle-audit executable. | |
-| | \-\-bundleAuditWorkingDirectory | \ | The path to working directory that the bundle-audit command should be executed from when doing Gem bundle analysis. | |
-| | \-\-proxyserver | \ | The proxy server to use when downloading resources; see the [proxy configuration](../data/proxy.html) page for more information. | |
-| | \-\-proxyport | \ | The proxy port to use when downloading resources. | |
-| | \-\-nonProxyHosts | \ | The proxy exclusion list: hostnames (or patterns) for which proxy should not be used. Use pipe, comma or colon as list separator. Example: `something.com|*.something.com|www.somethingelse.*` | |
-| \-c | \-\-connectiontimeout | \ | The connection timeout (in milliseconds) to use when downloading resources. | 10000 |
-| | \-\-readtimeout | \ | The read timeout (in milliseconds) to use when downloading resources. | 60000 |
-| | \-\-proxypass | \ | The proxy password to use when downloading resources. | |
-| | \-\-proxyuser | \ | The proxy username to use when downloading resources. | |
-| | \-\-connectionString | \ | The connection string to the database. See using a [database server](../data/database.html). | |
-| | \-\-dbDriverName | \ | The database driver name. | |
-| | \-\-dbDriverPath | \ | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. | |
-| | \-\-dbPassword | \ | The password for connecting to the database. | |
-| | \-\-dbUser | \ | The username used to connect to the database. | |
-| \-d | \-\-data | \ | The location of the data directory used to store persistent data. This option should generally not be set. | |
-| | \-\-purge | | Delete the local copy of the NVD. This is used to force a refresh of the data. | |
-| | \-\-disableHostedSuppressions | | Whether the usage of the hosted suppressions file will be disabled. | false |
-| | \-\-hostedSuppressionsForceUpdate | | Whether the hosted suppressions file will update regardless of the `noupdate` argument. | false |
-| | \-\-hostedSuppressionsValidForHours | \ | The number of hours to wait before checking for new updates of the hosted suppressions file | 2 |
-| | \-\-hostedSuppressionsUrl | \ | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://jeremylong.github.io/DependencyCheck/suppressions/publishedSuppressions.xml |
+| Short | Argument Name | Parameter | Description | Default Value |
+|-------|-----------------------------------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| | \-\-nvdApiKey | \ | The API Key to access the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key | |
+| | \-\-nvdApiEndpoint | \ | The NVD API endpoint URL; setting this is uncommon. | https://services.nvd.nist.gov/rest/json/cves/2.0 |
+| | \-\-nvdMaxRetryCount | \ | The maximum number of retry requests for a single call to the NVD API. | 10 |
+| | \-\-nvdApiDelay | \ | The number of milliseconds to wait between calls to the NVD API. | 3500 with an NVD API Key or 8000 without an API Key |
+| | \-\-nvdApiResultsPerPage | \ | The number records for a single page from NVD API (must be <=2000). | 2000 |
+| | \-\-nvdDatafeed | \ | The URL for the NVD API Data feed that can be generated using https://github.com/jeremylong/open-vulnerability-cli/blob/main/README.md#mirroring-the-nvd-cve-data - example value `https://internal.server/cache/nvdcve-{0}.json.gz` | |
+| | \-\-nvdUser | \ | Credentials used for basic authentication for the NVD API Data feed. | |
+| | \-\-nvdPassword | \ | Credentials used for basic authentication for the NVD API Data feed. | |
+| | \-\-nvdBearerToken | \ | Credentials used for bearer authentication for the NVD API Data feed. | |
+| | \-\-nvdValidForHours | \ | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | 4 |
+| | \-\-hints | \ | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) | |
+| \-P | \-\-propertyfile | \ | Specifies a file that contains properties to use instead of application defaults. The key values used in the properties file are not the same as the arguments listed on this page; use the keys here: https://github.com/dependency-check/DependencyCheck/blob/main/core/src/main/resources/dependencycheck.properties | |
+| | \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. | |
+| | \-\-disableKnownExploited | | Sets whether the Known Exploited Vulnerability update and analyzer are enabled. | |
+| | \-\-kevURL | \ | URL to the CISA Known Exploited Vulnerabilities JSON data feed. | https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
+| | \-\-kevUser | \ | Credentials used for basic authentication for the CISA Known Exploited Vulnerabilities JSON data feed. | |
+| | \-\-kevPassword | \ | Credentials used for basic authentication for URL to the CISA Known Exploited Vulnerabilities JSON data feed. | |
+| | \-\-kevBearerToken | \ | Credentials used for bearer authentication for URL to the CISA Known Exploited Vulnerabilities JSON data feed. | |
+| | \-\-disableFileName | | Disables the File Name Analyzer; in generally, this should not be disabled. | |
+| | \-\-disablePyDist | | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | |
+| | \-\-disablePyPkg | | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | |
+| | \-\-disableMSBuild | | Sets whether the MS Build Project Analyzer will be used. | |
+| | \-\-disableNodeJS | | Sets whether the Node.js Package Analyzer will be used. | |
+| | \-\-disableYarnAudit | | Sets whether the yarn Audit Analyzer will be used. This analyzer requires an internet connection and that yarn is installed. Use `--nodeAuditSkipDevDependencies` to skip dev dependencies. | |
+| | \-\-yarn | \ | The path to `yarn`. | |
+| | \-\-disablePnpmAudit | | Sets whether the pnpm Audit Analyzer will be used. This analyzer requires an internet connection and that pnpm is installed. Use `--nodeAuditSkipDevDependencies` to skip dev dependencies. | |
+| | \-\-pnpm | \ | The path to `pnpm`. | |
+| | \-\-disableNodeAudit | | Sets whether the Node Audit Analyzer will be used. This analyzer requires an internet connection. | |
+| | \-\-disableNodeAuditCache | | When the argument is present the Node Audit Analyzer will not cache results. By default the results are cached for 24 hours. | |
+| | \-\-nodeAuditSkipDevDependencies | | Configures the Node Audit Analyzer to skip devDependencies. | |
+| | \-\-nodePackageSkipDevDependencies | | Configures the Node Package Analyzer to skip devDependencies. | |
+| | \-\-disableRetireJS | | Sets whether the RetireJS Analyzer will be used. | |
+| | \-\-retireJsForceUpdate | | Sets whether the RetireJS Analyzer will update regardless of the `noupdate` argument. | false |
+| | \-\-retireJsUrl | \ | The URL to the Retire JS repository. | https://raw.githubusercontent.com/Retirejs/retire.js/master/repository/jsrepository.json |
+| | \-\-retirejsFilter | \ | The RetireJS Analyzers content filter used to exclude JS files when the content contains the given regular expression; this option can be specified multiple times. | |
+| | \-\-retirejsFilterNonVulnerable | | Specifies that the Retire JS Analyzer should filter out non-vulnerable JS files from the report. | |
+| | \-\-retireJsUrlUser | \ | Credentials used for basic authentication for the RetireJS data. | |
+| | \-\-retirejsUrlPassword | \ | Credentials used for basic authentication for the RetireJS data. | |
+| | \-\-retirejsUrlBearerToken | \ | Credentials used for bearer authentication for the RetireJS data. | |
+| | \-\-disableRubygems | | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | |
+| | \-\-disableBundleAudit | | Sets whether the [experimental](../analyzers/index.html) Ruby Bundler Audit Analyzer will be used. | |
+| | \-\-disableCocoapodsAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer will be used. | |
+| | \-\-disableCarthageAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Carthage Analyzer will be used. | |
+| | \-\-disableSwiftPackageManagerAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Swift Package Manager Analyzer will be used. | |
+| | \-\-disableSwiftPackageResolvedAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Swift Package Resolved Analyzer will be used. | |
+| | \-\-disableAutoconf | | Sets whether the [experimental](../analyzers/index.html) Autoconf Analyzer will be used. | |
+| | \-\-disableOpenSSL | | Sets whether the OpenSSL Analyzer will be used. | |
+| | \-\-disableCmake | | Sets whether the [experimental](../analyzers/index.html) Cmake Analyzer will be disabled. | |
+| | \-\-disableArchive | | Sets whether the Archive Analyzer will be disabled. | |
+| | \-\-zipExtensions | \ | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | |
+| | \-\-disableJar | | Sets whether the Jar Analyzer will be disabled. | |
+| | \-\-disableComposer | | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer will be disabled. | |
+| | \-\-composerSkipDev | | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should skip "packages-dev". | |
+| | \-\-disableCpan | | Sets whether the [experimental](../analyzers/index.html) Perl CPAN File Analyzer will be disabled. | |
+| | \-\-disableDart | | Sets whether the [experimental](../analyzers/index.html) Dart Analyzer will be disabled. | |
+| | \-\-disableOssIndex | | Sets whether the [OSS Index Analyzer](../analyzers/oss-index-analyzer.html) will be disabled. This analyzer requires an internet connection. | |
+| | \-\-disableOssIndexCache | | When the argument is present the OSS Index Analyzer will not cache results. By default results are cached for 24 hours. | |
+| | \-\-ossIndexUsername | \ | To authenticate Sonatype OSS Index requests and profit from higher rate limits, provide the OSS account email address as username. Provide both a username _and_ a password (see below) or none. | |
+| | \-\-ossIndexPassword | \ | Password or API token to connect to Sonatype's OSS Index. Provide both a username (see above) _and_ a password or none. | |
+| | \-\-ossIndexRemoteErrorWarnOnly | \ | Whether we should only warn about Sonatype OSS Index remote errors instead of failing completely. | |
+| | \-\-ossIndexUrl | \ | Alternative URL for the OSS Index. If not set the public Sonatype OSS Index will be used. | https://ossindex.sonatype.org |
+| | \-\-disableCentral | | Sets whether the Central Analyzer will be used to enrich Java dependencies. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled, you can use the Artifactory Analyzer or Nexus Analyzer as a replacement. | |
+| | \-\-disableCentralCache | | When the argument is present the Central Analyzer will not cache results locally. By default results are cached locally for 30 days. | |
+| | \-\-centralUrl | | Alternative URL for Maven Central Search. If not set the public Sonatype Maven Central will be used. | https://search.maven.org/solrsearch/select |
+| | \-\-centralUsername | \ | The username to authenticate with bearer auth to the alternative Maven Central url set by the 'centralUrl' argument. If neither basic nor bearer auth config is set it will use an unauthenticated connection. | |
+| | \-\-centralPassword | \ | The password to authenticate with bearer auth to the alternative Maven Central url set by the 'centralUrl' argument. If neither basic nor bearer auth config is set it will use an unauthenticated connection. | |
+| | \-\-centralBearerToken | \ | The token to authenticate with bearer auth to the alternative Maven Central url set by the 'centralUrl' argument. If neither basic nor bearer auth config is set it will use an unauthenticated connection. | |
+| | \-\-enableNexus | | Sets whether Nexus Analyzer will be used. This analyzer is an alternative to the Central or Artifactory Analyzers, allowing retrieval from Sonatype Nexus installations. | |
+| | \-\-enableArtifactory | | Sets whether Artifactory analyzer will be used to enrich Java dependencies. **To use Artifactory, you will need to disable the central analyzer by adding the --disableCentral parameter.** | |
+| | \-\-artifactoryUrl | \ | The Artifactory server URL. | |
+| | \-\-artifactoryUseProxy | \ | Whether Artifactory should be accessed through a proxy or not. | false |
+| | \-\-artifactoryParallelAnalysis | \ | Whether the Artifactory analyzer should be run in parallel or not | true |
+| | \-\-artifactoryUsername | \ | The user name (only used with API token) to connect to Artifactory instance | |
+| | \-\-artifactoryApiToken | \ | The API token to connect to Artifactory instance, only used if the username or the API key are not defined by artifactoryAnalyzerServerId, artifactoryAnalyzerUsername or artifactoryAnalyzerApiToken. | |
+| | \-\-artifactoryBearerToken | \ | The bearer token to connect to Artifactory instance | |
+| | \-\-nexus | \ | The url to the Nexus Server's web service end point (example: http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | |
+| | \-\-nexusUser | \ | The username to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus Analyzer will use an unauthenticated connection. | |
+| | \-\-nexusPass | \ | The password to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus Analyzer will use an unauthenticated connection. | |
+| | \-\-nexusUsesProxy | \ | Whether or not the defined proxy should be used when connecting to Nexus. | true |
+| | \-\-disableNuspec | | Sets whether the .NET Nuget Nuspec Analyzer will be used. | |
+| | \-\-disableNugetconf | | Sets whether the [experimental](../analyzers/index.html) .NET Nuget packages.config Analyzer will be used. | |
+| | \-\-disableAssembly | | Sets whether the .NET Assembly Analyzer should be used. | |
+| | \-\-dotnet | \ | The path to dotnet core for .NET Assembly analysis on non-windows systems. | |
+| | \-\-disableGolangDep | | Sets whether the [experimental](../analyzers/index.html) Go Dependency Analyzer should be used. | |
+| | \-\-disableGolangMod | | Sets whether the [experimental](../analyzers/index.html) Go Mod Analyzer should be used. | |
+| | \-\-disableMixAudit | | Sets whether the [experimental](../analyzers/index.html) Elixir mix audit Analyze should be used. | |
+| | \-\-disablePoetry | | Sets whether the [experimental](../analyzers/index.html) Poetry Analyzer should be used. | |
+| | \-\-disableVersionCheck | | Sets whether dependency-check should check if a new version is available. | |
+| | \-\-go | \ | The path to `go` executable for the Go Mode Analyzer; only necessary if `go` is not on the path. | |
+| | \-\-bundleAudit | | The path to the bundle-audit executable. | |
+| | \-\-bundleAuditWorkingDirectory | \ | The path to working directory that the bundle-audit command should be executed from when doing Gem bundle analysis. | |
+| | \-\-proxyserver | \ | The proxy server to use when downloading resources; see the [proxy configuration](../data/proxy.html) page for more information. | |
+| | \-\-proxyport | \ | The proxy port to use when downloading resources. | |
+| | \-\-nonProxyHosts | \ | The proxy exclusion list: hostnames (or patterns) for which proxy should not be used. Use pipe, comma or colon as list separator. Example: `something.com\|*.something.com\|www.somethingelse.*` | |
+| \-c | \-\-connectiontimeout | \ | The connection timeout (in milliseconds) to use when downloading resources. | 10000 |
+| | \-\-readtimeout | \ | The read timeout (in milliseconds) to use when downloading resources. | 60000 |
+| | \-\-proxypass | \ | The proxy password to use when downloading resources. | |
+| | \-\-proxyuser | \ | The proxy username to use when downloading resources. | |
+| | \-\-connectionString | \ | The connection string to the database. See using a [database server](../data/database.html). | |
+| | \-\-dbDriverName | \ | The database driver full classname; note, only needs to be set if the driver is not JDBC4 compliant or the JAR is outside of the class path. | |
+| | \-\-dbDriverPath | \ | The path to the database driver; note, this does not need to be set unless the JAR is outside of the class path. | |
+| | \-\-dbPassword | \ | The password for connecting to the database. | |
+| | \-\-dbUser | \ | The username used to connect to the database. | |
+| \-d | \-\-data | \ | The location of the data directory used to store persistent data. | /usr/local/var/dependencycheck if installed through brew (→ [formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/d/dependency-check.rb#L29)). Otherwise, the data directory is created inside the install directory i.e. as a sibling to the `/bin`, `/lib` directories. |
+| | \-\-purge | | Delete the local copy of the NVD. This is used to force a refresh of the data. | |
+| | \-\-disableHostedSuppressions | | Whether the usage of the hosted suppressions file will be disabled. | false |
+| | \-\-hostedSuppressionsForceUpdate | | Whether the hosted suppressions file will update regardless of the `noupdate` argument. | false |
+| | \-\-hostedSuppressionsValidForHours | \ | The number of hours to wait before checking for new updates of the hosted suppressions file | 2 |
+| | \-\-hostedSuppressionsUrl | \ | The URL to a mirrored copy of the hosted suppressions file for internet-constrained environments | https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml |
+| | \-\-hostedSuppressionsUser | \ | The user for basic authentication to a mirrored copy of the hosted suppressions file | |
+| | \-\-hostedSuppressionsPassword | \ | The password for basic authentication to a mirrored copy of the hosted suppressions file | |
+| | \-\-hostedSuppressionsBearerToken | \ | The token for bearer authentication to a mirrored copy of the hosted suppressions file | |
+| | \-\-suppressionUser | \ | The user for basic authentication to web-hosted suppression XML files (as configured with `--suppression`) | |
+| | \-\-suppressionPassword | \ | The password for basic authentication to web-hosted suppression XML files (as configured with `--suppression`) | |
+| | \-\-suppressionBearerToken | \ | The token for bearer authentication to web-hosted suppression XML files (as configured with `--suppression`) | |
diff --git a/cli/src/site/markdown/index.md.vm b/cli/src/site/markdown/index.md.vm
index cc8a23b0aa1..fdb675ad605 100644
--- a/cli/src/site/markdown/index.md.vm
+++ b/cli/src/site/markdown/index.md.vm
@@ -7,8 +7,8 @@ identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
Installation & Usage
====================
-Import the GPG key used to sign all Dependency Check releases: `gpg --keyserver hkp://keys.gnupg.net --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED`.
-Download the dependency-check command line tool the [GitHub Release](https://github.com/jeremylong/DependencyCheck/releases/download/v${project.version}/dependency-check-${project.version}-release.zip) and the associated GPG signature file from the [GitHub Release](https://github.com/jeremylong/DependencyCheck/releases/download/v${project.version}/dependency-check-${project.version}-release.zip.asc).
+Import the GPG key used to sign all Dependency Check releases: `gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED`.
+Download the dependency-check command line tool the [GitHub Release](https://github.com/dependency-check/DependencyCheck/releases/download/v${project.version}/dependency-check-${project.version}-release.zip) and the associated GPG signature file from the [GitHub Release](https://github.com/dependency-check/DependencyCheck/releases/download/v${project.version}/dependency-check-${project.version}-release.zip.asc).
Verify the cryptographic integrity of your download: `gpg --verify dependency-check-${project.version}-release.zip.asc`.
Extract the zip file to a location on your computer and put the 'bin' directory into the
path environment variable.
@@ -51,4 +51,4 @@ the JAR files the directory.
- repos
- data
- plugins
-```
\ No newline at end of file
+```
diff --git a/cli/src/site/site.xml b/cli/src/site/site.xml
index 30cd83a0937..87e2776f51f 100644
--- a/cli/src/site/site.xml
+++ b/cli/src/site/site.xml
@@ -16,11 +16,11 @@ limitations under the License.
Copyright (c) 2013 Jeremy Long. All Rights Reserved.
-->
-
+
- OWASP dependency-check-cli
- OWASP dependency-check-cli
- ./images/dc-cli.svg
+
@@ -31,5 +31,6 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+
]]>
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/cli/src/test/java/org/owasp/dependencycheck/AppTest.java b/cli/src/test/java/org/owasp/dependencycheck/AppTest.java
index 4e8ca751be4..45f10d8c2cb 100644
--- a/cli/src/test/java/org/owasp/dependencycheck/AppTest.java
+++ b/cli/src/test/java/org/owasp/dependencycheck/AppTest.java
@@ -17,35 +17,34 @@
*/
package org.owasp.dependencycheck;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.UnrecognizedOptionException;
+import org.junit.jupiter.api.Test;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.Settings.KEYS;
import java.io.File;
import java.io.FileNotFoundException;
-import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.UnrecognizedOptionException;
import static org.hamcrest.MatcherAssert.assertThat;
-import org.junit.Assert;
-import org.junit.Test;
-import org.owasp.dependencycheck.utils.InvalidSettingException;
-import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.utils.Settings.KEYS;
+import static org.hamcrest.core.Is.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests for the {@link AppTest} class.
*/
-public class AppTest extends BaseTest {
+class AppTest extends BaseTest {
/**
* Test of ensureCanonicalPath method, of class App.
*/
@Test
- public void testEnsureCanonicalPath() {
+ void testEnsureCanonicalPath() {
String file = "../*.jar";
App instance = new App(getSettings());
String result = instance.ensureCanonicalPath(file);
@@ -55,7 +54,7 @@ public void testEnsureCanonicalPath() {
file = "../some/skip/../path/file.txt";
String expResult = "/some/path/file.txt";
result = instance.ensureCanonicalPath(file);
- assertTrue("result=" + result, result.endsWith(expResult));
+ assertTrue(result.endsWith(expResult), "result=" + result);
}
/**
@@ -65,7 +64,7 @@ public void testEnsureCanonicalPath() {
* @throws Exception the unexpected {@link Exception}.
*/
@Test
- public void testPopulateSettings() throws Exception {
+ void testPopulateSettings() throws Exception {
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
String[] args = {"-P", prop.getAbsolutePath()};
Map expected = new HashMap<>();
@@ -115,13 +114,12 @@ public void testPopulateSettings() throws Exception {
* Assert that an {@link UnrecognizedOptionException} is thrown when a
* property that is not supported is specified on the CLI.
*
- * @throws Exception the unexpected {@link Exception}.
*/
@Test
- public void testPopulateSettingsException() throws Exception {
+ void testPopulateSettingsException() {
String[] args = {"-invalidPROPERTY"};
- Exception exception = Assert.assertThrows(UnrecognizedOptionException.class, () -> testBooleanProperties(args, null));
- Assert.assertTrue(exception.getMessage().contains("Unrecognized option: -invalidPROPERTY"));
+ UnrecognizedOptionException exception = assertThrows(UnrecognizedOptionException.class, () -> testBooleanProperties(args, null));
+ assertTrue(exception.getMessage().contains("Unrecognized option: -invalidPROPERTY"));
}
/**
@@ -130,7 +128,7 @@ public void testPopulateSettingsException() throws Exception {
* @throws Exception the unexpected {@link Exception}.
*/
@Test
- public void testPopulatingSuppressionSettingsWithASingleFile() throws Exception {
+ void testPopulatingSuppressionSettingsWithASingleFile() throws Exception {
// GIVEN CLI properties with the mandatory arguments
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
@@ -154,7 +152,7 @@ public void testPopulatingSuppressionSettingsWithASingleFile() throws Exception
* @throws Exception the unexpected {@link Exception}.
*/
@Test
- public void testPopulatingSuppressionSettingsWithMultipleFiles() throws Exception {
+ void testPopulatingSuppressionSettingsWithMultipleFiles() throws Exception {
// GIVEN CLI properties with the mandatory arguments
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
@@ -171,95 +169,8 @@ public void testPopulatingSuppressionSettingsWithMultipleFiles() throws Exceptio
assertThat("Expected the suppression files to be set in the Settings with a separator", getSettings().getString(KEYS.SUPPRESSION_FILE), is("[\"first-file.xml\",\"another-file.xml\"]"));
}
- @Test
- public void testPopulateSettingsShouldSetDefaultValueToCveUrlModified() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Settings settings = getSettings();
- final App app = new App(settings);
-
- String[] args = {"--cveUrlBase", "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz"};
- final CliParser parser = new CliParser(settings);
- parser.parse(args);
-
- // When
- app.populateSettings(parser);
-
- // Then
- String output = settings.getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to a default of the same model", output, is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldSetDefaultValueToCveUrlModifiedWhenCveUrlModifiedIsEmpty() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Settings settings = getSettings();
- final App app = new App(settings);
-
- String[] args = {"--cveUrlBase", "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz", "--cveUrlModified", ""};
- final CliParser parser = new CliParser(settings);
- parser.parse(args);
-
- // When
- app.populateSettings(parser);
-
- // Then
- String output = settings.getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to a default of the same model when arg is empty", output, is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldNotSetDefaultValueToCveUrlModifiedWhenValueIsExplicitelySet() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Settings settings = getSettings();
- final App app = new App(settings);
-
- String[] args = {"--cveUrlBase", "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/some-unusual-file-name-%d.json.gz", "--cveUrlModified", "https://another-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz"};
- final CliParser parser = new CliParser(settings);
- parser.parse(args);
-
- // When
- app.populateSettings(parser);
-
- // Then
- String output = settings.getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://another-custom-mirror-of-nvd/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must be set to the specified value", output, is(expectedOutput));
- }
-
- @Test
- public void testPopulateSettingsShouldNotSetDefaultValueToCveUrlModifiedWhenUnknownValueIsSet() throws Exception {
- // Given
- System.clearProperty(Settings.KEYS.CVE_MODIFIED_JSON);
- System.clearProperty(Settings.KEYS.CVE_BASE_JSON);
-
- final Settings settings = getSettings();
- final App app = new App(settings);
-
- String[] args = {"--cveUrlBase", "https://my-custom-mirror-of-nvd/feeds/json/cve/1.1/some-unusual-file-name-%d.json.gz"};
- final CliParser parser = new CliParser(settings);
- parser.parse(args);
-
- // When
- app.populateSettings(parser);
-
- // Then
- String output = settings.getString(Settings.KEYS.CVE_MODIFIED_JSON);
- String expectedOutput = "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz";
- assertThat("cveUrlModified must not be set when name is not the same as from the nvd datasource", output, is(expectedOutput));
- }
- private boolean testBooleanProperties(String[] args, Map expected) throws URISyntaxException, FileNotFoundException, ParseException, InvalidSettingException {
+ private boolean testBooleanProperties(String[] args, Map expected) throws FileNotFoundException, ParseException, InvalidSettingException {
this.reloadSettings();
final CliParser cli = new CliParser(getSettings());
cli.parse(args);
diff --git a/cli/src/test/java/org/owasp/dependencycheck/BaseTest.java b/cli/src/test/java/org/owasp/dependencycheck/BaseTest.java
index b486fa6a089..072baf8593b 100644
--- a/cli/src/test/java/org/owasp/dependencycheck/BaseTest.java
+++ b/cli/src/test/java/org/owasp/dependencycheck/BaseTest.java
@@ -15,8 +15,8 @@
*/
package org.owasp.dependencycheck;
-import org.junit.After;
-import org.junit.Before;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -33,7 +33,7 @@ public abstract class BaseTest {
/**
* Initialize the {@link Settings}.
*/
- @Before
+ @BeforeEach
public void setUp() {
settings = new Settings();
}
@@ -41,7 +41,7 @@ public void setUp() {
/**
* Clean the {@link Settings}.
*/
- @After
+ @AfterEach
public void tearDown() {
settings.cleanup(true);
}
diff --git a/cli/src/test/java/org/owasp/dependencycheck/CliParserTest.java b/cli/src/test/java/org/owasp/dependencycheck/CliParserTest.java
index 6800f4c4489..f92288c6ade 100644
--- a/cli/src/test/java/org/owasp/dependencycheck/CliParserTest.java
+++ b/cli/src/test/java/org/owasp/dependencycheck/CliParserTest.java
@@ -17,21 +17,28 @@
*/
package org.owasp.dependencycheck;
+import org.apache.commons.cli.ParseException;
+import org.junit.jupiter.api.Test;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
+
import static java.nio.charset.StandardCharsets.UTF_8;
-import org.apache.commons.cli.ParseException;
-import org.junit.Assert;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/**
*
* @author Jeremy Long
*/
-public class CliParserTest extends BaseTest {
+class CliParserTest extends BaseTest {
/**
* Test of parse method, of class CliParser.
@@ -39,7 +46,7 @@ public class CliParserTest extends BaseTest {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse() throws Exception {
+ void testParse() throws Exception {
String[] args = {};
@@ -49,9 +56,9 @@ public void testParse() throws Exception {
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
@@ -60,16 +67,16 @@ public void testParse() throws Exception {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_help() throws Exception {
+ void testParse_help() throws Exception {
String[] args = {"-help"};
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertTrue(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertFalse(instance.isGetVersion());
+ assertTrue(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
@@ -78,38 +85,35 @@ public void testParse_help() throws Exception {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_version() throws Exception {
+ void testParse_version() throws Exception {
String[] args = {"-version"};
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertTrue(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertTrue(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
* Test of parse method with failOnCVSS without an argument
*
- * @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_failOnCVSSNoArg() throws Exception {
+ void testParse_failOnCVSSNoArg() {
String[] args = {"--failOnCVSS"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("an argument for failOnCVSS was missing and an exception was not thrown");
- } catch (ParseException ex) {
- Assert.assertTrue(ex.getMessage().contains("Missing argument"));
- }
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ ParseException ex = assertThrows(ParseException.class, () -> instance.parse(args),
+ "an argument for failOnCVSS was missing and an exception was not thrown");
+ assertTrue(ex.getMessage().contains("Missing argument"));
+
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
@@ -119,16 +123,16 @@ public void testParse_failOnCVSSNoArg() throws Exception {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_failOnCVSSInvalidArgument() throws Exception {
+ void testParse_failOnCVSSInvalidArgument() throws Exception {
String[] args = {"--failOnCVSS", "bad"};
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertEquals("Default should be 11", 11.0, instance.getFailOnCVSS(), 0);
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertEquals(11.0, instance.getFailOnCVSS(), 0, "Default should be 11");
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
@@ -138,25 +142,24 @@ public void testParse_failOnCVSSInvalidArgument() throws Exception {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_failOnCVSSValidArgument() throws Exception {
+ void testParse_failOnCVSSValidArgument() throws Exception {
String[] args = {"--failOnCVSS", "6"};
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertEquals(6.0, instance.getFailOnCVSS(), 0);
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertEquals(6.0, instance.getFailOnCVSS(), 0);
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
* Test of parse method with jar and cpe args, of class CliParser.
*
- * @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_unknown() throws Exception {
+ void testParse_unknown() {
String[] args = {"-unknown"};
@@ -167,62 +170,53 @@ public void testParse_unknown() throws Exception {
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("Unrecognized option should have caused an exception");
- } catch (ParseException ex) {
- Assert.assertTrue(ex.getMessage().contains("Unrecognized option"));
- }
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ ParseException ex = assertThrows(ParseException.class, () -> instance.parse(args) ,
+ "Unrecognized option should have caused an exception");
+ assertTrue(ex.getMessage().contains("Unrecognized option"));
+
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
* Test of parse method with scan arg, of class CliParser.
*
- * @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_scan() throws Exception {
+ void testParse_scan() {
String[] args = {"-scan"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("Missing argument should have caused an exception");
- } catch (ParseException ex) {
- Assert.assertTrue(ex.getMessage().contains("Missing argument"));
- }
+ ParseException ex = assertThrows(ParseException.class, () -> instance.parse(args),
+ "Missing argument should have caused an exception");
+ assertTrue(ex.getMessage().contains("Missing argument"));
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
* Test of parse method with jar arg, of class CliParser.
*
- * @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_scan_unknownFile() throws Exception {
+ void testParse_scan_unknownFile() {
String[] args = {"-scan", "jar.that.does.not.exist", "--project", "test"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("An exception should have been thrown");
- } catch (FileNotFoundException ex) {
- Assert.assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
- }
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertFalse(instance.isRunScan());
+ FileNotFoundException ex = assertThrows(FileNotFoundException.class, () -> instance.parse(args),
+ "An exception should have been thrown");
+ assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
+
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertFalse(instance.isRunScan());
}
/**
@@ -231,28 +225,27 @@ public void testParse_scan_unknownFile() throws Exception {
* @throws Exception thrown when an exception occurs.
*/
@Test
- public void testParse_scan_withFileExists() throws Exception {
+ void testParse_scan_withFileExists() throws Exception {
File path = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
String[] args = {"--scan", path.getCanonicalPath(), "--out", "./", "--project", "test"};
CliParser instance = new CliParser(getSettings());
instance.parse(args);
- Assert.assertEquals(path.getCanonicalPath(), instance.getScanFiles()[0]);
+ assertEquals(path.getCanonicalPath(), instance.getScanFiles()[0]);
- Assert.assertFalse(instance.isGetVersion());
- Assert.assertFalse(instance.isGetHelp());
- Assert.assertTrue(instance.isRunScan());
+ assertFalse(instance.isGetVersion());
+ assertFalse(instance.isGetHelp());
+ assertTrue(instance.isRunScan());
}
/**
* Test of printVersionInfo, of class CliParser.
*
- * @throws Exception thrown when an exception occurs.
*/
@Test
@SuppressWarnings("StringSplitter")
- public void testParse_printVersionInfo() throws Exception {
+ void testParse_printVersionInfo() {
PrintStream out = System.out;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -262,14 +255,14 @@ public void testParse_printVersionInfo() throws Exception {
instance.printVersionInfo();
try {
baos.flush();
- String text = new String(baos.toByteArray(), UTF_8).toLowerCase();
- String[] lines = text.split(System.getProperty("line.separator"));
- Assert.assertTrue(lines.length >= 1);
- Assert.assertTrue(text.contains("version"));
- Assert.assertFalse(text.contains("unknown"));
+ String text = baos.toString(UTF_8).toLowerCase();
+ String[] lines = text.split(System.lineSeparator());
+ assertTrue(lines.length >= 1);
+ assertTrue(text.contains("version"));
+ assertFalse(text.contains("unknown"));
} catch (IOException ex) {
System.setOut(out);
- Assert.fail("CliParser.printVersionInfo did not write anything to system.out.");
+ fail("CliParser.printVersionInfo did not write anything to system.out.", ex);
} finally {
System.setOut(out);
}
@@ -282,7 +275,7 @@ public void testParse_printVersionInfo() throws Exception {
*/
@Test
@SuppressWarnings("StringSplitter")
- public void testParse_printHelp() throws Exception {
+ void testParse_printHelp() throws Exception {
PrintStream out = System.out;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -297,13 +290,13 @@ public void testParse_printHelp() throws Exception {
instance.printHelp();
try {
baos.flush();
- String text = (new String(baos.toByteArray(), UTF_8));
- String[] lines = text.split(System.getProperty("line.separator"));
- Assert.assertTrue(lines[0].startsWith("usage: "));
- Assert.assertTrue((lines.length > 2));
+ String text = (baos.toString(UTF_8));
+ String[] lines = text.split(System.lineSeparator());
+ assertTrue(lines[0].startsWith("usage: "));
+ assertTrue((lines.length > 2));
} catch (IOException ex) {
System.setOut(out);
- Assert.fail("CliParser.printVersionInfo did not write anything to system.out.");
+ fail("CliParser.printVersionInfo did not write anything to system.out.");
} finally {
System.setOut(out);
}
@@ -313,70 +306,66 @@ public void testParse_printHelp() throws Exception {
* Test of getBooleanArgument method, of class CliParser.
*/
@Test
- public void testGetBooleanArgument() throws ParseException {
+ void testGetBooleanArgument() {
String[] args = {"--scan", "missing.file", "--artifactoryUseProxy", "false", "--artifactoryParallelAnalysis", "true", "--project", "test"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("invalid scan should have caused an error");
- } catch (FileNotFoundException ex) {
- Assert.assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
- }
+
+ FileNotFoundException ex = assertThrows(FileNotFoundException.class, () -> instance.parse(args),
+ "invalid scan should have caused an error");
+ assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
+
boolean expResult;
Boolean result = instance.getBooleanArgument("missingArgument");
- Assert.assertNull(result);
+ assertNull(result);
expResult = false;
result = instance.getBooleanArgument(CliParser.ARGUMENT.ARTIFACTORY_USES_PROXY);
- Assert.assertEquals(expResult, result);
+ assertEquals(expResult, result);
expResult = true;
result = instance.getBooleanArgument(CliParser.ARGUMENT.ARTIFACTORY_PARALLEL_ANALYSIS);
- Assert.assertEquals(expResult, result);
+ assertEquals(expResult, result);
}
/**
* Test of getStringArgument method, of class CliParser.
*/
@Test
- public void testGetStringArgument() throws ParseException {
+ void testGetStringArgument() {
String[] args = {"--scan", "missing.file", "--artifactoryUsername", "blue42", "--project", "test"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("invalid scan argument should have caused an exception");
- } catch (FileNotFoundException ex) {
- Assert.assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
- }
+
+ FileNotFoundException ex = assertThrows(FileNotFoundException.class, () -> instance.parse(args),
+ "invalid scan argument should have caused an exception");
+ assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
+
String expResult;
String result = instance.getStringArgument("missingArgument");
- Assert.assertNull(result);
+ assertNull(result);
expResult = "blue42";
result = instance.getStringArgument(CliParser.ARGUMENT.ARTIFACTORY_USERNAME);
- Assert.assertEquals(expResult, result);
+ assertEquals(expResult, result);
}
@Test
- public void testHasOption() throws ParseException {
+ void testHasOption() {
String[] args = {"--scan", "missing.file", "--artifactoryUsername", "blue42", "--project", "test"};
CliParser instance = new CliParser(getSettings());
- try {
- instance.parse(args);
- Assert.fail("invalid scan argument should have caused an exception");
- } catch (FileNotFoundException ex) {
- Assert.assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
- }
+
+ FileNotFoundException ex = assertThrows(FileNotFoundException.class, () -> instance.parse(args),
+ "invalid scan argument should have caused an exception");
+ assertTrue(ex.getMessage().contains("Invalid 'scan' argument"));
Boolean result = instance.hasOption("missingOption");
- Assert.assertNull(result);
+ assertNull(result);
Boolean expResult = true;
result = instance.hasOption(CliParser.ARGUMENT.PROJECT);
- Assert.assertEquals(expResult, result);
+ assertEquals(expResult, result);
}
}
diff --git a/cli/src/test/resources/sample.properties b/cli/src/test/resources/sample.properties
index a8595dee200..ca09248d7dd 100644
--- a/cli/src/test/resources/sample.properties
+++ b/cli/src/test/resources/sample.properties
@@ -21,6 +21,7 @@ analyzer.openssl.enabled=true
analyzer.central.enabled=true
analyzer.nexus.enabled=false
analyzer.cocoapods.enabled=true
+analyzer.carthage.enabled=true
analyzer.swift.package.manager.enabled=true
#whether the nexus analyzer uses the proxy
analyzer.nexus.proxy=true
diff --git a/cli/src/test/resources/sample2.properties b/cli/src/test/resources/sample2.properties
index e94af3186bd..859ede41042 100644
--- a/cli/src/test/resources/sample2.properties
+++ b/cli/src/test/resources/sample2.properties
@@ -21,6 +21,7 @@ analyzer.openssl.enabled=false
analyzer.central.enabled=false
analyzer.nexus.enabled=true
analyzer.cocoapods.enabled=false
+analyzer.carthage.enabled=false
analyzer.swift.package.manager.enabled=false
#whether the nexus analyzer uses the proxy
analyzer.nexus.proxy=false
diff --git a/core/README.md b/core/README.md
index b05b6e327e2..1b6c759cb08 100644
--- a/core/README.md
+++ b/core/README.md
@@ -8,10 +8,12 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
-Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/main/LICENSE.txt) file for the full license.
+Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/dependency-check/DependencyCheck/main/LICENSE.txt) file for the full license.
Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt][notices] file for more information.
- [wiki]: https://github.com/jeremylong/DependencyCheck/wiki
- [notices]: https://github.com/jeremylong/DependencyCheck/blob/main/NOTICE.txt
+ [wiki]: https://github.com/dependency-check/DependencyCheck/wiki
+ [notices]: https://github.com/dependency-check/DependencyCheck/blob/main/NOTICE.txt
+
+
\ No newline at end of file
diff --git a/core/pom.xml b/core/pom.xml
index cd0d820b391..05407c13ead 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.owaspdependency-check-parent
- 8.2.2-SNAPSHOT
+ 12.1.9-SNAPSHOTdependency-check-core
@@ -29,9 +29,9 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
Dependency-Check Coredependency-check-core is the engine and reporting tool used to identify and report if there are any known, publicly disclosed vulnerabilities in the scanned project's dependencies. The engine extracts meta-data from the dependencies and uses this to do fuzzy key-word matching against the Common Platfrom Enumeration (CPE), if any CPE identifiers are found the associated Common Vulnerability and Exposure (CVE) entries are added to the generated report.
- scm:git:https://github.com/jeremylong/DependencyCheck.git
- https://github.com/jeremylong/DependencyCheck/tree/main/core
- scm:git:git@github.com:jeremylong/DependencyCheck.git
+ scm:git:https://github.com/dependency-check/DependencyCheck.git
+ https://github.com/dependency-check/DependencyCheck/tree/main/core
+ scm:git:git@github.com/dependency-check/DependencyCheck.gitv6.4.1
@@ -105,7 +105,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
jsonschema2pojo-maven-plugin
-
+
generate-knownexploitedgenerate-sources
@@ -126,6 +126,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
generate
+ false${basedir}/src/main/resources/schema/external/cisa${project.build.directory}/generated-sources/javatrue
@@ -184,6 +185,10 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
+
+ io.github.jeremylong
+ open-vulnerability-clients
+ org.anarres.jdiagnosticsjdiagnostics
@@ -194,7 +199,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.apache.commons
- commons-jcs-core
+ commons-jcs3-core
+
+
+ io.github.jeremylong
+ jcs3-slf4j
+ runtimecom.github.package-url
@@ -218,6 +228,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
logback-classictest
+
+ ch.qos.logback
+ logback-core
+ test
+ org.owaspdependency-check-utils
@@ -258,12 +273,17 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.apache.lucene
- lucene-analyzers-common
+ lucene-analysis-commonorg.apache.lucenelucene-queryparser
+
+
+ org.slf4j
+ jul-to-slf4j
+ org.apache.velocityvelocity-engine-core
@@ -275,7 +295,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.glassfish
- javax.json
+ jakarta.jsonorg.jsoup
@@ -286,8 +306,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
jackson-databind
- com.fasterxml.jackson.module
- jackson-module-afterburner
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310com.fasterxml.jackson.module
@@ -320,21 +340,64 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.mockito
- mockito-core
+ mockito-junit-jupitertestcommons-validatorcommons-validator
-
- commons-beanutils
- commons-beanutils
- org.eclipse.packagerpackager-rpm
+
+ org.apache.httpcomponents.core5
+ httpcore5
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ org.sonatype.goodies
+ package-url-java
+ 1.2.0
+
+
+ joda-time
+ joda-time
+ 2.14.0
+
+
+ org.sonatype.ossindex
+ ossindex-service-api
+ 1.8.2
+
+
+ com.esotericsoftware
+ minlog
+ 1.3.1
+
+
+ com.vaadin.external.google
+ android-json
+ 0.0.20131108.vaadin1
+
+
+ xml-apis
+ xml-apis
+ 1.4.01
+ test
+
@@ -376,20 +439,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.apache.maven.pluginsmaven-failsafe-plugin
-
-
- data.driver_path
- ${driver_path}
-
-
- data.driver_name
- ${driver_name}
-
-
- data.connection_string
- ${connection_string}
-
-
+
+ ${driver_path}
+ ${driver_name}
+ ${connection_string}
+ **/*MySqlIT.java
@@ -417,7 +471,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.postgresqlpostgresql
- 42.6.0
+ 42.7.8
@@ -426,20 +480,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
org.apache.maven.pluginsmaven-failsafe-plugin
-
-
- data.driver_path
- ${driver_path}
-
-
- data.driver_name
- ${driver_name}
-
-
- data.connection_string
- ${connection_string}
-
-
+
+ ${driver_path}
+ ${driver_name}
+ ${connection_string}
+ **/*MySqlIT.java
@@ -462,6 +507,45 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
true
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ ${maven-dependency-plugin.version}
+
+
+
+ org.springframework:spring-webmvc
+ org.mortbay.jetty:jetty
+ net.sf.ehcache:ehcache-core
+ com.google.inject:guice
+ org.apache.struts:struts2-core
+ xalan:xalan
+ com.hazelcast:hazelcast
+ commons-fileupload:commons-fileupload
+ org.jslipc:jslipc
+ com.thoughtworks.xstream:xstream
+ org.dojotoolkit:dojo-war
+ org.apache.openjpa:openjpa
+ uk.ltd.getahead:dwr
+ org.glassfish.main.admingui:war
+ org.springframework.retry:spring-retry
+ io.github.faob-dev:aar
+ org.apache.maven.scm:maven-scm-provider-cvsexe
+ org.apache.axis2:axis2-spring
+ org.apache.geronimo.daytrader:daytrader-ear
+ org.springframework.security:spring-security-web
+ org.apache.axis2:axis2-adb
+
+
+
+
+
+
diff --git a/core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java b/core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
index 97cf62b93db..06b63fafec7 100644
--- a/core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
+++ b/core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
@@ -87,7 +87,7 @@ public Void call() {
try {
analyzer.analyze(dependency, engine);
} catch (AnalysisException ex) {
- LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
+ LOGGER.warn("An error occurred while analyzing '{}' ({}): {}", dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
LOGGER.debug("", ex);
exceptions.add(ex);
} catch (Throwable ex) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/Engine.java b/core/src/main/java/org/owasp/dependencycheck/Engine.java
index 5b6d41e5929..625da29a419 100644
--- a/core/src/main/java/org/owasp/dependencycheck/Engine.java
+++ b/core/src/main/java/org/owasp/dependencycheck/Engine.java
@@ -18,8 +18,7 @@
package org.owasp.dependencycheck;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.jcs.JCS;
+import org.apache.commons.jcs3.JCS;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
@@ -40,6 +39,7 @@
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.exception.WriteLockException;
import org.owasp.dependencycheck.reporting.ReportGenerator;
+import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.WriteLock;
import org.slf4j.Logger;
@@ -78,7 +78,9 @@
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.INITIAL;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_FINDING_ANALYSIS;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
-import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_INFORMATION_COLLECTION;
+import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_INFORMATION_COLLECTION1;
+import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_INFORMATION_COLLECTION2;
+import static org.owasp.dependencycheck.analyzer.AnalysisPhase.POST_INFORMATION_COLLECTION3;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.PRE_FINDING_ANALYSIS;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.PRE_INFORMATION_COLLECTION;
@@ -187,6 +189,7 @@ public Engine(@NotNull final ClassLoader serviceClassLoader, @NotNull final Mode
this.serviceClassLoader = serviceClassLoader;
this.mode = mode;
this.accessExternalSchema = System.getProperty("javax.xml.accessExternalSchema");
+
initializeEngine();
}
@@ -252,8 +255,8 @@ public List getAnalyzers(AnalysisPhase phase) {
/**
* Adds a dependency. In some cases, when adding a virtual dependency, the
- * method will identify if the virtual dependency was previously added and update
- * the existing dependency rather then adding a duplicate.
+ * method will identify if the virtual dependency was previously added and
+ * update the existing dependency rather then adding a duplicate.
*
* @param dependency the dependency to add
*/
@@ -639,13 +642,12 @@ public void analyzeDependencies() throws ExceptionCollection {
LOGGER.info("\n\nDependency-Check is an open source tool performing a best effort analysis of 3rd party dependencies; false positives and "
+ "false negatives may exist in the analysis performed by the tool. Use of the tool and the reporting provided constitutes "
+ "acceptance for use in an AS IS condition, and there are NO warranties, implied or otherwise, with regard to the analysis "
- + "or its use. Any use of the tool and the reporting provided is at the user’s risk. In no event shall the copyright holder "
+ + "or its use. Any use of the tool and the reporting provided is at the user's risk. In no event shall the copyright holder "
+ "or OWASP be held liable for any damages whatsoever arising out of or in connection with the use of this tool, the analysis "
+ "performed, or the resulting report.\n\n\n"
- + " About ODC: https://jeremylong.github.io/DependencyCheck/general/internals.html\n"
- + " False Positives: https://jeremylong.github.io/DependencyCheck/general/suppression.html\n"
- + "\n"
- + "💖 Sponsor: https://github.com/sponsors/jeremylong\n\n");
+ + " About ODC: https://dependency-check.github.io/DependencyCheck/general/internals.html\n"
+ + " False Positives: https://dependency-check.github.io/DependencyCheck/general/suppression.html\n"
+ + "\n");
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
LOGGER.info("Analysis Started");
final long analysisStart = System.currentTimeMillis();
@@ -943,7 +945,7 @@ public boolean purge() {
try {
final File cache = new File(settings.getDataDirectory(), "cache");
if (cache.exists()) {
- if (FileUtils.deleteQuietly(cache)) {
+ if (FileUtils.delete(cache)) {
LOGGER.info("Cache directory purged");
}
}
@@ -953,7 +955,7 @@ public boolean purge() {
try {
final File cache = new File(settings.getDataDirectory(), "oss_cache");
if (cache.exists()) {
- if (FileUtils.deleteQuietly(cache)) {
+ if (FileUtils.delete(cache)) {
LOGGER.info("OSS Cache directory purged");
}
}
@@ -1181,7 +1183,7 @@ private void throwFatalExceptionCollection(String message, @NotNull final Throwa
* @param applicationName the name of the application/project
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
- * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @param format the report format (see {@link ReportGenerator.Format})
* @throws ReportException thrown if there is an error generating the report
* @deprecated use
* {@link #writeReports(java.lang.String, java.io.File, java.lang.String, org.owasp.dependencycheck.exception.ExceptionCollection)}
@@ -1198,7 +1200,7 @@ public void writeReports(String applicationName, File outputDir, String format)
* @param applicationName the name of the application/project
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
- * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @param format the report format (see {@link ReportGenerator.Format})
* @param exceptions a collection of exceptions that may have occurred
* during the analysis
* @throws ReportException thrown if there is an error generating the report
@@ -1217,7 +1219,7 @@ public void writeReports(String applicationName, File outputDir, String format,
* @param version the Maven version
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
- * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @param format the report format (see {@link ReportGenerator.Format})
* @throws ReportException thrown if there is an error generating the report
* @deprecated use
* {@link #writeReports(String, String, String, String, File, String, ExceptionCollection)}
@@ -1239,7 +1241,7 @@ public synchronized void writeReports(String applicationName, @Nullable final St
* @param version the Maven version
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
- * @param format the report format (ALL, HTML, CSV, JSON, etc.)
+ * @param format the report format (see {@link ReportGenerator.Format})
* @param exceptions a collection of exceptions that may have occurred
* during the analysis
* @throws ReportException thrown if there is an error generating the report
@@ -1294,7 +1296,9 @@ public enum Mode {
PRE_INFORMATION_COLLECTION,
INFORMATION_COLLECTION,
INFORMATION_COLLECTION2,
- POST_INFORMATION_COLLECTION
+ POST_INFORMATION_COLLECTION1,
+ POST_INFORMATION_COLLECTION2,
+ POST_INFORMATION_COLLECTION3
),
/**
* In evidence processing mode the {@link Engine} processes the evidence
diff --git a/core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
index b7f893fb85d..598c342f343 100644
--- a/core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
+++ b/core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java
@@ -101,12 +101,17 @@ public class DependencyCheckScanAgent {
* to 11. The valid range for the fail build on CVSS is 0 to 11, where
* anything above 10 will not cause the build to fail.
*/
- private float failBuildOnCVSS = 11;
+ private Double failBuildOnCVSS = 11.0;
/**
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
* recommended that this be turned to false. Default is true.
*/
private boolean autoUpdate = true;
+ /**
+ * The NVD API key.
+ */
+ private String nvdApiKey;
+
/**
* Sets whether the data directory should be updated without performing a
* scan. Default is false.
@@ -117,9 +122,10 @@ public class DependencyCheckScanAgent {
*/
private boolean generateReport = true;
/**
- * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, ALL).
- * This configuration option has no affect if using this within the Site
- * plugin unless the externalReport is set to true. Default is HTML.
+ * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF,
+ * JENKINS, GITLAB, ALL). This configuration option has no affect if using
+ * this within the Site plugin unless the externalReport is set to true.
+ * Default is HTML.
*/
private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
/**
@@ -171,6 +177,10 @@ public class DependencyCheckScanAgent {
* Whether the Maven Central analyzer is enabled.
*/
private boolean centralAnalyzerEnabled = true;
+ /**
+ * Whether the build should fail if there are unused suppression rules.
+ */
+ private boolean failOnUnusedSuppressionRule = false;
/**
* The URL of Maven Central.
*/
@@ -208,14 +218,6 @@ public class DependencyCheckScanAgent {
* comma-separated list of file extensions to treat like ZIP files.
*/
private String zipExtensions;
- /**
- * The URL for the modified NVD CVE JSON.
- */
- private String cveUrlModified;
- /**
- * The base URL for the NVD CVE JSON data feeds.
- */
- private String cveUrlBase;
/**
* The path to dotnet core for .NET assembly analysis.
*/
@@ -251,6 +253,24 @@ public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
+ /**
+ * Get the value of nvdApiKey.
+ *
+ * @return the value of nvdApiKey
+ */
+ public String getNvdApiKey() {
+ return nvdApiKey;
+ }
+
+ /**
+ * Set the value of nvdApiKey.
+ *
+ * @param nvdApiKey new value of nvdApiKey
+ */
+ public void setNvdApiKey(String nvdApiKey) {
+ this.nvdApiKey = nvdApiKey;
+ }
+
/**
* Returns a list of pre-determined dependencies.
*
@@ -310,7 +330,7 @@ public void setReportOutputDirectory(String reportOutputDirectory) {
*
* @return the value of failBuildOnCVSS
*/
- public float getFailBuildOnCVSS() {
+ public Double getFailBuildOnCVSS() {
return failBuildOnCVSS;
}
@@ -319,7 +339,7 @@ public float getFailBuildOnCVSS() {
*
* @param failBuildOnCVSS new value of failBuildOnCVSS
*/
- public void setFailBuildOnCVSS(float failBuildOnCVSS) {
+ public void setFailBuildOnCVSS(Double failBuildOnCVSS) {
this.failBuildOnCVSS = failBuildOnCVSS;
}
@@ -603,6 +623,24 @@ public String getCpeStartsWithFilter() {
return cpeStartsWithFilter;
}
+ /**
+ * Get the value of failOnUnusedSuppressionRule.
+ *
+ * @return the value of failOnUnusedSuppressionRule
+ */
+ public boolean isFailOnUnusedSuppressionRule() {
+ return failOnUnusedSuppressionRule;
+ }
+
+ /**
+ * Set the value of failOnUnusedSuppressionRule.
+ *
+ * @param failOnUnusedSuppressionRule new value of failOnUnusedSuppressionRule
+ */
+ public void setFailOnUnusedSuppressionRule(boolean failOnUnusedSuppressionRule) {
+ this.failOnUnusedSuppressionRule = failOnUnusedSuppressionRule;
+ }
+
/**
* Get the value of centralAnalyzerEnabled.
*
@@ -801,42 +839,6 @@ public void setZipExtensions(String zipExtensions) {
this.zipExtensions = zipExtensions;
}
- /**
- * Get the value of cveUrlModified.
- *
- * @return the value of cveUrlModified
- */
- public String getCveUrlModified() {
- return cveUrlModified;
- }
-
- /**
- * Set the value of cveUrlModified.
- *
- * @param cveUrlModified new value of cveUrlModified
- */
- public void setCveUrlModified(String cveUrlModified) {
- this.cveUrlModified = cveUrlModified;
- }
-
- /**
- * Get the value of cveUrlBase.
- *
- * @return the value of cveUrlBase
- */
- public String getCveUrlBase() {
- return cveUrlBase;
- }
-
- /**
- * Set the value of cveUrlBase.
- *
- * @param cveUrlBase new value of cveUrlBase
- */
- public void setCveUrlBase(String cveUrlBase) {
- this.cveUrlBase = cveUrlBase;
- }
-
/**
* Get the value of pathToCore.
*
@@ -970,9 +972,9 @@ private void populateSettings() {
settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_JSON, cveUrlModified);
- settings.setStringIfNotEmpty(Settings.KEYS.CVE_BASE_JSON, cveUrlBase);
+ settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, nvdApiKey);
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_DOTNET_PATH, pathToCore);
+ settings.setBoolean(Settings.KEYS.FAIL_ON_UNUSED_SUPPRESSION_RULE, failOnUnusedSuppressionRule);
}
/**
@@ -993,7 +995,7 @@ public Engine execute() throws ScanAgentException {
if (this.showSummary) {
showSummary(engine.getDependencies());
}
- if (this.failBuildOnCVSS <= 10) {
+ if (this.failBuildOnCVSS <= 10.0) {
checkForFailure(engine.getDependencies());
}
}
@@ -1025,15 +1027,29 @@ private void checkForFailure(Dependency[] dependencies) throws ScanAgentExceptio
for (Dependency d : dependencies) {
boolean addName = true;
for (Vulnerability v : d.getVulnerabilities()) {
- if ((v.getCvssV2() != null && v.getCvssV2().getScore() >= failBuildOnCVSS)
- || (v.getCvssV3() != null && v.getCvssV3().getBaseScore() >= failBuildOnCVSS)
- || (v.getUnscoredSeverity() != null && SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) >= failBuildOnCVSS)
+ final double cvssV2 = v.getCvssV2() != null && v.getCvssV2().getCvssData() != null
+ && v.getCvssV2().getCvssData().getBaseScore() != null ? v.getCvssV2().getCvssData().getBaseScore() : -1;
+ final double cvssV3 = v.getCvssV3() != null && v.getCvssV3().getCvssData() != null
+ && v.getCvssV3().getCvssData().getBaseScore() != null ? v.getCvssV3().getCvssData().getBaseScore() : -1;
+ final double cvssV4 = v.getCvssV4() != null && v.getCvssV4().getCvssData() != null
+ && v.getCvssV4().getCvssData().getBaseScore() != null ? v.getCvssV4().getCvssData().getBaseScore() : -1;
+ final boolean useUnscored = cvssV2 == -1 && cvssV3 == -1 && cvssV4 == -1;
+ final double unscoredCvss = (useUnscored && v.getUnscoredSeverity() != null) ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
+ if (cvssV2 >= failBuildOnCVSS
+ || cvssV3 >= failBuildOnCVSS
+ || cvssV4 >= failBuildOnCVSS
+ || unscoredCvss >= failBuildOnCVSS
//safety net to fail on any if for some reason the above misses on 0
- || (failBuildOnCVSS <= 0.0f)) {
+ || failBuildOnCVSS <= 0.0f
+ ) {
if (addName) {
addName = false;
- ids.append(NEW_LINE).append(d.getFileName()).append(": ");
- ids.append(v.getName());
+ ids.append(NEW_LINE).append(d.getFileName()).append(" (")
+ .append(Stream.concat(d.getSoftwareIdentifiers().stream(), d.getVulnerableSoftwareIdentifiers().stream())
+ .map(Identifier::getValue)
+ .collect(Collectors.joining(", ")))
+ .append("): ")
+ .append(v.getName());
} else {
ids.append(", ").append(v.getName());
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
index 573c50e3372..a02e3d40d74 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractNpmAnalyzer.java
@@ -28,7 +28,6 @@
import org.owasp.dependencycheck.data.nodeaudit.NodeAuditSearch;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
-import org.owasp.dependencycheck.dependency.Reference;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.dependency.VulnerableSoftwareBuilder;
@@ -45,13 +44,13 @@
import java.util.List;
import java.util.Map;
import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
-import javax.json.JsonString;
-import javax.json.JsonValue;
-import javax.json.JsonValue.ValueType;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
+import jakarta.json.JsonValue.ValueType;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
@@ -394,8 +393,11 @@ public void gatherEvidence(final JsonObject json, Dependency dependency) {
}
}
dependency.setLicense(sb.toString());
- } else {
- dependency.setLicense(json.getJsonObject("license").getString("type"));
+ } else if (value instanceof JsonObject) {
+ final JsonObject object = (JsonObject) value;
+ if (object.containsKey("type") && !object.isNull("type")) {
+ dependency.setLicense(object.getString("type"));
+ }
}
}
}
@@ -505,16 +507,13 @@ protected void processResults(final List advisories, Engine engine,
* @param vuln the vulnerability to add
*/
protected void replaceOrAddVulnerability(Dependency dependency, Vulnerability vuln) {
- boolean found = false;
- for (Vulnerability existing : dependency.getVulnerabilities()) {
- for (Reference ref : existing.getReferences()) {
- if (ref.getName() != null
- && vuln.getSource().toString().equals("NPM")
- && ref.getName().equals("https://nodesecurity.io/advisories/" + vuln.getName())) {
- found = true;
- }
- }
- }
+ final boolean found = vuln.getSource() == Vulnerability.Source.NPM
+ && dependency.getVulnerabilities().stream().anyMatch(existing -> {
+ return existing.getReferences().stream().anyMatch(ref -> {
+ return ref.getName() != null
+ && ref.getName().equals("https://nodesecurity.io/advisories/" + vuln.getName());
+ });
+ });
if (!found) {
dependency.addVulnerability(vuln);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java
index 7b741bdf87c..f03d2f6157f 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java
@@ -188,23 +188,37 @@ private void loadSuppressionBaseData(final Engine engine) throws SuppressionPars
}
/**
- * Loads all the base suppression rules packaged with the application.
+ * Loads the base suppression rules packaged with the application.
*
* @param parser The suppression parser to use
* @param engine a reference the dependency-check engine
* @throws SuppressionParseException thrown if the XML cannot be parsed.
*/
private void loadPackagedSuppressionBaseData(final SuppressionParser parser, final Engine engine) throws SuppressionParseException {
- final List ruleList;
- try (InputStream in = FileUtils.getResourceAsStream(BASE_SUPPRESSION_FILE)) {
- if (in == null) {
- throw new SuppressionParseException("Suppression rules `" + BASE_SUPPRESSION_FILE + "` could not be found");
- }
+ List ruleList = null;
+ final URL jarLocation = AbstractSuppressionAnalyzer.class.getProtectionDomain().getCodeSource().getLocation();
+ String suppressionFileLocation = jarLocation.getFile();
+ if (suppressionFileLocation.endsWith(".jar")) {
+ suppressionFileLocation = "jar:file:" + suppressionFileLocation + "!/" + BASE_SUPPRESSION_FILE;
+ } else if (suppressionFileLocation.startsWith("nested:") && suppressionFileLocation.endsWith(".jar!/")) {
+ // suppressionFileLocation -> nested:/app/app.jar/!BOOT-INF/lib/dependency-check-core-.jar!/
+ // goal-> jar:nested:/app/app.jar/!BOOT-INF/lib/dependency-check-core-.jar!/dependencycheck-base-suppression.xml
+ suppressionFileLocation = "jar:" + suppressionFileLocation + BASE_SUPPRESSION_FILE;
+ } else {
+ suppressionFileLocation = "file:" + suppressionFileLocation + BASE_SUPPRESSION_FILE;
+ }
+ URL baseSuppresssionURL = null;
+ try {
+ baseSuppresssionURL = new URL(suppressionFileLocation);
+ } catch (MalformedURLException e) {
+ throw new SuppressionParseException("Unable to load the base suppression data file", e);
+ }
+ try (InputStream in = baseSuppresssionURL.openStream()) {
ruleList = parser.parseSuppressionRules(in);
} catch (SAXException | IOException ex) {
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
}
- if (!ruleList.isEmpty()) {
+ if (ruleList != null && !ruleList.isEmpty()) {
if (engine.hasObject(SUPPRESSION_OBJECT_KEY)) {
@SuppressWarnings("unchecked")
final List rules = (List) engine.getObject(SUPPRESSION_OBJECT_KEY);
@@ -345,14 +359,15 @@ private List loadSuppressionFile(final SuppressionParser parser
deleteTempFile = true;
file = getSettings().getTempFile("suppression", "xml");
final URL url = new URL(suppressionFilePath);
- final Downloader downloader = new Downloader(getSettings());
try {
- downloader.fetchFile(url, file, false, Settings.KEYS.SUPPRESSION_FILE_USER, Settings.KEYS.SUPPRESSION_FILE_PASSWORD);
+ Downloader.getInstance().fetchFile(url, file, false, Settings.KEYS.SUPPRESSION_FILE_USER,
+ Settings.KEYS.SUPPRESSION_FILE_PASSWORD, Settings.KEYS.SUPPRESSION_FILE_BEARER_TOKEN);
} catch (DownloadFailedException ex) {
LOGGER.trace("Failed download suppression file - first attempt", ex);
try {
Thread.sleep(500);
- downloader.fetchFile(url, file, true, Settings.KEYS.SUPPRESSION_FILE_USER, Settings.KEYS.SUPPRESSION_FILE_PASSWORD);
+ Downloader.getInstance().fetchFile(url, file, true, Settings.KEYS.SUPPRESSION_FILE_USER,
+ Settings.KEYS.SUPPRESSION_FILE_PASSWORD, Settings.KEYS.SUPPRESSION_FILE_BEARER_TOKEN);
} catch (TooManyRequestsException ex1) {
throw new SuppressionParseException("Unable to download supression file `" + file
+ "`; received 429 - too many requests", ex1);
@@ -377,7 +392,7 @@ private List loadSuppressionFile(final SuppressionParser parser
deleteTempFile = true;
file = getSettings().getTempFile("suppression", "xml");
try {
- org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionFromClasspath, file);
+ Files.copy(suppressionFromClasspath, file.toPath());
} catch (IOException ex) {
throwSuppressionParseException("Unable to locate suppression file in classpath", ex, suppressionFilePath);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AnalysisPhase.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AnalysisPhase.java
index 818ba2186c8..1dcaa3bafe9 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AnalysisPhase.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AnalysisPhase.java
@@ -26,54 +26,127 @@ public enum AnalysisPhase {
/**
* Initialization phase.
+ * @implNote Bound analyzers are {@link ArchiveAnalyzer}
*/
INITIAL,
/**
* Pre information collection phase.
+ * @implNote Bound analyzers are {@link ElixirMixAuditAnalyzer},{@link RubyBundleAuditAnalyzer}
*/
PRE_INFORMATION_COLLECTION,
/**
* Information collection phase.
+ * @implNote Bound analyzers are
+ * {@link ArtifactoryAnalyzer}
+ * {@link AssemblyAnalyzer}
+ * {@link AutoconfAnalyzer}
+ * {@link CMakeAnalyzer}
+ * {@link CentralAnalyzer}
+ * {@link CarthageAnalyzer}
+ * {@link CocoaPodsAnalyzer}
+ * {@link ComposerLockAnalyzer}
+ * {@link DartAnalyzer}
+ * {@link FileNameAnalyzer}
+ * {@link GolangDepAnalyzer}
+ * {@link GolangModAnalyzer}
+ * {@link JarAnalyzer}
+ * {@link LibmanAnalyzer}
+ * {@link MSBuildProjectAnalyzer}
+ * {@link NexusAnalyzer}
+ * {@link NodeAuditAnalyzer}
+ * {@link NugetconfAnalyzer}
+ * {@link NuspecAnalyzer}
+ * {@link OpenSSLAnalyzer}
+ * {@link PinnedMavenInstallAnalyzer}
+ * {@link PipAnalyzer}
+ * {@link PipfileAnalyzer}
+ * {@link PipfilelockAnalyzer}
+ * {@link PoetryAnalyzer}
+ * {@link PythonDistributionAnalyzer}
+ * {@link PythonPackageAnalyzer}
+ * {@link RubyGemspecAnalyzer}
+ * {@link RubyBundlerAnalyzer}
+ * {@link SwiftPackageManagerAnalyzer}
+ * {@link SwiftPackageResolvedAnalyzer}
*/
INFORMATION_COLLECTION,
/**
* Information collection phase 2.
+ * @implNote Bound analyzers are
+ * {@link PEAnalyzer}
*/
INFORMATION_COLLECTION2,
/**
- * Post information collection phase.
+ * Post information collection phase 1.
+ * @implNote Bound analyzers are
+ * {@link DependencyMergingAnalyzer}
*/
- POST_INFORMATION_COLLECTION,
+ POST_INFORMATION_COLLECTION1,
+ /**
+ * Post information collection phase 2.
+ * @implNote Bound analyzers are
+ * {@link HintAnalyzer} (must run before {@link VersionFilterAnalyzer}, should run after {@link DependencyMergingAnalyzer})
+ */
+ POST_INFORMATION_COLLECTION2,
+ /**
+ * Post information collection phase 3.
+ * @implNote Bound analyzers are
+ * {@link VersionFilterAnalyzer}
+ */
+ POST_INFORMATION_COLLECTION3,
/**
* Pre identifier analysis phase.
+ * @implNote Bound analyzers are
+ * {@link NpmCPEAnalyzer} (must run in a separate phase from {@link CPEAnalyzer} due to singleton re-use)
*/
PRE_IDENTIFIER_ANALYSIS,
/**
* Identifier analysis phase.
+ * @implNote Bound analyzers are
+ * {@link CPEAnalyzer}
*/
IDENTIFIER_ANALYSIS,
/**
* Post identifier analysis phase.
+ * @implNote Bound analyzers are
+ * {@link CpeSuppressionAnalyzer}
+ * {@link FalsePositiveAnalyzer}
*/
POST_IDENTIFIER_ANALYSIS,
/**
* Pre finding analysis phase.
+ * @implNote No analyzers bound to this phase
*/
PRE_FINDING_ANALYSIS,
/**
* Finding analysis phase.
+ * @implNote Bound analyzers are
+ * {@link NodeAuditAnalyzer}
+ * {@link NvdCveAnalyzer}
+ * {@link PnpmAuditAnalyzer}
+ * {@link RetireJsAnalyzer}
+ * {@link YarnAuditAnalyzer}
+ *
*/
FINDING_ANALYSIS,
/**
* Finding analysis phase 2.
+ * @implNote Bound analyzers are
+ * {@link OssIndexAnalyzer}
*/
FINDING_ANALYSIS_PHASE2,
/**
* Post analysis phase.
+ * @implNote Bound analyzers are
+ * {@link KnownExploitedVulnerabilityAnalyzer}
+ * {@link VulnerabilitySuppressionAnalyzer}
*/
POST_FINDING_ANALYSIS,
/**
* The final analysis phase.
+ * @implNote Bound analyzers are
+ * {@link DependencyBundlingAnalyzer}
+ * {@link UnusedSuppressionRuleAnalyzer}
*/
FINAL
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java
index 593b6d42500..7e7a113b6b0 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java
@@ -17,41 +17,21 @@
*/
package org.owasp.dependencycheck.analyzer;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import javax.annotation.concurrent.ThreadSafe;
-
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2Utils;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipUtils;
-import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.io.IOUtils;
import org.eclipse.packager.rpm.RpmTag;
import org.eclipse.packager.rpm.parse.RpmInputStream;
import org.owasp.dependencycheck.Engine;
-import static org.owasp.dependencycheck.analyzer.AbstractNpmAnalyzer.shouldProcess;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
@@ -60,10 +40,30 @@
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import static org.owasp.dependencycheck.analyzer.AbstractNpmAnalyzer.shouldProcess;
+
/**
*
* An analyzer that extracts files from archives and ensures any supported files
@@ -360,7 +360,7 @@ private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine
dependency.setMd5sum("");
dependency.setSha1sum("");
dependency.setSha256sum("");
- org.apache.commons.io.FileUtils.copyFile(dependency.getActualFile(), tmpLoc);
+ Files.copy(dependency.getActualFile().toPath(), tmpLoc.toPath());
final List dependencySet = findMoreDependencies(engine, tmpLoc);
if (dependencySet != null && !dependencySet.isEmpty()) {
dependencySet.forEach((d) -> {
@@ -460,7 +460,7 @@ private void extractFiles(File archive, File destination, Engine engine) throws
tin = new TarArchiveInputStream(in);
extractArchive(tin, destination, engine);
} else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
- final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
+ final String uncompressedName = GzipUtils.getUncompressedFileName(archive.getName());
final File f = new File(destination, uncompressedName);
if (engine.accept(f)) {
final String destPath = destination.getCanonicalPath();
@@ -475,7 +475,7 @@ private void extractFiles(File archive, File destination, Engine engine) throws
decompressFile(gin, f);
}
} else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) {
- final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName());
+ final String uncompressedName = BZip2Utils.getUncompressedFileName(archive.getName());
final File f = new File(destination, uncompressedName);
if (engine.accept(f)) {
final String destPath = destination.getCanonicalPath();
@@ -524,12 +524,11 @@ private void extractFiles(File archive, File destination, Engine engine) throws
* executable JAR is identified the input stream will be advanced to the
* start of the actual JAR file ( skipping the script).
*
- * @see
- * Installing
- * Spring Boot Applications
* @param archiveExt the file extension
* @param in the input stream
* @throws IOException thrown if there is an error reading the stream
+ * @see Installing
+ * Spring Boot Applications
*/
private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
if (("war".equals(archiveExt) || "jar".equals(archiveExt)) && in.markSupported()) {
@@ -729,7 +728,7 @@ private boolean isZipFileActuallyJarFile(Dependency dependency) {
boolean isJar = false;
ZipFile zip = null;
try {
- zip = new ZipFile(dependency.getActualFilePath());
+ zip = ZipFile.builder().setFile(dependency.getActualFilePath()).get();
if (zip.getEntry("META-INF/MANIFEST.MF") != null
|| zip.getEntry("META-INF/maven") != null) {
final Enumeration entries = zip.getEntries();
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/ArtifactoryAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/ArtifactoryAnalyzer.java
index 0aaf21e7ac5..332323a0063 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/ArtifactoryAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/ArtifactoryAnalyzer.java
@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.artifactory.ArtifactorySearch;
@@ -30,8 +29,11 @@
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
import org.owasp.dependencycheck.xml.pom.PomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,8 +46,6 @@
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
-import org.owasp.dependencycheck.utils.ResourceNotFoundException;
-import org.owasp.dependencycheck.utils.TooManyRequestsException;
/**
* Analyzer which will attempt to locate a dependency, and the GAV information,
@@ -234,10 +234,10 @@ private void processPom(Dependency dependency, MavenArtifact ma) throws IOExcept
Files.delete(pomFile.toPath());
LOGGER.debug("Downloading {}", ma.getPomUrl());
//TODO add caching
- final Downloader downloader = new Downloader(getSettings());
- downloader.fetchFile(new URL(ma.getPomUrl()), pomFile,
+ Downloader.getInstance().fetchFile(new URL(ma.getPomUrl()), pomFile, true,
Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME,
- Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN);
+ Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN,
+ Settings.KEYS.ANALYZER_ARTIFACTORY_BEARER_TOKEN);
PomUtils.analyzePOM(dependency, pomFile);
} catch (DownloadFailedException ex) {
@@ -251,7 +251,7 @@ private void processPom(Dependency dependency, MavenArtifact ma) throws IOExcept
LOGGER.warn("pom.xml not found for {} from Artifactory; "
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
} finally {
- if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
+ if (pomFile != null && pomFile.exists() && !FileUtils.delete(pomFile)) {
LOGGER.debug("Failed to delete temporary pom file {}", pomFile);
pomFile.deleteOnExit();
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
index f3b2ec4c167..d9cd109f3ba 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java
@@ -284,20 +284,24 @@ private void updateDependency(final AssemblyData data, Dependency dependency) {
if (!StringUtils.isBlank(data.getCompanyName())) {
dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "CompanyName", data.getCompanyName(), Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "CompanyName", data.getCompanyName(), Confidence.LOW);
addMatchingValues(data.getNamespaces(), data.getCompanyName(), dependency, EvidenceType.VENDOR);
}
if (!StringUtils.isBlank(data.getProductName())) {
dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "ProductName", data.getProductName(), Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "ProductName", data.getProductName(), Confidence.MEDIUM);
addMatchingValues(data.getNamespaces(), data.getProductName(), dependency, EvidenceType.PRODUCT);
}
if (!StringUtils.isBlank(data.getFileDescription())) {
dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "FileDescription", data.getFileDescription(), Confidence.HIGH);
+ dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "FileDescription", data.getFileDescription(), Confidence.LOW);
addMatchingValues(data.getNamespaces(), data.getFileDescription(), dependency, EvidenceType.PRODUCT);
}
final String internalName = data.getInternalName();
if (!StringUtils.isBlank(internalName)) {
dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "InternalName", internalName, Confidence.MEDIUM);
+ dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "InternalName", internalName, Confidence.LOW);
addMatchingValues(data.getNamespaces(), internalName, dependency, EvidenceType.PRODUCT);
addMatchingValues(data.getNamespaces(), internalName, dependency, EvidenceType.VENDOR);
if (dependency.getName() == null && StringUtils.containsIgnoreCase(dependency.getActualFile().getName(), internalName)) {
@@ -313,6 +317,7 @@ private void updateDependency(final AssemblyData data, Dependency dependency) {
final String originalFilename = data.getOriginalFilename();
if (!StringUtils.isBlank(originalFilename)) {
dependency.addEvidence(EvidenceType.PRODUCT, "grokassembly", "OriginalFilename", originalFilename, Confidence.MEDIUM);
+ dependency.addEvidence(EvidenceType.VENDOR, "grokassembly", "OriginalFilename", originalFilename, Confidence.LOW);
addMatchingValues(data.getNamespaces(), originalFilename, dependency, EvidenceType.PRODUCT);
if (dependency.getName() == null && StringUtils.containsIgnoreCase(dependency.getActualFile().getName(), originalFilename)) {
final String ext = FileUtils.getFileExtension(originalFilename);
@@ -355,7 +360,7 @@ public void prepareFileTypeAnalyzer(Engine engine) throws InitializationExceptio
+ "'exe' or 'dll' was scanned. The 'dotnet' executable could not be found on "
+ "the path; either disable the Assembly Analyzer or add the path to dotnet "
+ "core in the configuration.");
- LOGGER.error("The dotnet 6.0 core runtime or SDK is required to analyze assemblies");
+ LOGGER.error("The dotnet 8.0 core runtime or SDK is required to analyze assemblies");
LOGGER.error("----------------------------------------------------");
return;
}
@@ -367,28 +372,28 @@ public void prepareFileTypeAnalyzer(Engine engine) throws InitializationExceptio
final String error = processReader.getError();
if (p.exitValue() != 1 || !StringUtils.isBlank(error)) {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.\n"
- + "dependency-check requires dotnet 6.0 core runtime or sdk to be installed to analyze assemblies.");
+ + "dependency-check requires dotnet 8.0 core runtime or sdk to be installed to analyze assemblies.");
LOGGER.debug("GrokAssembly.dll is not working properly");
grokAssembly = null;
setEnabled(false);
- throw new InitializationException("Could not execute .NET AssemblyAnalyzer, is the dotnet 6.0 runtime or sdk installed?");
+ throw new InitializationException("Could not execute .NET AssemblyAnalyzer, is the dotnet 8.0 runtime or sdk installed?");
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
- + "dependency-check requires dotnet 6.0 core runtime or sdk to be installed to analyze assemblies;\n"
+ + "dependency-check requires dotnet 8.0 core runtime or sdk to be installed to analyze assemblies;\n"
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
setEnabled(false);
throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
} catch (IOException e) {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
- + "dependency-check requires dotnet 6.0 core to be installed to analyze assemblies;\n"
+ + "dependency-check requires dotnet 8.0 core to be installed to analyze assemblies;\n"
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
setEnabled(false);
- throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer, is the dotnet 6.0 runtime or sdk installed?", e);
+ throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer, is the dotnet 8.0 runtime or sdk installed?", e);
}
}
@@ -422,7 +427,9 @@ private File extractGrokAssembly() throws InitializationException {
*/
@Override
public void closeAnalyzer() throws Exception {
- FileUtils.delete(grokAssembly.getParentFile());
+ if (grokAssembly != null) {
+ FileUtils.delete(grokAssembly.getParentFile());
+ }
}
@Override
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
index 303d775e58b..08c059b8a70 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java
@@ -17,11 +17,12 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
@@ -29,11 +30,10 @@
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Autoconf input files named configure.ac or configure.in.
@@ -187,7 +187,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine)
* @param contents the contents to analyze for evidence
*/
private void extractConfigureScriptEvidence(Dependency dependency,
- final String name, final String contents) {
+ final String name, final String contents) {
final Matcher matcher = PACKAGE_VAR.matcher(contents);
while (matcher.find()) {
final String variable = matcher.group(1);
@@ -195,12 +195,15 @@ private void extractConfigureScriptEvidence(Dependency dependency,
if (!value.isEmpty()) {
if (variable.endsWith("NAME")) {
dependency.addEvidence(EvidenceType.PRODUCT, name, variable, value, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, name, variable, value, Confidence.MEDIUM);
} else if ("VERSION".equals(variable)) {
dependency.addEvidence(EvidenceType.VERSION, name, variable, value, Confidence.HIGHEST);
} else if ("BUGREPORT".equals(variable)) {
dependency.addEvidence(EvidenceType.VENDOR, name, variable, value, Confidence.HIGH);
+ dependency.addEvidence(EvidenceType.PRODUCT, name, variable, value, Confidence.MEDIUM);
} else if ("URL".equals(variable)) {
dependency.addEvidence(EvidenceType.VENDOR, name, variable, value, Confidence.HIGH);
+ dependency.addEvidence(EvidenceType.PRODUCT, name, variable, value, Confidence.MEDIUM);
}
}
}
@@ -216,7 +219,7 @@ private void extractConfigureScriptEvidence(Dependency dependency,
private String getFileContents(final File actualFile)
throws AnalysisException {
try {
- return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ return new String(Files.readAllBytes(actualFile.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -231,7 +234,7 @@ private String getFileContents(final File actualFile)
* @param contents the evidence to analyze
*/
private void gatherEvidence(Dependency dependency, final String name,
- String contents) {
+ String contents) {
final Matcher matcher = AC_INIT_PATTERN.matcher(contents);
if (matcher.find()) {
dependency.addEvidence(EvidenceType.PRODUCT, name, "Package", matcher.group(1), Confidence.HIGHEST);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java
index 4b422c3d756..fdd36476954 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java
@@ -17,10 +17,10 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceType;
@@ -30,14 +30,14 @@
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -45,7 +45,6 @@
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
/**
*
@@ -101,9 +100,8 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Regex to extract product and version information.
*
- * Group 1: Product
- *
- * Group 2: Version
+ *
Group 1: Product
+ *
Group 2: Version
*/
private static final Pattern SET_VERSION = Pattern
.compile("^\\s*set\\s*\\(\\s*(\\w+)_version\\s+\"?([^\")]*)\\s*\"?\\)", REGEX_OPTIONS);
@@ -171,7 +169,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
final String name = file.getName();
final String contents;
try {
- contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
+ contents = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -349,8 +347,8 @@ protected String getAnalyzerEnabledSettingKey() {
* initialized by other variables and end up forming an unresolvable
* chain.
*
- * This method takes the resolved variables map as an input and will return
- * a new map, without the keys generate an infinite resolution chain.
+ *
This method takes the resolved variables map as an input and will return
+ * a new map, without the keys generating an infinite resolution chain.
*
* @param vars variables initialization detected in the CMake build file
*
@@ -379,6 +377,9 @@ private boolean isVariableSelfReferencing(Map vars, String key)
break;
}
nextKey = matcher.group(2);
+ if (Objects.nonNull(nextKey) && resolutionChain.contains(nextKey)) {
+ return true;
+ }
resolutionChain.add(nextKey);
} while (Objects.nonNull(nextKey) && vars.containsKey(nextKey) && !key.equals(nextKey));
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java
index e1c89c41c74..d2fe65a1460 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java
@@ -20,8 +20,6 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -49,6 +47,7 @@
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
@@ -110,24 +109,7 @@ public class CPEAnalyzer extends AbstractAnalyzer {
* alpha characters.
*/
private static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
- /**
- * UTF-8 character set name.
- */
- private static final String UTF8 = StandardCharsets.UTF_8.name();
- /**
- * The URL to search the NVD CVE data at NIST. This is used by calling:
- *
- */
- public static final String NVD_SEARCH_URL = "https://nvd.nist.gov/vuln/search/results?form_type=Advanced&"
- + "results_type=overview&search_type=all&cpe_vendor=cpe%%3A%%2F%%3A%1$s&cpe_product=cpe%%3A%%2F%%3A%1$s%%3A%2$s&"
- + "cpe_version=cpe%%3A%%2F%%3A%1$s%%3A%2$s%%3A%3$s";
- /**
- * The URL to search the NVD CVE data at NIST. This is used by calling:
- *
String.format(NVD_SEARCH_URL, vendor, product);
- */
- public static final String NVD_SEARCH_BROAD_URL = "https://nvd.nist.gov/vuln/search/results?form_type=Advanced&"
- + "results_type=overview&search_type=all&cpe_vendor=cpe%%3A%%2F%%3A%1$s&cpe_product=cpe%%3A%%2F%%3A%1$s%%3A%2$s";
/**
* The CPE in memory index.
*/
@@ -805,12 +787,11 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
* analysis
* @return true if an identifier was added to the dependency;
* otherwise false
- * @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
* @throws AnalysisException thrown if the suppression rules failed
*/
@SuppressWarnings("StringSplitter")
protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
- Confidence currentConfidence) throws UnsupportedEncodingException, AnalysisException {
+ Confidence currentConfidence) throws AnalysisException {
final CpeBuilder cpeBuilder = new CpeBuilder();
@@ -831,7 +812,7 @@ protected boolean determineIdentifiers(Dependency dependency, String vendor, Str
String bestGuessURL = null;
final Set collected = new HashSet<>();
- considerDependencyVersion(dependency, vendor, product, currentConfidence, collected, bestGuess);
+ considerDependencyVersion(dependency, vendor, product, currentConfidence, collected);
//TODO the following algorithm incorrectly identifies things as a lower version
// if there lower confidence evidence when the current (highest) version number
@@ -863,8 +844,7 @@ protected boolean determineIdentifiers(Dependency dependency, String vendor, Str
dbVerUpdate = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate(), true);
}
if (dbVer == null) { //special case, no version specified - everything is vulnerable
- final String url = String.format(NVD_SEARCH_BROAD_URL, URLEncoder.encode(vs.getVendor(), UTF8),
- URLEncoder.encode(vs.getProduct(), UTF8));
+ final String url = CpeIdentifier.nvdProductSearchUrlFor(vs);
final IdentifierMatch match = new IdentifierMatch(vs, url, IdentifierConfidence.BROAD_MATCH, conf);
collected.add(match);
} else if (evVer.equals(dbVer)) {
@@ -874,8 +854,7 @@ protected boolean determineIdentifiers(Dependency dependency, String vendor, Str
bestGuessConf = conf;
bestGuess = dbVer;
bestGuessUpdate = evBaseVerUpdate;
- bestGuessURL = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getVendor(), UTF8),
- URLEncoder.encode(vs.getProduct(), UTF8), URLEncoder.encode(vs.getVersion(), UTF8));
+ bestGuessURL = CpeIdentifier.nvdSearchUrlFor(vs);
} else if (dbVerUpdate != null && evVer.getVersionParts().size() <= dbVerUpdate.getVersionParts().size()
&& evVer.matchesAtLeastThreeLevels(dbVerUpdate)) {
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
@@ -982,14 +961,12 @@ protected boolean determineIdentifiers(Dependency dependency, String vendor, Str
* @param updateVersion the update version
* @param conf the current confidence
* @param collected a reference to the collected identifiers
- * @throws UnsupportedEncodingException thrown if UTF-8 is not supported
*/
private void addExactMatch(Cpe vs, String updateVersion, Confidence conf,
- final Set collected) throws UnsupportedEncodingException {
+ final Set collected) {
final CpeBuilder cpeBuilder = new CpeBuilder();
- final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getVendor(), UTF8),
- URLEncoder.encode(vs.getProduct(), UTF8), URLEncoder.encode(vs.getVersion(), UTF8));
+ final String url = CpeIdentifier.nvdSearchUrlFor(vs);
Cpe useCpe;
if (updateVersion != null && "*".equals(vs.getUpdate())) {
try {
@@ -1019,16 +996,13 @@ private void addExactMatch(Cpe vs, String updateVersion, Confidence conf,
* @param vendor the vendor name
* @param confidence the current confidence level
* @param collected a reference to the identifiers matched
- * @param bestGuess the current best guess as to the dependency version
* @throws AnalysisException thrown if aliens attacked and valid input could
* not be used to construct a CPE
- * @throws UnsupportedEncodingException thrown if run on a system that
- * doesn't support UTF-8
*/
private void considerDependencyVersion(Dependency dependency,
String vendor, String product, Confidence confidence,
- final Set collected, DependencyVersion bestGuess)
- throws AnalysisException, UnsupportedEncodingException {
+ final Set collected)
+ throws AnalysisException {
if (dependency.getVersion() != null && !dependency.getVersion().isEmpty()) {
final CpeBuilder cpeBuilder = new CpeBuilder();
@@ -1037,7 +1011,8 @@ private void considerDependencyVersion(Dependency dependency,
if (dependency.getName() != null && !dependency.getName().isEmpty()) {
final String name = dependency.getName();
for (String word : product.split("[^a-zA-Z0-9]")) {
- useDependencyVersion &= name.contains(word) || stopWords.contains(word);
+ useDependencyVersion &= name.contains(word) || stopWords.contains(word)
+ || wordMatchesEcosystem(dependency.getEcosystem(), word);
}
}
@@ -1050,18 +1025,37 @@ private void considerDependencyVersion(Dependency dependency,
addVersionAndUpdate(depVersion, cpeBuilder);
try {
final Cpe depCpe = cpeBuilder.build();
- final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vendor, UTF8),
- URLEncoder.encode(product, UTF8), URLEncoder.encode(depCpe.getVersion(), UTF8));
+ final String url = CpeIdentifier.nvdSearchUrlFor(vendor, product, depCpe.getVersion());
final IdentifierMatch match = new IdentifierMatch(depCpe, url, IdentifierConfidence.EXACT_MATCH, confidence);
collected.add(match);
} catch (CpeValidationException ex) {
- throw new AnalysisException(String.format("Unable to create a CPE for %s:%s:%s", vendor, product, bestGuess.toString()));
+ throw new AnalysisException(String.format("Unable to create a CPE for %s:%s:%s", vendor, product, depVersion));
}
}
}
}
}
+ /**
+ * If a CPE product word represents the ecosystem of a dependency it is not required
+ * to appear in the dependencyName to still consider the CPE product a match.
+ *
+ * @param ecosystem The ecosystem of the dependency
+ * @param word The word from the CPE product to check
+ * @return {@code true} when the CPE product word is known to match the ecosystem of the dependency
+ * @implNote This method is not intended to cover every possible case where the ecosystem is represented by the word. It is a
+ * best-effort attempt to prevent {@link #considerDependencyVersion(Dependency, String, String, Confidence, Set)}
+ * from not taking an exact-match versioned CPE into account because the ecosystem-related word does not appear in
+ * the dependencyName. It helps prevent false-positive cases like https://github.com/dependency-check/DependencyCheck/issues/5545
+ * @see #considerDependencyVersion(Dependency, String, String, Confidence, Set)
+ */
+ private boolean wordMatchesEcosystem(@Nullable String ecosystem, String word) {
+ if (Ecosystem.JAVA.equalsIgnoreCase(word)) {
+ return Ecosystem.JAVA.equals(ecosystem);
+ }
+ return false;
+ }
+
/**
*
* Returns the setting key to determine if the analyzer is enabled.
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/CarthageAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/CarthageAnalyzer.java
new file mode 100644
index 00000000000..05d711a49d3
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/CarthageAnalyzer.java
@@ -0,0 +1,297 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2023 The OWASP Foundation. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import com.github.packageurl.MalformedPackageURLException;
+import com.github.packageurl.PackageURL;
+import com.github.packageurl.PackageURLBuilder;
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Confidence;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.utils.Checksum;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This analyzer is used to analyze SWIFT and Objective-C packages by collecting
+ * information from Cartfile files. Carthage dependency manager see
+ * https://github.com/Carthage/Carthage.
+ *
+ * Based on CocoaPodsAnalyzer by Bianca Jiang.
+ *
+ * @author Alin Radut (https://github.com/alinradut)
+ */
+@Experimental
+@ThreadSafe
+public class CarthageAnalyzer extends AbstractFileTypeAnalyzer {
+
+ /**
+ * A descriptor for the type of dependencies processed or added by this
+ * analyzer.
+ */
+ public static final String DEPENDENCY_ECOSYSTEM = Ecosystem.IOS;
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(CarthageAnalyzer.class);
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Carthage Package Analyzer";
+
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+
+ /**
+ * The file name to scan.
+ */
+ public static final String CARTFILE_RESOLVED = "Cartfile.resolved";
+ /**
+ * Filter that detects files named "Cartfile.resolved".
+ */
+ private static final FileFilter CARTHAGE_FILTER = FileFilterBuilder.newInstance().addFilenames(CARTFILE_RESOLVED).build();
+
+ /**
+ * The capture group #1 is the dependency type, #2 is the name, #3 is
+ * dependency version. The version can be a commit ref, so we can't assume
+ * it's a number
+ *
+ * Example values:
+ *
+ */
+ private static final Pattern CARTFILE_RESOLVED_BINARY_DEPENDENCY = Pattern.compile("([a-zA-Z0-9\\-_\\.]+).json");
+
+ /**
+ * Returns the FileFilter
+ *
+ * @return the FileFilter
+ */
+ @Override
+ protected FileFilter getFileFilter() {
+ return CARTHAGE_FILTER;
+ }
+
+ @Override
+ protected void prepareFileTypeAnalyzer(Engine engine) {
+ // NO-OP
+ }
+
+ /**
+ * Returns the name of the analyzer.
+ *
+ * @return the name of the analyzer.
+ */
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
+
+ /**
+ * Returns the phase that the analyzer is intended to run in.
+ *
+ * @return the phase that the analyzer is intended to run in.
+ */
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
+
+ /**
+ * Returns the key used in the properties file to reference the analyzer's
+ * enabled property.
+ *
+ * @return the analyzer's enabled property setting key
+ */
+ @Override
+ protected String getAnalyzerEnabledSettingKey() {
+ return Settings.KEYS.ANALYZER_CARTHAGE_ENABLED;
+ }
+
+ @Override
+ protected void analyzeDependency(Dependency dependency, Engine engine)
+ throws AnalysisException {
+ if (CARTFILE_RESOLVED.equals(dependency.getFileName())) {
+ analyzeCartfileResolvedDependency(dependency, engine);
+ }
+ }
+
+ /**
+ * Analyzes the Cartfile.resolved and adds the evidence to the dependency.
+ *
+ * @param cartfileResolved the dependency
+ * @param engine a reference to the dependency-check engine
+ * @throws AnalysisException thrown if there is an error analyzing the
+ * Cartfile
+ */
+ private void analyzeCartfileResolvedDependency(Dependency cartfileResolved, Engine engine)
+ throws AnalysisException {
+ engine.removeDependency(cartfileResolved);
+
+ final String contents;
+ try {
+ contents = new String(Files.readAllBytes(cartfileResolved.getActualFile().toPath()), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new AnalysisException(
+ "Problem occurred while reading dependency file.", e);
+ }
+
+ final Matcher matcher = CARTFILE_RESOLVED_DEPENDENCY_PATTERN.matcher(contents);
+ while (matcher.find()) {
+ final String type = matcher.group(1);
+ String name = matcher.group(2);
+ String version = matcher.group(3);
+
+ final Matcher versionMatcher = CARTFILE_VERSION_PATTERN.matcher(version);
+ if (versionMatcher.find()) {
+ version = versionMatcher.group(1);
+ } else {
+ // this is probably a git commit reference, so we'll default to 0.0.0.
+ // this will probably bubble up a ton of CVEs, but serves you right for
+ // not using semantic versioning.
+ version = "0.0.0";
+ }
+
+ if (type.contentEquals("git")) {
+ final Matcher nameMatcher = CARTFILE_RESOLVED_GIT_DEPENDENCY.matcher(name);
+ if (!nameMatcher.find()) {
+ continue;
+ }
+ name = nameMatcher.group(1);
+ } else if (type.contentEquals("github")) {
+ final Matcher nameMatcher = CARTFILE_RESOLVED_GITHUB_DEPENDENCY.matcher(name);
+ if (!nameMatcher.find()) {
+ continue;
+ }
+ name = nameMatcher.group(1);
+ } else if (type.contentEquals("binary")) {
+ final Matcher nameMatcher = CARTFILE_RESOLVED_BINARY_DEPENDENCY.matcher(name);
+ if (!nameMatcher.find()) {
+ continue;
+ }
+ name = nameMatcher.group(1);
+ }
+
+ final Dependency dependency = new Dependency(cartfileResolved.getActualFile(), true);
+ dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
+ dependency.setName(name);
+ dependency.setVersion(version);
+
+ try {
+ final PackageURLBuilder builder = PackageURLBuilder.aPackageURL().withType("carthage").withName(dependency.getName());
+ if (dependency.getVersion() != null) {
+ builder.withVersion(dependency.getVersion());
+ }
+ final PackageURL purl = builder.build();
+ dependency.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
+ } catch (MalformedPackageURLException ex) {
+ LOGGER.debug("Unable to build package url for carthage", ex);
+ final GenericIdentifier id;
+ if (dependency.getVersion() != null) {
+ id = new GenericIdentifier("carthage:" + dependency.getName() + "@" + dependency.getVersion(), Confidence.HIGHEST);
+ } else {
+ id = new GenericIdentifier("carthage:" + dependency.getName(), Confidence.HIGHEST);
+ }
+ dependency.addSoftwareIdentifier(id);
+ }
+
+ final String packagePath = String.format("%s:%s", name, version);
+ dependency.setPackagePath(packagePath);
+ dependency.setDisplayFileName(packagePath);
+ dependency.setSha1sum(Checksum.getSHA1Checksum(packagePath));
+ dependency.setSha256sum(Checksum.getSHA256Checksum(packagePath));
+ dependency.setMd5sum(Checksum.getMD5Checksum(packagePath));
+ dependency.addEvidence(EvidenceType.VENDOR, CARTFILE_RESOLVED, "name", name, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.PRODUCT, CARTFILE_RESOLVED, "name", name, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VERSION, CARTFILE_RESOLVED, "version", version, Confidence.HIGHEST);
+ engine.addDependency(dependency);
+ }
+ }
+
+ /**
+ * Sets the package path on the given dependency.
+ *
+ * @param dep the dependency to update
+ */
+ private void setPackagePath(Dependency dep) {
+ final File file = new File(dep.getFilePath());
+ final String parent = file.getParent();
+ if (parent != null) {
+ dep.setPackagePath(parent);
+ }
+ }
+}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java
index 1495bcb6b70..be270c96e8e 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java
@@ -17,20 +17,34 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.jcs3.access.exception.CacheException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
+import org.owasp.dependencycheck.data.cache.DataCache;
+import org.owasp.dependencycheck.data.cache.DataCacheFactory;
import org.owasp.dependencycheck.data.central.CentralSearch;
-import org.owasp.dependencycheck.utils.TooManyRequestsException;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.exception.InitializationException;
+import org.owasp.dependencycheck.utils.DownloadFailedException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.FileUtils;
+import org.owasp.dependencycheck.utils.ForbiddenException;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
+import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
+import org.owasp.dependencycheck.xml.pom.Model;
import org.owasp.dependencycheck.xml.pom.PomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
@@ -39,20 +53,6 @@
import java.net.URL;
import java.text.MessageFormat;
import java.util.List;
-import javax.annotation.concurrent.ThreadSafe;
-import org.apache.commons.jcs.access.exception.CacheException;
-import org.owasp.dependencycheck.data.cache.DataCache;
-import org.owasp.dependencycheck.data.cache.DataCacheFactory;
-
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.exception.InitializationException;
-import org.owasp.dependencycheck.utils.DownloadFailedException;
-import org.owasp.dependencycheck.utils.Downloader;
-import org.owasp.dependencycheck.utils.FileFilterBuilder;
-import org.owasp.dependencycheck.utils.InvalidSettingException;
-import org.owasp.dependencycheck.utils.ResourceNotFoundException;
-import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.xml.pom.Model;
/**
* Analyzer which will attempt to locate a dependency, and the GAV information,
@@ -242,12 +242,12 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
LOGGER.debug("Unable to delete temp file");
}
- final Downloader downloader = new Downloader(getSettings());
final int maxAttempts = this.getSettings().getInt(Settings.KEYS.ANALYZER_CENTRAL_RETRY_COUNT, 3);
int retryCount = 0;
long sleepingTimeBetweenRetriesInMillis = BASE_RETRY_WAIT;
boolean success = false;
Model model = null;
+ DownloadFailedException lastException = null;
if (cache != null) {
model = cache.get(ma.getPomUrl());
}
@@ -259,9 +259,10 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
do {
//CSOFF: NestedTryDepth
try {
- downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
+ Downloader.getInstance().fetchFile(new URL(ma.getPomUrl()), pomFile);
success = true;
} catch (DownloadFailedException ex) {
+ lastException = ex;
try {
Thread.sleep(sleepingTimeBetweenRetriesInMillis);
} catch (InterruptedException ex1) {
@@ -288,6 +289,10 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
} else {
LOGGER.warn("Unable to download pom.xml for {} from Central; "
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
+ setEnabled(false);
+ LOGGER.warn("Disabling the Central Analyzer due to repeated download failures; Central Search "
+ + "may be down see https://status.maven.org/\n Note that this could result in both false "
+ + "positives and false negatives", lastException);
}
} catch (AnalysisException ex) {
@@ -295,7 +300,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
+ "this could result in undetected CPE/CVEs.", dependency.getFileName()), ex);
} finally {
- if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
+ if (pomFile != null && pomFile.exists() && !FileUtils.delete(pomFile)) {
LOGGER.debug("Failed to delete temporary pom file {}", pomFile);
pomFile.deleteOnExit();
}
@@ -304,15 +309,25 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
}
} catch (TooManyRequestsException tre) {
this.setEnabled(false);
- final String message = "Connections to Central search refused. Analysis failed.";
+ final String message = "Connections to Central search refused. Analysis failed. Disabling Central analyzer - this " +
+ "could lead to both false positives and false negatives.";
LOGGER.error(message, tre);
throw new AnalysisException(message, tre);
} catch (IllegalArgumentException iae) {
LOGGER.info("invalid sha1-hash on {}", dependency.getFileName());
} catch (FileNotFoundException fnfe) {
LOGGER.debug("Artifact not found in repository: '{}", dependency.getFileName());
+ } catch (ForbiddenException e) {
+ this.setEnabled(false);
+ final String message = "Connection to Central search refused. This is most likely not a problem with " +
+ "Dependency-Check itself and is related to network connectivity. Please check " +
+ "https://central.sonatype.org/faq/403-error-central/.";
+ LOGGER.error(message);
+ throw new AnalysisException(message, e);
} catch (IOException ioe) {
- final String message = "Could not connect to Central search. Analysis failed.";
+ this.setEnabled(false);
+ final String message = "Could not connect to Central search. Analysis failed; disabling Central analyzer - this " +
+ "could lead to both false positives and false negatives.";
LOGGER.error(message, ioe);
throw new AnalysisException(message, ioe);
}
@@ -332,7 +347,8 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
* @throws TooManyRequestsException if Central has received too many
* requests.
*/
- protected List fetchMavenArtifacts(Dependency dependency) throws IOException, TooManyRequestsException {
+ protected List fetchMavenArtifacts(Dependency dependency) throws IOException,
+ TooManyRequestsException {
IOException lastException = null;
long sleepingTimeBetweenRetriesInMillis = BASE_RETRY_WAIT;
int triesLeft = numberOfRetries;
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java
index 21be018850b..4b347bd3061 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java
@@ -20,15 +20,6 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -37,12 +28,21 @@
import org.owasp.dependencycheck.dependency.EvidenceType;
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.utils.Checksum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* This analyzer is used to analyze SWIFT and Objective-C packages by collecting
* information from .podspec files. CocoaPods dependency manager see
@@ -170,7 +170,7 @@ private void analyzePodfileLockDependencies(Dependency podfileLock, Engine engin
final String contents;
try {
- contents = FileUtils.readFileToString(podfileLock.getActualFile(), Charset.defaultCharset());
+ contents = new String(Files.readAllBytes(podfileLock.getActualFile().toPath()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -229,7 +229,7 @@ private void analyzePodspecDependency(Dependency dependency)
dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
String contents;
try {
- contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
+ contents = new String(Files.readAllBytes(dependency.getActualFile().toPath()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -260,6 +260,7 @@ private void analyzePodspecDependency(Dependency dependency)
final String summary = determineEvidence(contents, blockVariable, "summary");
if (!summary.isEmpty()) {
dependency.addEvidence(EvidenceType.PRODUCT, PODSPEC, "summary", summary, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, PODSPEC, "summary", summary, Confidence.MEDIUM);
}
final String author = determineEvidence(contents, blockVariable, "authors?");
@@ -269,6 +270,7 @@ private void analyzePodspecDependency(Dependency dependency)
final String homepage = determineEvidence(contents, blockVariable, "homepage");
if (!homepage.isEmpty()) {
dependency.addEvidence(EvidenceType.VENDOR, PODSPEC, "homepage", homepage, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.PRODUCT, PODSPEC, "homepage", homepage, Confidence.LOW);
}
final String license = determineEvidence(contents, blockVariable, "licen[cs]es?");
if (!license.isEmpty()) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java
index 99f2c200dbf..43be4322194 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java
@@ -108,7 +108,8 @@ protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationExcep
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
engine.removeDependency(dependency);
try (FileInputStream fis = new FileInputStream(dependency.getActualFile())) {
- final ComposerLockParser clp = new ComposerLockParser(fis);
+ final boolean skipdev = getSettings().getBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_SKIP_DEV, false);
+ final ComposerLockParser clp = new ComposerLockParser(fis, skipdev);
LOGGER.debug("Checking composer.lock file {}", dependency.getActualFilePath());
clp.process();
clp.getDependencies().stream().map((dep) -> {
@@ -132,7 +133,9 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
d.setSha256sum(Checksum.getSHA256Checksum(filePath));
d.setMd5sum(Checksum.getMD5Checksum(filePath));
d.addEvidence(EvidenceType.VENDOR, COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.PRODUCT, COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.MEDIUM);
d.addEvidence(EvidenceType.PRODUCT, COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.VENDOR, COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGH);
d.addEvidence(EvidenceType.VERSION, COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
return d;
}).forEach((d) -> {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java
index 07c596275d0..432330fa88e 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java
@@ -47,7 +47,7 @@ public class DependencyMergingAnalyzer extends AbstractDependencyComparingAnalyz
/**
* The phase that this analyzer is intended to run in.
*/
- private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION;
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION1;
/**
* Used for synchronization when merging related dependencies.
*/
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/GolangModAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/GolangModAnalyzer.java
index b23a63932a3..b87d408cfee 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/GolangModAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/GolangModAnalyzer.java
@@ -32,7 +32,7 @@
import java.util.ArrayList;
import java.util.List;
-import javax.json.stream.JsonParsingException;
+import jakarta.json.stream.JsonParsingException;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
import org.owasp.dependencycheck.processing.GoModProcessor;
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java
index 37787063628..2a4cd757dc5 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java
@@ -17,22 +17,12 @@
*/
package org.owasp.dependencycheck.analyzer;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.EvidenceType;
import org.owasp.dependencycheck.exception.InitializationException;
-import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
@@ -40,14 +30,26 @@
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.TooManyRequestsException;
import org.owasp.dependencycheck.xml.hints.EvidenceMatcher;
-import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule;
import org.owasp.dependencycheck.xml.hints.HintParseException;
import org.owasp.dependencycheck.xml.hints.HintParser;
import org.owasp.dependencycheck.xml.hints.HintRule;
+import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule;
+import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
/**
* This analyzer adds evidence to dependencies to enhance the accuracy of
* library identification.
@@ -80,7 +82,7 @@ public class HintAnalyzer extends AbstractAnalyzer {
/**
* The phase that this analyzer is intended to run in.
*/
- private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION2;
/**
* Returns the name of the analyzer.
@@ -198,7 +200,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
for (VendorDuplicatingHintRule dhr : vendorHints) {
if (dhr.getValue().equalsIgnoreCase(e.getValue())) {
dependency.addEvidence(EvidenceType.VENDOR, new Evidence(e.getSource() + " (hint)",
- e.getName(), dhr.getDuplicate(), e.getConfidence()));
+ e.getName(), dhr.getDuplicate(), e.getConfidence(), true));
}
}
}
@@ -265,13 +267,12 @@ private void loadHintRules() throws HintParseException {
deleteTempFile = true;
file = getSettings().getTempFile("hint", "xml");
final URL url = new URL(filePath);
- final Downloader downloader = new Downloader(getSettings());
try {
- downloader.fetchFile(url, file, false);
+ Downloader.getInstance().fetchFile(url, file, false);
} catch (DownloadFailedException ex) {
try {
Thread.sleep(500);
- downloader.fetchFile(url, file, true);
+ Downloader.getInstance().fetchFile(url, file, true);
} catch (TooManyRequestsException ex1) {
throw new HintParseException("Unable to download hint file `" + file + "`; received 429 - too many requests", ex1);
} catch (ResourceNotFoundException ex1) {
@@ -291,7 +292,7 @@ private void loadHintRules() throws HintParseException {
try (InputStream fromClasspath = FileUtils.getResourceAsStream(filePath)) {
deleteTempFile = true;
file = getSettings().getTempFile("hint", "xml");
- org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
+ Files.copy(fromClasspath, file.toPath());
} catch (IOException ex) {
throw new HintParseException("Unable to locate hints file in classpath", ex);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
index 60e4185f905..8288148c119 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
@@ -54,7 +54,7 @@
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
-import org.h2.util.IOUtils;
+import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
@@ -160,7 +160,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
"dstamp",
"eclipse-sourcereferences",
"kotlin-version",
- "require-capability");
+ "require-capability",
+ "require-bundle");
/**
* Deprecated Jar manifest attribute, that is, nonetheless, useful for
* analysis.
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/LibmanAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/LibmanAnalyzer.java
new file mode 100644
index 00000000000..8013e704239
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/LibmanAnalyzer.java
@@ -0,0 +1,245 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2023 The OWASP Foundation. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import com.github.packageurl.MalformedPackageURLException;
+import com.github.packageurl.PackageURL;
+import com.github.packageurl.PackageURLBuilder;
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Confidence;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
+import org.owasp.dependencycheck.utils.Checksum;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Analyzer which parses a libman.json file to gather module information.
+ *
+ * @author Arjen Korevaar
+ */
+@ThreadSafe
+public class LibmanAnalyzer extends AbstractFileTypeAnalyzer {
+
+ /**
+ * A descriptor for the type of dependencies processed or added by this
+ * analyzer.
+ */
+ private static final String DEPENDENCY_ECOSYSTEM = Ecosystem.NODEJS;
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(LibmanAnalyzer.class);
+
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Libman Analyzer";
+
+ /**
+ * The phase in which the analyzer runs.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
+
+ /**
+ * The file filter used to determine which files this analyzer supports.
+ */
+ private static final String FILE_NAME = "libman.json";
+
+ /**
+ * The file filter used to determine which files this analyzer supports.
+ */
+ private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames(FILE_NAME).build();
+
+ /**
+ * Regex used to match Library property.
+ */
+ private static final Pattern LIBRARY_REGEX = Pattern
+ .compile("(\\@(?[a-zA-Z]+)\\/)?(?.+)\\@(?.+)", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Initializes the analyzer once before any analysis is performed.
+ *
+ * @param engine a reference to the dependency-check engine
+ * @throws InitializationException if there's an error during initialization
+ */
+ @Override
+ public void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
+ // nothing to initialize
+ }
+
+ /**
+ * Returns the analyzer's name.
+ *
+ * @return the name of the analyzer
+ */
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
+
+ /**
+ * Returns the key used in the properties file to reference the analyzer's
+ * enabled property.
+ *
+ * @return the analyzer's enabled property setting key
+ */
+ @Override
+ protected String getAnalyzerEnabledSettingKey() {
+ return Settings.KEYS.ANALYZER_LIBMAN_ENABLED;
+ }
+
+ /**
+ * Returns the analysis phase under which the analyzer runs.
+ *
+ * @return the phase under which this analyzer runs
+ */
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
+
+ /**
+ * Returns the FileFilter
+ *
+ * @return the FileFilter
+ */
+ @Override
+ protected FileFilter getFileFilter() {
+ return FILTER;
+ }
+
+ /**
+ * Performs the analysis.
+ *
+ * @param dependency the dependency to analyze
+ * @param engine the engine
+ * @throws AnalysisException when there's an exception during analysis
+ */
+ @Override
+ public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
+ LOGGER.debug("Checking file {}", dependency.getActualFilePath());
+
+ if (FILE_NAME.equals(dependency.getFileName()) && !dependency.isVirtual()) {
+ engine.removeDependency(dependency);
+ }
+
+ final File dependencyFile = dependency.getActualFile();
+
+ if (!dependencyFile.isFile() || dependencyFile.length() == 0) {
+ return;
+ }
+
+ try (JsonReader jsonReader = Json.createReader(Files.newInputStream(dependencyFile.toPath()))) {
+ final JsonObject json = jsonReader.readObject();
+
+ final String libmanVersion = json.getString("version");
+
+ if (!"1.0".equals(libmanVersion)) {
+ LOGGER.warn("The Libman analyzer currently only supports Libman version 1.0");
+ return;
+ }
+
+ final String defaultProvider = json.getString("defaultProvider");
+ final JsonArray libraries = json.getJsonArray("libraries");
+
+ libraries.forEach(e -> {
+ final JsonObject reference = (JsonObject) e;
+
+ final String provider = reference.getString("provider", defaultProvider);
+ final String library = reference.getString("library");
+
+ if ("filesystem".equals(provider)) {
+ LOGGER.warn("Unable to determine name and version for filesystem package: {}", library);
+ return;
+ }
+
+ final Matcher matcher = LIBRARY_REGEX.matcher(library);
+
+ if (!matcher.find()) {
+ LOGGER.warn("Unable to parse library, unknown format: {}", library);
+ return;
+ }
+
+ final String vendor = matcher.group("package");
+ final String name = matcher.group("name");
+ final String version = matcher.group("version");
+
+ LOGGER.debug("Found Libman package: vendor {}, name {}, version {}", vendor, name, version);
+
+ final Dependency child = new Dependency(dependency.getActualFile(), true);
+
+ child.setEcosystem(DEPENDENCY_ECOSYSTEM);
+ child.setName(name);
+ child.setVersion(version);
+
+ if (vendor != null) {
+ child.addEvidence(EvidenceType.VENDOR, FILE_NAME, "vendor", vendor, Confidence.HIGHEST);
+ }
+ child.addEvidence(EvidenceType.VENDOR, FILE_NAME, "name", name, Confidence.HIGH);
+ child.addEvidence(EvidenceType.PRODUCT, FILE_NAME, "name", name, Confidence.HIGHEST);
+ child.addEvidence(EvidenceType.VERSION, FILE_NAME, "version", version, Confidence.HIGHEST);
+
+ final String packagePath = String.format("%s:%s", name, version);
+
+ child.setSha1sum(Checksum.getSHA1Checksum(packagePath));
+ child.setSha256sum(Checksum.getSHA256Checksum(packagePath));
+ child.setMd5sum(Checksum.getMD5Checksum(packagePath));
+ child.setPackagePath(packagePath);
+
+ try {
+ final PackageURL purl = PackageURLBuilder.aPackageURL()
+ .withType("libman")
+ .withName(name)
+ .withVersion(version)
+ .build();
+ final PurlIdentifier id = new PurlIdentifier(purl, Confidence.HIGHEST);
+ child.addSoftwareIdentifier(id);
+ } catch (MalformedPackageURLException ex) {
+ LOGGER.warn("Unable to build package url for {}", ex.toString());
+ }
+
+ engine.addDependency(child);
+ });
+ } catch (JsonException e) {
+ LOGGER.warn(String.format("Failed to parse %s file", FILE_NAME), e);
+ } catch (IOException e) {
+ throw new AnalysisException("Problem occurred while reading dependency file", e);
+ }
+ }
+}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/MSBuildProjectAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/MSBuildProjectAnalyzer.java
index c7a69aef755..f68718e4947 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/MSBuildProjectAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/MSBuildProjectAnalyzer.java
@@ -150,7 +150,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
final List packages;
try (FileInputStream fis = new FileInputStream(dependency.getActualFilePath());
- BOMInputStream bis = new BOMInputStream(fis)) {
+ BOMInputStream bis = BOMInputStream.builder().setInputStream(fis).get()) {
//skip BOM if it exists
bis.getBOM();
packages = parser.parse(bis, props, centrallyManaged);
@@ -185,6 +185,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
child.setMd5sum(Checksum.getMD5Checksum(String.format("%s:%s", id, version)));
child.addEvidence(EvidenceType.PRODUCT, "msbuild", "id", id, Confidence.HIGHEST);
+ child.addEvidence(EvidenceType.VENDOR, "msbuild", "id", id, Confidence.MEDIUM);
child.addEvidence(EvidenceType.VERSION, "msbuild", "version", version, Confidence.HIGHEST);
if (id.indexOf('.') > 0) {
@@ -193,10 +194,12 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
// example: Microsoft.EntityFrameworkCore
child.addEvidence(EvidenceType.VENDOR, "msbuild", "id", parts[0], Confidence.MEDIUM);
child.addEvidence(EvidenceType.PRODUCT, "msbuild", "id", parts[1], Confidence.MEDIUM);
+ child.addEvidence(EvidenceType.VENDOR, "msbuild", "id", parts[1], Confidence.LOW);
if (parts.length > 2) {
final String rest = id.substring(id.indexOf('.') + 1);
child.addEvidence(EvidenceType.PRODUCT, "msbuild", "id", rest, Confidence.MEDIUM);
+ child.addEvidence(EvidenceType.VENDOR, "msbuild", "id", rest, Confidence.LOW);
}
} else {
// example: jQuery
@@ -315,7 +318,7 @@ private Map readDirectoryBuildProps(File directoryProps) throws
if (directoryProps != null && directoryProps.isFile()) {
final DirectoryBuildPropsParser parser = new DirectoryBuildPropsParser();
try (FileInputStream fis = new FileInputStream(directoryProps);
- BOMInputStream bis = new BOMInputStream(fis)) {
+ BOMInputStream bis = BOMInputStream.builder().setInputStream(fis).get()) {
//skip BOM if it exists
bis.getBOM();
entries = parser.parse(bis);
@@ -344,7 +347,7 @@ private Map loadCentrallyManaged(File folder, Properties props)
if (packages != null && packages.isFile()) {
final DirectoryPackagesPropsParser parser = new DirectoryPackagesPropsParser();
try (FileInputStream fis = new FileInputStream(packages);
- BOMInputStream bis = new BOMInputStream(fis)) {
+ BOMInputStream bis = BOMInputStream.builder().setInputStream(fis).get()) {
//skip BOM if it exists
bis.getBOM();
return parser.parse(bis, props);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
index b5828678402..2b1014a113d 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
@@ -17,14 +17,17 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
+
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.data.nexus.NexusSearch;
+import org.owasp.dependencycheck.data.nexus.NexusV2Search;
+import org.owasp.dependencycheck.data.nexus.NexusV3Search;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
+import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.xml.pom.PomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,6 +38,7 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Locale;
import javax.annotation.concurrent.ThreadSafe;
import org.owasp.dependencycheck.dependency.EvidenceType;
import org.owasp.dependencycheck.exception.InitializationException;
@@ -169,17 +173,38 @@ public void prepareFileTypeAnalyzer(Engine engine) throws InitializationExceptio
if (isEnabled()) {
final boolean useProxy = useProxy();
LOGGER.debug("Using proxy: {}", useProxy);
- try {
- searcher = new NexusSearch(getSettings(), useProxy);
- if (!searcher.preflightRequest()) {
- setEnabled(false);
- throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
- }
- } catch (MalformedURLException mue) {
+ searcher = createNexusSearchOrDisable(useProxy);
+ }
+ }
+
+ /**
+ * Creates a NexusSearch for the appropriate Nexus version (Nexus V2 and V3 supported).
+ *
+ * If errors are encountered creating or validating the NexusSearch it disables this analyzer.
+ *
+ * @param useProxy Whether a proxy is to be used
+ * @return A NexusSearch appropriate for the configured ANALYZER_NEXUS_URL
+ * @throws InitializationException Upon errors creating of validating the ANALYZER_NEXUS_URL
+ */
+ private NexusSearch createNexusSearchOrDisable(boolean useProxy) throws InitializationException {
+ final Settings settings = getSettings();
+ final String nexusRootURL = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
+ final NexusSearch result;
+ try {
+ if (nexusRootURL.toLowerCase(Locale.ROOT).contains("service/local/")) {
+ result = new NexusV2Search(settings, useProxy);
+ } else {
+ result = new NexusV3Search(settings, useProxy);
+ }
+ if (!result.preflightRequest()) {
setEnabled(false);
- throw new InitializationException("Malformed URL to Nexus", mue);
+ throw new InitializationException("There was an error getting Nexus status. Disabling NexusAnalyzer.");
}
+ } catch (MalformedURLException mue) {
+ setEnabled(false);
+ throw new InitializationException("Malformed URL to Nexus. Disabling NexusAnalyzer", mue);
}
+ return result;
}
/**
@@ -257,8 +282,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
LOGGER.debug("Unable to delete temp file");
}
LOGGER.debug("Downloading {}", ma.getPomUrl());
- final Downloader downloader = new Downloader(getSettings());
- downloader.fetchFile(new URL(ma.getPomUrl()), pomFile);
+ Downloader.getInstance().fetchFile(new URL(ma.getPomUrl()), pomFile);
PomUtils.analyzePOM(dependency, pomFile);
} catch (DownloadFailedException ex) {
LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
@@ -271,7 +295,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
LOGGER.warn("pom.xml not found for {} from nexus; "
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
} finally {
- if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
+ if (pomFile != null && pomFile.exists() && !FileUtils.delete(pomFile)) {
LOGGER.debug("Failed to delete temporary pom file {}", pomFile);
pomFile.deleteOnExit();
}
@@ -297,8 +321,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
*/
public boolean useProxy() {
try {
- return getSettings().getString(Settings.KEYS.PROXY_SERVER) != null
- && getSettings().getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
+ return getSettings().getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
} catch (InvalidSettingException ise) {
LOGGER.warn("Failed to parse proxy settings.", ise);
return false;
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
index b186f0eadf1..c6de926ed56 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodeAuditAnalyzer.java
@@ -17,34 +17,34 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.analyzer.exception.SearchException;
+import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
import org.owasp.dependencycheck.data.nodeaudit.Advisory;
import org.owasp.dependencycheck.data.nodeaudit.NpmPayloadBuilder;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.URLConnectionFailureException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import us.springett.parsers.cpe.exceptions.CpeValidationException;
+
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.List;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import org.apache.commons.collections4.MultiValuedMap;
-import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
-import org.owasp.dependencycheck.analyzer.exception.SearchException;
-import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
-import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
-import org.owasp.dependencycheck.utils.URLConnectionFailureException;
-import us.springett.parsers.cpe.exceptions.CpeValidationException;
-
/**
* Used to analyze Node Package Manager (npm) package-lock.json and
* npm-shrinkwrap.json files via NPM Audit API.
@@ -171,11 +171,11 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
* submitting the npm audit API payload
*/
private List analyzePackage(final File lockFile, final File packageFile,
- Dependency dependency, MultiValuedMap dependencyMap)
+ Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
try {
- final JsonReader packageReader = Json.createReader(FileUtils.openInputStream(packageFile));
- final JsonReader lockReader = Json.createReader(FileUtils.openInputStream(lockFile));
+ final JsonReader packageReader = Json.createReader(Files.newInputStream(packageFile.toPath()));
+ final JsonReader lockReader = Json.createReader(Files.newInputStream(lockFile.toPath()));
// Retrieves the contents of package-lock.json from the Dependency
final JsonObject lockJson = lockReader.readObject();
// Retrieves the contents of package-lock.json from the Dependency
@@ -231,7 +231,7 @@ private List analyzePackage(final File lockFile, final File packageFil
private List legacyAnalysis(final File file, Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
- try (JsonReader jsonReader = Json.createReader(FileUtils.openInputStream(file))) {
+ try (JsonReader jsonReader = Json.createReader(Files.newInputStream(file.toPath()))) {
// Retrieves the contents of package-lock.json from the Dependency
final JsonObject packageJson = jsonReader.readObject();
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java
index 68e2eca3016..650bcf9ce8c 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java
@@ -20,39 +20,39 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.Engine.Mode;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
+import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonReader;
-import javax.json.JsonValue;
-import org.owasp.dependencycheck.Engine.Mode;
-import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
-import org.owasp.dependencycheck.dependency.Confidence;
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
-import org.owasp.dependencycheck.exception.InitializationException;
-import org.owasp.dependencycheck.utils.Checksum;
-import org.owasp.dependencycheck.utils.InvalidSettingException;
/**
* Used to analyze Node Package Manager (npm) package.json files, and collect
@@ -93,7 +93,7 @@ public class NodePackageAnalyzer extends AbstractNpmAnalyzer {
*/
public static final String SHRINKWRAP_JSON = "npm-shrinkwrap.json";
/**
- * The name of the directory that contains node modules
+ * The name of the directory that contains node modules.
*/
public static final String NODE_MODULES_DIRNAME = "node_modules";
/**
@@ -196,7 +196,8 @@ private boolean isNodeAuditEnabled(Engine engine) {
try {
((AbstractNpmAnalyzer) a).prepareFileTypeAnalyzer(engine);
} catch (InitializationException ex) {
- LOGGER.debug("Error initializing the {}", a.getName());
+ String message = "Error initializing the " + a.getName();
+ LOGGER.debug(message, ex);
}
}
return a.isEnabled();
@@ -252,7 +253,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
return;
}
- try (JsonReader jsonReader = Json.createReader(FileUtils.openInputStream(dependencyFile))) {
+ try (JsonReader jsonReader = Json.createReader(Files.newInputStream(dependencyFile.toPath()))) {
final JsonObject json = jsonReader.readObject();
final String parentName = json.getString("name", "");
final String parentVersion = json.getString("version", "");
@@ -303,7 +304,7 @@ public static boolean shouldSkipDependency(String name, String version, boolean
// using a local node_module is not supported by npm audit, it crash
if (Objects.nonNull(version) && (version.startsWith("file:") || version.matches("^[.~]{0,2}/.*"))) {
LOGGER.warn("dependency skipped: package.json contain an local node_module for {} seems to be "
- + "located {} npm audit doesn't support locally referenced modules",
+ + "located {} npm audit doesn't support locally referenced modules",
name, version);
return true;
}
@@ -320,12 +321,12 @@ public static boolean shouldSkipDependency(String name, String version, boolean
/**
* Checks if the given dependency should be skipped.
*
- * @see NodePackageAnalyzer#shouldSkipDependency(java.lang.String,
- * java.lang.String, boolean, boolean)
* @param name the name of the dependency to test
* @param version the version of the dependency to test
* @return true if the dependency should be skipped; otherwise
* false
+ * @see NodePackageAnalyzer#shouldSkipDependency(java.lang.String,
+ * java.lang.String, boolean, boolean)
*/
public static boolean shouldSkipDependency(String name, String version) {
return shouldSkipDependency(name, version, false, true);
@@ -344,20 +345,20 @@ public static boolean shouldSkipDependency(String name, String version) {
* @throws AnalysisException thrown if there is an exception
*/
private void processDependencies(JsonObject json, File baseDir, File rootFile,
- String parentPackage, Engine engine) throws AnalysisException {
- final boolean skipDev = getSettings().getBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_SKIPDEV, false);
- final JsonObject deps;
- final File modulesRoot = new File(rootFile.getParentFile(), "node_modules");
- final int lockJsonVersion = json.containsKey("lockfileVersion") ? json.getInt("lockfileVersion") : 1;
- if (lockJsonVersion >= 2) {
+ String parentPackage, Engine engine) throws AnalysisException {
+ final boolean skipDev = getSettings().getBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_SKIPDEV, false);
+ final JsonObject deps;
+ final File modulesRoot = new File(rootFile.getParentFile(), "node_modules");
+ final int lockJsonVersion = json.containsKey("lockfileVersion") ? json.getInt("lockfileVersion") : 1;
+ if (lockJsonVersion >= 2) {
deps = json.getJsonObject("packages");
- } else if (json.containsKey("dependencies")) {
+ } else if (json.containsKey("dependencies")) {
deps = json.getJsonObject("dependencies");
- } else {
+ } else {
deps = null;
- }
+ }
- if (deps != null) {
+ if (deps != null) {
for (Map.Entry entry : deps.entrySet()) {
final String pathName = entry.getKey();
String name = pathName;
@@ -428,7 +429,7 @@ private void processDependencies(JsonObject json, File baseDir, File rootFile,
} catch (IOException | NoSuchAlgorithmException ex) {
LOGGER.debug("Error setting hashes:" + ex.getMessage(), ex);
}
- try (JsonReader jr = Json.createReader(FileUtils.openInputStream(f))) {
+ try (JsonReader jr = Json.createReader(Files.newInputStream(f.toPath()))) {
final JsonObject childJson = jr.readObject();
gatherEvidence(childJson, child);
} catch (JsonException e) {
@@ -458,18 +459,19 @@ private void processDependencies(JsonObject json, File baseDir, File rootFile,
LOGGER.debug("Unable to build package url for `" + packagePath + "`", ex);
}
}
-
- final Dependency existing = findDependency(engine, name, version);
- if (existing != null) {
- if (existing.isVirtual()) {
- DependencyMergingAnalyzer.mergeDependencies(child, existing, null);
- engine.removeDependency(existing);
- engine.addDependency(child);
+ synchronized (this) {
+ final Dependency existing = findDependency(engine, name, version);
+ if (existing != null) {
+ if (existing.isVirtual()) {
+ DependencyMergingAnalyzer.mergeDependencies(child, existing, null);
+ engine.removeDependency(existing);
+ engine.addDependency(child);
+ } else {
+ DependencyBundlingAnalyzer.mergeDependencies(existing, child, null);
+ }
} else {
- DependencyBundlingAnalyzer.mergeDependencies(existing, child, null);
+ engine.addDependency(child);
}
- } else {
- engine.addDependency(child);
}
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NpmCPEAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NpmCPEAnalyzer.java
index 0acce56f45c..530a5d669ad 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NpmCPEAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NpmCPEAnalyzer.java
@@ -49,7 +49,7 @@ public class NpmCPEAnalyzer extends CPEAnalyzer {
/**
* The Logger.
*/
- private static final Logger LOGGER = LoggerFactory.getLogger(CPEAnalyzer.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(NpmCPEAnalyzer.class);
/**
* Returns the analysis phase that this analyzer should run in.
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NugetconfAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NugetconfAnalyzer.java
index 3e98913ef2e..11417208d6e 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NugetconfAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NugetconfAnalyzer.java
@@ -182,6 +182,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
child.setMd5sum(Checksum.getMD5Checksum(String.format("%s:%s", id, version)));
child.addEvidence(EvidenceType.VERSION, "packages.config", "version", np.getVersion(), Confidence.HIGHEST);
child.addEvidence(EvidenceType.PRODUCT, "packages.config", "id", np.getId(), Confidence.HIGHEST);
+ child.addEvidence(EvidenceType.VENDOR, "packages.config", "id", np.getId(), Confidence.MEDIUM);
// handle package names the same way as the MSBuild analyzer
if (id.indexOf('.') > 0) {
@@ -190,10 +191,12 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
// example: Microsoft.EntityFrameworkCore
child.addEvidence(EvidenceType.VENDOR, "packages.config", "id", parts[0], Confidence.MEDIUM);
child.addEvidence(EvidenceType.PRODUCT, "packages.config", "id", parts[1], Confidence.MEDIUM);
+ child.addEvidence(EvidenceType.VENDOR, "packages.config", "id", parts[1], Confidence.LOW);
if (parts.length > 2) {
final String rest = id.substring(id.indexOf('.') + 1);
child.addEvidence(EvidenceType.PRODUCT, "packages.config", "id", rest, Confidence.MEDIUM);
+ child.addEvidence(EvidenceType.VENDOR, "packages.config", "id", rest, Confidence.LOW);
}
} else {
// example: jQuery
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java
index 5f3124dc0c4..44aeb555023 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java
@@ -158,6 +158,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
dependency.addEvidence(EvidenceType.VENDOR, "nuspec", "authors", np.getAuthors(), Confidence.HIGH);
dependency.addEvidence(EvidenceType.VERSION, "nuspec", "version", np.getVersion(), Confidence.HIGHEST);
dependency.addEvidence(EvidenceType.PRODUCT, "nuspec", "id", np.getId(), Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, "nuspec", "id", np.getId(), Confidence.HIGH);
dependency.addEvidence(EvidenceType.VENDOR, "nuspec", "description", np.getDescription(), Confidence.LOW);
dependency.addEvidence(EvidenceType.PRODUCT, "nuspec", "description", np.getDescription(), Confidence.LOW);
dependency.setName(np.getId());
@@ -178,6 +179,7 @@ public void analyzeDependency(Dependency dependency, Engine engine) throws Analy
}
if (np.getTitle() != null) {
dependency.addEvidence(EvidenceType.PRODUCT, "nuspec", "title", np.getTitle(), Confidence.MEDIUM);
+ dependency.addEvidence(EvidenceType.VENDOR, "nuspec", "title", np.getTitle(), Confidence.LOW);
}
} catch (Throwable e) {
throw new AnalysisException(e);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java
index 1ba5986dd07..bcb5ff6d816 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java
@@ -18,7 +18,9 @@
package org.owasp.dependencycheck.analyzer;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.annotation.concurrent.ThreadSafe;
import org.owasp.dependencycheck.Engine;
@@ -150,17 +152,17 @@ private synchronized List filterEcosystem(String ecosystem, List<
final List remove = new ArrayList<>();
vulnerabilities.forEach((v) -> {
boolean found = false;
- final List removeSoftare = new ArrayList<>();
+ final Set removeSoftware = new HashSet<>();
for (VulnerableSoftware s : v.getVulnerableSoftware()) {
if (ecosystemMatchesTargetSoftware(ecosystem, s.getTargetSw())) {
found = true;
} else {
- removeSoftare.add(s);
+ removeSoftware.add(s);
}
}
if (found) {
- if (!removeSoftare.isEmpty()) {
- removeSoftare.forEach(v.getVulnerableSoftware()::remove);
+ if (!removeSoftware.isEmpty()) {
+ v.removeVulnerableSoftware(removeSoftware);
}
} else {
remove.add(v);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java
index b1ed360abe6..33f7ce947e0 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java
@@ -20,27 +20,27 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
-import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
-import org.owasp.dependencycheck.exception.InitializationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Used to analyze OpenSSL source code present in the file system.
@@ -72,7 +72,7 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Pattern VERSION_PATTERN = Pattern.compile(
"define\\s+OPENSSL_VERSION_NUMBER\\s+0x([0-9a-zA-Z]{8})L", Pattern.DOTALL
- | Pattern.CASE_INSENSITIVE);
+ | Pattern.CASE_INSENSITIVE);
/**
* The offset of the major version number.
*/
@@ -231,7 +231,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine)
private String getFileContents(final File actualFile)
throws AnalysisException {
try {
- return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ return new String(Files.readAllBytes(actualFile.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/OssIndexAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/OssIndexAnalyzer.java
index 344d6996c61..cae89d79467 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/OssIndexAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/OssIndexAnalyzer.java
@@ -17,27 +17,29 @@
*/
package org.owasp.dependencycheck.analyzer;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV2;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV2Data;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV4;
import org.sonatype.ossindex.service.api.componentreport.ComponentReport;
import org.sonatype.ossindex.service.api.componentreport.ComponentReportVulnerability;
import org.sonatype.ossindex.service.api.cvss.Cvss2Severity;
import org.sonatype.ossindex.service.api.cvss.Cvss2Vector;
-import org.sonatype.ossindex.service.api.cvss.Cvss3Severity;
-import org.sonatype.ossindex.service.api.cvss.Cvss3Vector;
import org.sonatype.ossindex.service.api.cvss.CvssVector;
import org.sonatype.ossindex.service.api.cvss.CvssVectorFactory;
import org.sonatype.ossindex.service.client.OssindexClient;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.ossindex.OssindexClientFactory;
-import org.owasp.dependencycheck.dependency.CvssV2;
-import org.owasp.dependencycheck.dependency.CvssV3;
+
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.dependency.VulnerableSoftwareBuilder;
import org.owasp.dependencycheck.dependency.naming.Identifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.Settings.KEYS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.springett.parsers.cpe.exceptions.CpeValidationException;
@@ -54,8 +56,11 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.net.SocketTimeoutException;
+
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
+import org.owasp.dependencycheck.utils.CvssUtil;
import org.sonatype.goodies.packageurl.InvalidException;
import org.sonatype.ossindex.service.client.transport.Transport.TransportException;
@@ -124,6 +129,17 @@ protected void closeAnalyzer() throws Exception {
}
}
+ @Override
+ protected void prepareAnalyzer(Engine engine) throws InitializationException {
+ synchronized (FETCH_MUTIX) {
+ if (StringUtils.isEmpty(getSettings().getString(KEYS.ANALYZER_OSSINDEX_USER, StringUtils.EMPTY)) ||
+ StringUtils.isEmpty(getSettings().getString(KEYS.ANALYZER_OSSINDEX_PASSWORD, StringUtils.EMPTY))) {
+ LOG.warn("Disabling OSS Index analyzer due to missing user/password credentials. Authentication is now required: https://ossindex.sonatype.org/doc/auth-required");
+ setEnabled(false);
+ }
+ }
+ }
+
@Override
protected void analyzeDependency(final Dependency dependency, final Engine engine) throws AnalysisException {
// batch request component-reports for all dependencies
@@ -132,31 +148,45 @@ protected void analyzeDependency(final Dependency dependency, final Engine engin
try {
requestDelay();
reports = requestReports(engine.getDependencies());
- } catch (TransportException ex) {
+ } catch (SocketTimeoutException e) {
+ final boolean warnOnly = getSettings().getBoolean(Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, false);
+ this.setEnabled(false);
+ if (warnOnly) {
+ LOG.warn("OSS Index socket timeout, disabling the analyzer", e);
+ } else {
+ LOG.debug("OSS Index socket timeout", e);
+ throw new AnalysisException("Failed to establish socket to OSS Index", e);
+ }
+ } catch (Exception ex) {
final String message = ex.getMessage();
final boolean warnOnly = getSettings().getBoolean(Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, false);
this.setEnabled(false);
- if (StringUtils.endsWith(message, "401")) {
- LOG.error("Invalid credentials for the OSS Index, disabling the analyzer");
- throw new AnalysisException("Invalid credentials provided for OSS Index", ex);
- } else if (StringUtils.endsWith(message, "403")) {
- LOG.error("OSS Index access forbidden, disabling the analyzer");
- throw new AnalysisException("OSS Index access forbidden", ex);
- } else if (StringUtils.endsWith(message, "429")) {
+ if (StringUtils.contains(message, "401")) {
+ if (warnOnly) {
+ LOG.warn("Invalid credentials for the OSS Index, disabling the analyzer");
+ } else {
+ LOG.error("Invalid credentials for the OSS Index, disabling the analyzer");
+ throw new AnalysisException("Invalid credentials provided for OSS Index", ex);
+ }
+ } else if (StringUtils.contains(message, "403")) {
+ if (warnOnly) {
+ LOG.warn("OSS Index access forbidden, disabling the analyzer");
+ } else {
+ LOG.error("OSS Index access forbidden, disabling the analyzer");
+ throw new AnalysisException("OSS Index access forbidden", ex);
+ }
+ } else if (StringUtils.contains(message, "429")) {
if (warnOnly) {
LOG.warn("OSS Index rate limit exceeded, disabling the analyzer", ex);
} else {
throw new AnalysisException("OSS Index rate limit exceeded, disabling the analyzer", ex);
}
} else if (warnOnly) {
- LOG.warn("Error requesting component reports, disabling the analyzer", ex);
+ LOG.warn("Error requesting component reports, disabling the analyzer. " + ex.getMessage(), ex);
} else {
LOG.debug("Error requesting component reports, disabling the analyzer", ex);
- throw new AnalysisException("Failed to request component-reports", ex);
+ throw new AnalysisException("Failed to request component-reports. " + ex.getMessage(), ex);
}
- } catch (Exception e) {
- LOG.debug("Error requesting component reports", e);
- throw new AnalysisException("Failed to request component-reports", e);
}
}
@@ -260,7 +290,7 @@ void enrich(final Dependency dependency) {
.orElse(null);
if (existing != null) {
//TODO - can we enhance anything other than the references?
- existing.getReferences().addAll(v.getReferences());
+ existing.addReferences(v.getReferences());
} else {
dependency.addVulnerability(v);
}
@@ -307,34 +337,63 @@ private Vulnerability transform(final ComponentReport report, final ComponentRep
result.setDescription(source.getDescription());
result.addCwe(source.getCwe());
- final float cvssScore = source.getCvssScore() != null ? source.getCvssScore() : -1;
+ final double cvssScore = source.getCvssScore() != null ? source.getCvssScore().doubleValue() : -1;
if (source.getCvssVector() != null) {
- if (source.getCvssVector().startsWith("CVSS:3")) {
- result.setCvssV3(new CvssV3(source.getCvssVector(), cvssScore));
+ if (source.getCvssVector().startsWith("CVSS:4")) {
+ result.setCvssV4(CvssUtil.vectorToCvssV4("ossindex", CvssV4.Type.PRIMARY, cvssScore, source.getCvssVector()));
+ } else if (source.getCvssVector().startsWith("CVSS:3")) {
+ result.setCvssV3(CvssUtil.vectorToCvssV3(source.getCvssVector(), cvssScore));
} else {
// convert cvss details
final CvssVector cvssVector = CvssVectorFactory.create(source.getCvssVector());
final Map metrics = cvssVector.getMetrics();
if (cvssVector instanceof Cvss2Vector) {
- result.setCvssV2(new CvssV2(
- cvssScore,
- metrics.get(Cvss2Vector.ACCESS_VECTOR),
- metrics.get(Cvss2Vector.ACCESS_COMPLEXITY),
- metrics.get(Cvss2Vector.AUTHENTICATION),
- metrics.get(Cvss2Vector.CONFIDENTIALITY_IMPACT),
- metrics.get(Cvss2Vector.INTEGRITY_IMPACT),
- metrics.get(Cvss2Vector.AVAILABILITY_IMPACT),
- Cvss2Severity.of(cvssScore).name()
- ));
+ String tmp = metrics.get(Cvss2Vector.ACCESS_VECTOR);
+ CvssV2Data.AccessVectorType accessVector = null;
+ if (tmp != null) {
+ accessVector = CvssV2Data.AccessVectorType.fromValue(tmp);
+ }
+ tmp = metrics.get(Cvss2Vector.ACCESS_COMPLEXITY);
+ CvssV2Data.AccessComplexityType accessComplexity = null;
+ if (tmp != null) {
+ accessComplexity = CvssV2Data.AccessComplexityType.fromValue(tmp);
+ }
+ tmp = metrics.get(Cvss2Vector.AUTHENTICATION);
+ CvssV2Data.AuthenticationType authentication = null;
+ if (tmp != null) {
+ authentication = CvssV2Data.AuthenticationType.fromValue(tmp);
+ }
+ tmp = metrics.get(Cvss2Vector.CONFIDENTIALITY_IMPACT);
+ CvssV2Data.CiaType confidentialityImpact = null;
+ if (tmp != null) {
+ confidentialityImpact = CvssV2Data.CiaType.fromValue(tmp);
+ }
+ tmp = metrics.get(Cvss2Vector.INTEGRITY_IMPACT);
+ CvssV2Data.CiaType integrityImpact = null;
+ if (tmp != null) {
+ integrityImpact = CvssV2Data.CiaType.fromValue(tmp);
+ }
+ tmp = metrics.get(Cvss2Vector.AVAILABILITY_IMPACT);
+ CvssV2Data.CiaType availabilityImpact = null;
+ if (tmp != null) {
+ availabilityImpact = CvssV2Data.CiaType.fromValue(tmp);
+ }
+ final String severity = Cvss2Severity.of((float) cvssScore).name().toUpperCase();
+ final CvssV2Data cvssData = new CvssV2Data(CvssV2Data.Version._2_0, source.getCvssVector(), accessVector,
+ accessComplexity, authentication, confidentialityImpact,
+ integrityImpact, availabilityImpact, cvssScore,
+ severity, null, null, null, null, null, null, null, null, null, null);
+ final CvssV2 cvssV2 = new CvssV2(null, null, cvssData, severity, null, null, null, null, null, null, null);
+ result.setCvssV2(cvssV2);
} else {
LOG.warn("Unsupported CVSS vector: {}", cvssVector);
- result.setUnscoredSeverity(Float.toString(cvssScore));
+ result.setUnscoredSeverity(Double.toString(cvssScore));
}
}
} else {
LOG.debug("OSS has no vector for {}", result.getName());
- result.setUnscoredSeverity(Float.toString(cvssScore));
+ result.setUnscoredSeverity(Double.toString(cvssScore));
}
// generate a reference to the vulnerability details on OSS Index
result.addReference(REFERENCE_TYPE, source.getTitle(), source.getReference().toString());
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PEAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PEAnalyzer.java
index d097daa7469..3d8f23c76b3 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PEAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PEAnalyzer.java
@@ -185,6 +185,7 @@ protected void analyzeDependency(final Dependency dependency, final Engine engin
break;
case "InternalName":
dependency.addEvidence(EvidenceType.PRODUCT, "PE Header", "InternalName", value, Confidence.MEDIUM);
+ dependency.addEvidence(EvidenceType.VENDOR, "PE Header", "InternalName", value, Confidence.LOW);
determineDependencyName(dependency, value);
break;
case "LegalCopyright":
@@ -201,6 +202,7 @@ protected void analyzeDependency(final Dependency dependency, final Engine engin
break;
case "ProductName":
dependency.addEvidence(EvidenceType.PRODUCT, "PE Header", "ProductName", value, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, "PE Header", "ProductName", value, Confidence.MEDIUM);
determineDependencyName(dependency, value);
break;
default:
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PerlCpanfileAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PerlCpanfileAnalyzer.java
index c2725fc9b64..954e300fa89 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PerlCpanfileAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PerlCpanfileAnalyzer.java
@@ -20,36 +20,35 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
+import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.Identifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
+import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import javax.annotation.concurrent.ThreadSafe;
-import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
-import org.owasp.dependencycheck.dependency.Confidence;
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
-import org.owasp.dependencycheck.exception.InitializationException;
-import org.owasp.dependencycheck.utils.Checksum;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.nio.charset.Charset;
-
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import static java.util.stream.Collectors.toCollection;
-import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
-import org.owasp.dependencycheck.dependency.naming.Identifier;
/**
*
@@ -127,7 +126,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
private String tryReadFile(File file) throws AnalysisException {
try {
- return FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
+ return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java
index 34285b80a08..0be4239329f 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PinnedMavenInstallAnalyzer.java
@@ -19,11 +19,14 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
+import java.util.Map;
+import java.util.stream.Collectors;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -118,26 +121,47 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
}
final DependencyTree tree;
+ List deps;
try {
- final InstallFile installFile = INSTALL_FILE_READER.readValue(dependencyFile);
- tree = installFile.getDependencyTree();
- } catch (IOException e) {
- return;
- }
+ final JsonNode jsonNode = MAPPER.readTree(dependencyFile);
+ final JsonNode v2Version = jsonNode.path("version");
+ final JsonNode v010Version = jsonNode.path("dependency_tree").path("version");
+
+ if (v2Version.isTextual()) {
+ final InstallFileV2 installFile = INSTALL_FILE_V2_READER.readValue(dependencyFile);
+ if (!Objects.equals(installFile.getAutogeneratedSentinel(), "THERE_IS_NO_DATA_ONLY_ZUUL")) {
+ return;
+ }
+ if (!Objects.equals(installFile.getVersion(), "2")) {
+ LOGGER.warn("Unsupported pinned maven_install.json version {}. Continuing optimistically.", installFile.getVersion());
+ }
+ deps = installFile.getArtifacts().entrySet().stream().map(entry -> new MavenDependency(
+ entry.getKey() + ":" + entry.getValue().getVersion()
+ )).collect(Collectors.toList());
+ } else if (v010Version.isTextual()) {
+ final InstallFile installFile = INSTALL_FILE_READER.readValue(dependencyFile);
+ tree = installFile.getDependencyTree();
+ if (tree == null) {
+ return;
+ } else if (!Objects.equals(tree.getAutogeneratedSentinel(), "THERE_IS_NO_DATA_ONLY_ZUUL")) {
+ return;
+ }
+ if (!Objects.equals(tree.getVersion(), "0.1.0")) {
+ LOGGER.warn("Unsupported pinned maven_install.json version {}. Continuing optimistically.", tree.getVersion());
+ }
+ deps = tree.getDependencies();
+ } else {
+ LOGGER.warn("No pinned maven_install.json version found. Cannot Parse");
+ return;
+ }
- if (tree == null) {
- return;
- } else if (!Objects.equals(tree.getAutogeneratedSentinel(), "THERE_IS_NO_DATA_ONLY_ZUUL")) {
+ } catch (IOException e) {
+ System.out.println("e");
return;
}
engine.removeDependency(dependency);
- if (!Objects.equals(tree.getVersion(), "0.1.0")) {
- LOGGER.warn("Unsupported pinned maven_install.json version {}. Continuing optimistically.", tree.getVersion());
- }
-
- List deps = tree.getDependencies();
if (deps == null) {
deps = Collections.emptyList();
}
@@ -183,6 +207,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
d.setEcosystem(Ecosystem.JAVA);
d.addEvidence(EvidenceType.VENDOR, "project", "groupid", group, Confidence.HIGHEST);
d.addEvidence(EvidenceType.PRODUCT, "project", "artifactid", artifact, Confidence.HIGHEST);
+ d.addEvidence(EvidenceType.VENDOR, "project", "artifactid", artifact, Confidence.HIGH);
d.addEvidence(EvidenceType.VERSION, "project", "version", version, Confidence.HIGHEST);
d.setName(String.format("%s:%s", group, artifact));
d.setFilePath(String.format("%s>>%s", dependency.getActualFile(), dep.getCoord()));
@@ -301,6 +326,12 @@ public String getVersion() {
*/
private static class MavenDependency {
+ MavenDependency(String coord) {
+ this.coord = coord;
+ }
+
+ MavenDependency() {
+ }
/**
* The standard Maven coordinate string
* {@code group:artifact[:optional classifier][:optional packaging]:version}.
@@ -322,10 +353,106 @@ public String getCoord() {
* A reusable reader for {@link InstallFile}.
*/
private static final ObjectReader INSTALL_FILE_READER;
+ /**
+ * A reusable reader for {@link InstallFileV2}.
+ */
+ private static final ObjectReader INSTALL_FILE_V2_READER;
+ /**
+ * A reusable object mapper.
+ */
+ private static final ObjectMapper MAPPER;
static {
- final ObjectMapper mapper = new ObjectMapper();
- mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
- INSTALL_FILE_READER = mapper.readerFor(InstallFile.class);
+ MAPPER = new ObjectMapper();
+ MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ INSTALL_FILE_READER = MAPPER.readerFor(InstallFile.class);
+ INSTALL_FILE_V2_READER = MAPPER.readerFor(InstallFileV2.class);
}
+
+ /**
+ * Represents the entire pinned Maven dependency set in an install.json
+ * file.
+ *
+ *
+ * At the time of writing, the latest version is 2, and the dependencies are
+ * stored in {@code .artifacts}.
+ *
+ *
+ * The top-level keys we care about are {@code .artifacts}.
+ * {@code .version}.
+ */
+ private static class InstallFileV2 {
+
+ /**
+ * The file format version.
+ */
+ @JsonProperty("version")
+ private String version;
+
+ /**
+ * A list of Maven dependencies made available. Note that this map is
+ * transitively closed and pinned to a specific version of each
+ * artifact.
+ *
+ * The key is the Maven coordinate string, less the version
+ * {@code group:artifact[:optional classifier][:optional packaging]}.
+ *
+ * The value contains the version of the artifact.
+ */
+ @JsonProperty("artifacts")
+ private Map artifacts;
+
+ /**
+ * A sentinel value placed in the file to indicate that it is an
+ * auto-generated pinned maven install file.
+ */
+ @JsonProperty("__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY")
+ private String autogeneratedSentinel;
+
+ /**
+ * Returns artifacts.
+ *
+ * @return artifacts
+ */
+ public Map getArtifacts() {
+ return artifacts;
+ }
+
+ /**
+ * Returns version.
+ *
+ * @return version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Returns autogeneratedSentinel.
+ *
+ * @return autogeneratedSentinel
+ */
+ public String getAutogeneratedSentinel() {
+ return autogeneratedSentinel;
+ }
+ }
+
+ private static class Artifactv2 {
+
+ /**
+ * The version of the artifact.
+ */
+ @JsonProperty("version")
+ private String version;
+
+ /**
+ * Returns the value of version.
+ *
+ * @return the value of version
+ */
+ public String getVersion() {
+ return version;
+ }
+ }
+
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipAnalyzer.java
index 90ef79c6491..e4ceb68bf25 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipAnalyzer.java
@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
@@ -25,23 +24,25 @@
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
-import org.owasp.dependencycheck.utils.FileFilterBuilder;
-import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Checksum;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.stream.Collectors;
/**
* Used to analyze pip dependency files named requirements.txt.
@@ -74,7 +75,7 @@ public class PipAnalyzer extends AbstractFileTypeAnalyzer {
/**
* o * Matches AC_INIT variables in the output configure script.
*/
- private static final Pattern PACKAGE_VERSION = Pattern.compile("^([^#].*?)(?:[=>]=([\\.\\*0-9]+?))?$", Pattern.MULTILINE);
+ private static final Pattern PACKAGE_VERSION = Pattern.compile("^([^#].*?)(?:[=~>]=([\\.\\*0-9]+?))?$", Pattern.MULTILINE);
/**
* The file filter used to determine which files this analyzer supports.
@@ -174,7 +175,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
}
/**
- * Retrieves the contents of a given file.
+ * Retrieves the contents of a given file without blank lines.
*
* @param actualFile the file to read
* @return the contents of the file
@@ -182,7 +183,9 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
*/
private String getFileContents(final File actualFile) throws AnalysisException {
try {
- return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ return Files.lines(actualFile.toPath(), Charset.defaultCharset())
+ .filter(line -> !line.trim().isEmpty())
+ .collect(Collectors.joining("\n"));
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
index 76905edf0bb..bb5c66fc75e 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfileAnalyzer.java
@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
@@ -25,23 +24,24 @@
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
-import org.owasp.dependencycheck.utils.FileFilterBuilder;
-import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Checksum;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Used to analyze dependencies defined in Pipfile. This analyzer works in
@@ -81,7 +81,7 @@ public class PipfileAnalyzer extends AbstractFileTypeAnalyzer {
/**
* o * Matches AC_INIT variables in the output configure script.
*/
- private static final Pattern PACKAGE_VERSION = Pattern.compile("^([^#].*?) = \"(?:[=>]=([\\.\\*0-9]+?))?\"$", Pattern.MULTILINE);
+ private static final Pattern PACKAGE_VERSION = Pattern.compile("^([^#].*?) = \"(?:[=~>]=([\\.\\*0-9]+?))?\"$", Pattern.MULTILINE);
/**
* The file filter used to determine which files this analyzer supports.
@@ -192,7 +192,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
*/
private String getFileContents(final File actualFile) throws AnalysisException {
try {
- return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ return new String(Files.readAllBytes(actualFile.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java
index 525cdcfb6fa..d2a3f8f4719 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PipfilelockAnalyzer.java
@@ -17,39 +17,38 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import java.io.BufferedInputStream;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
-import org.owasp.dependencycheck.utils.FileFilterBuilder;
-import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Checksum;
+import org.owasp.dependencycheck.utils.FileFilterBuilder;
+import org.owasp.dependencycheck.utils.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.Set;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Used to analyze dependencies defined in Pipfile.lock. This analyzer works in
@@ -199,7 +198,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
*/
private String getFileContents(final File actualFile) throws AnalysisException {
try {
- return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
+ return new String(Files.readAllBytes(actualFile.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
index ef2a9c7ba79..74202cdc85c 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PnpmAuditAnalyzer.java
@@ -17,7 +17,8 @@
*/
package org.owasp.dependencycheck.analyzer;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
@@ -42,10 +43,9 @@
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.collections4.MultiValuedMap;
-import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
@ThreadSafe
public class PnpmAuditAnalyzer extends AbstractNpmAnalyzer {
@@ -219,7 +219,7 @@ private JSONObject fetchPnpmAuditJson(Dependency dependency, boolean skipDevDepe
if (!StringUtils.isBlank(errOutput)) {
LOGGER.error("Process error output: {}", errOutput);
}
- String verboseJson = FileUtils.readFileToString(tmpFile, StandardCharsets.UTF_8);
+ String verboseJson = new String(Files.readAllBytes(tmpFile.toPath()), StandardCharsets.UTF_8);
// Workaround implicit creation of .pnpm-debug.log, see https://github.com/pnpm/pnpm/issues/3832
// affects usage of docker container to analyze mounted directories without privileges
if (verboseJson.contains("EACCES: permission denied, open 'node_modules/.pnpm-debug.log'")) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java
index 0d29b5f8875..87be9cda21a 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PoetryAnalyzer.java
@@ -12,8 +12,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
- * Copyright (c) 2019 Nima Yahyazadeh. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
@@ -36,6 +34,8 @@
import com.moandjiezana.toml.Toml;
import java.io.File;
+import java.util.Optional;
+
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
@@ -147,14 +147,24 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
//do not report on the build file itself
engine.removeDependency(dependency);
+ final Optional potentiallyParsedToml = parseDependencyFile(dependency);
+ if (potentiallyParsedToml.isEmpty()) {
+ LOGGER.warn("toml file skipped: {} could not be parsed", dependency.getActualFilePath());
+ return;
+ }
+ final Toml result = potentiallyParsedToml.get();
if (PYPROJECT_TOML.equals(dependency.getActualFile().getName())) {
+ if (result.getTable("tool.poetry") == null) {
+ LOGGER.debug("skipping {} as it does not contain `tool.poetry`", dependency.getDisplayFileName());
+ return;
+ }
+
final File parentPath = dependency.getActualFile().getParentFile();
ensureLock(parentPath);
//exit as we can't analyze pyproject.toml - insufficient version information
return;
}
- final Toml result = new Toml().read(dependency.getActualFile());
final List projectsLocks = result.getTables("package");
if (projectsLocks == null) {
return;
@@ -195,6 +205,30 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
});
}
+ private Optional parseDependencyFile(Dependency dependency) {
+ try {
+ final Toml toml = new Toml().read(dependency.getActualFile());
+ return Optional.of(toml);
+ } catch (RuntimeException e) {
+ final Optional unparsableFileErrorMessage = Optional.ofNullable(e.getCause())
+ .filter(c -> c instanceof IllegalStateException)
+ .map(Throwable::getMessage)
+ .filter(PoetryAnalyzer::isInvalidKeyErrorMessage);
+
+ if (unparsableFileErrorMessage.isPresent()) {
+ final String message = String.format("Invalid toml file, cannot parse '%s'", dependency.getActualFile());
+ LOGGER.debug(message, e);
+ return Optional.empty();
+ }
+
+ throw e;
+ }
+ }
+
+ private static boolean isInvalidKeyErrorMessage(String m) {
+ return m.startsWith("Invalid key");
+ }
+
private void ensureLock(File parent) throws AnalysisException {
final File lock = new File(parent, POETRY_LOCK);
final File requirements = new File(parent, "requirements.txt");
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java
index ecd7c727c85..8396fb8f6e2 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java
@@ -20,31 +20,31 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
+import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.EvidenceType;
+import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
+import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
-import org.owasp.dependencycheck.dependency.EvidenceType;
-import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
-import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
-import org.owasp.dependencycheck.exception.InitializationException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Used to analyze a Python package, and collect information that can be used to
@@ -211,6 +211,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine)
//"The __init__.py files are required to make Python treat the directories as containing packages"
//see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html;
dependency.addEvidence(EvidenceType.PRODUCT, file.getName(), "PackageName", parentName, Confidence.HIGHEST);
+ dependency.addEvidence(EvidenceType.VENDOR, file.getName(), "PackageName", parentName, Confidence.MEDIUM);
dependency.setName(parentName);
final File[] fileList = parent.listFiles(PY_FILTER);
@@ -237,13 +238,13 @@ private void analyzeFileContents(Dependency dependency, File file)
throws AnalysisException {
final String contents;
try {
- contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
+ contents = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
if (!contents.isEmpty()) {
final String source = file.getName();
- gatherEvidence(dependency, EvidenceType.VERSION, VERSION_PATTERN, contents,
+ gatherEvidence(dependency, EvidenceType.VERSION, VERSION_PATTERN, contents,
source, "SourceVersion", Confidence.MEDIUM);
addSummaryInfo(dependency, SUMMARY_PATTERN, 4, contents,
source, "summary");
@@ -292,7 +293,7 @@ private void analyzeFileContents(Dependency dependency, File file)
* @param key the key name to use when recording the evidence
*/
private void addSummaryInfo(Dependency dependency, Pattern pattern,
- int group, String contents, String source, String key) {
+ int group, String contents, String source, String key) {
final Matcher matcher = pattern.matcher(contents);
final boolean found = matcher.find();
if (found) {
@@ -312,7 +313,7 @@ private void addSummaryInfo(Dependency dependency, Pattern pattern,
* @param contents the home page URL
*/
private void gatherHomePageEvidence(Dependency dependency, EvidenceType type, Pattern pattern,
- String source, String name, String contents) {
+ String source, String name, String contents) {
final Matcher matcher = pattern.matcher(contents);
if (matcher.find()) {
final String url = matcher.group(4);
@@ -335,7 +336,7 @@ private void gatherHomePageEvidence(Dependency dependency, EvidenceType type, Pa
* @param confidence in evidence
*/
private void gatherEvidence(Dependency dependency, EvidenceType type, Pattern pattern, String contents,
- String source, String name, Confidence confidence) {
+ String source, String name, Confidence confidence) {
final Matcher matcher = pattern.matcher(contents);
final boolean found = matcher.find();
if (found) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/RetireJsAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/RetireJsAnalyzer.java
index 7961f8f77c5..0c329a9e729 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/RetireJsAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/RetireJsAnalyzer.java
@@ -182,7 +182,7 @@ public void initialize(Settings settings) {
protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
// RetireJS outputs a bunch of repeated output like the following for
// vulnerable dependencies, with little context:
- //
+ //
// INFO: Vulnerability found: jquery below 1.6.3
//
// This logging is suppressed because it isn't particularly useful, and
@@ -216,7 +216,7 @@ protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationExcep
try {
ds.update(engine);
} catch (UpdateException ex) {
- throw new InitializationException("Unable to initialize the Retire JS respository", ex);
+ throw new InitializationException("Unable to initialize the Retire JS repository", ex);
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java
index 002eb6dc283..ab5c54a3e8d 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java
@@ -20,16 +20,6 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -44,6 +34,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* Used to analyze Ruby Gem specifications and collect information that can be
* used to determine the associated CPE. Regular expressions are used to parse
@@ -143,7 +143,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
String contents;
try {
- contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
+ contents = new String(Files.readAllBytes(dependency.getActualFile().toPath()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -265,7 +265,7 @@ private String addEvidenceFromVersionFile(Dependency dependency, EvidenceType ty
}
for (File f : matchingFiles) {
try {
- final List lines = FileUtils.readLines(f, Charset.defaultCharset());
+ final List lines = Files.readAllLines(f.toPath(), StandardCharsets.UTF_8);
if (lines.size() == 1) { //TODO other checking?
final String value = lines.get(0).trim();
if (version == null || !version.equals(value)) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java
index 805a32a8c49..7e9baaeef61 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java
@@ -20,15 +20,6 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.annotation.concurrent.ThreadSafe;
-
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -42,6 +33,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* This analyzer is used to analyze the SWIFT Package Manager
* (https://swift.org/package-manager/). It collects information about a package
@@ -158,7 +158,7 @@ private void analyzeSpmFileDependency(Dependency dependency)
throws AnalysisException, IOException {
dependency.setEcosystem(DEPENDENCY_ECOSYSTEM);
- final String contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
+ final String contents = new String(Files.readAllBytes(dependency.getActualFile().toPath()), StandardCharsets.UTF_8);
final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
if (matcher.find()) {
@@ -220,7 +220,7 @@ private void analyzeSpmFileDependency(Dependency dependency)
* @return the string that was added as evidence
*/
private String addStringEvidence(Dependency dependency, EvidenceType type,
- String packageDescription, String field, String fieldPattern, Confidence confidence) {
+ String packageDescription, String field, String fieldPattern, Confidence confidence) {
String value = "";
final Matcher matcher = Pattern.compile(
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageResolvedAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageResolvedAnalyzer.java
index 575aaa597ce..ccd10ec48d1 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageResolvedAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageResolvedAnalyzer.java
@@ -20,16 +20,6 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import com.github.packageurl.PackageURLBuilder;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-
-import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
@@ -44,6 +34,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
/**
* This analyzer is used to analyze the SWIFT Package Resolved
* (https://swift.org/package-manager/). It collects information about a package
@@ -155,8 +155,8 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
private void analyzeSpmResolvedDependencies(Dependency spmResolved, Engine engine)
throws AnalysisException, IOException {
- try (InputStream in = FileUtils.openInputStream(spmResolved.getActualFile());
- JsonReader resolved = Json.createReader(in)) {
+ try (InputStream in = Files.newInputStream(spmResolved.getActualFile().toPath());
+ JsonReader resolved = Json.createReader(in)) {
final JsonObject file = resolved.readObject();
final int fileVersion = file.getInt("version");
@@ -165,7 +165,8 @@ private void analyzeSpmResolvedDependencies(Dependency spmResolved, Engine engin
analyzeSpmResolvedDependenciesV1(spmResolved, engine, file);
break;
case 2:
- analyzeSpmResolvedDependenciesV2(spmResolved, engine, file);
+ case 3:
+ analyzeSpmResolvedDependenciesV2And3(spmResolved, engine, file);
break;
default:
return;
@@ -209,14 +210,14 @@ private void analyzeSpmResolvedDependenciesV1(Dependency spmResolved, Engine eng
}
/**
- * Analyzes the version 2 of the Package.resolved file to extract evidence
+ * Analyzes the versions 2 and 3 of the Package.resolved file to extract evidence
* for the dependency.
*
* @param spmResolved the dependency to analyze
* @param engine the analysis engine
* @param resolved the json object of the file to analyze
*/
- private void analyzeSpmResolvedDependenciesV2(Dependency spmResolved, Engine engine, JsonObject resolved) {
+ private void analyzeSpmResolvedDependenciesV2And3(Dependency spmResolved, Engine engine, JsonObject resolved) {
final JsonArray pins = resolved.getJsonArray("pins");
if (pins == null) {
return;
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/UnusedSuppressionRuleAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/UnusedSuppressionRuleAnalyzer.java
index 4c95fdbb78d..9f5188e06ad 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/UnusedSuppressionRuleAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/UnusedSuppressionRuleAnalyzer.java
@@ -34,6 +34,11 @@
*/
public class UnusedSuppressionRuleAnalyzer extends AbstractAnalyzer {
+ /**
+ * Exception message.
+ */
+ protected static final String EXCEPTION_MSG = "There are %d unused suppression rule(s): check logs.";
+
/**
* The Logger for use throughout the class.
*/
@@ -43,27 +48,54 @@ public class UnusedSuppressionRuleAnalyzer extends AbstractAnalyzer {
* been reported.
*/
private boolean reported = false;
+ /**
+ * A flag indicating whether build should fail on unused suppression rule
+ */
+ private boolean shouldFailForUnusedSuppressionRule = false;
+ /**
+ * unused suppression rule count
+ */
+ private int unusedSuppressionRuleCount = 0;
+
+ @Override
+ public synchronized void initialize(Settings settings) {
+ super.initialize(settings);
+ if (settings.getBoolean(Settings.KEYS.FAIL_ON_UNUSED_SUPPRESSION_RULE, false)) {
+ this.shouldFailForUnusedSuppressionRule = true;
+ }
+ }
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
if (!reported) {
- logUnusedRules(engine);
+ checkUnusedRules(engine);
reported = true;
+ if (unusedSuppressionRuleCount > 0 && failsForUnusedSuppressionRule()) {
+ final String message = String.format(EXCEPTION_MSG, unusedSuppressionRuleCount);
+ LOGGER.error(message);
+ throw new AnalysisException(message);
+ }
}
}
/**
- * Logs unused suppression RULES.
+ * check unused suppression RULES.
*
* @param engine a reference to the ODC engine
*/
- private void logUnusedRules(Engine engine) {
+ protected void checkUnusedRules(Engine engine) {
if (engine.hasObject(SUPPRESSION_OBJECT_KEY)) {
@SuppressWarnings("unchecked")
final List rules = (List) engine.getObject(SUPPRESSION_OBJECT_KEY);
rules.forEach((rule) -> {
if (!rule.isMatched() && !rule.isBase()) {
- LOGGER.info("Suppression Rule had zero matches: {}", rule.toString());
+ final String message = String.format("Suppression Rule had zero matches: %s", rule);
+ if (failsForUnusedSuppressionRule()) {
+ LOGGER.error(message);
+ } else {
+ LOGGER.info(message);
+ }
+ increaseUnusedSuppressionRuleCount();
}
});
}
@@ -89,4 +121,25 @@ public AnalysisPhase getAnalysisPhase() {
public boolean supportsParallelProcessing() {
return false;
}
+
+ /**
+ * increases the count of unused suppression rules.
+ */
+ public void increaseUnusedSuppressionRuleCount() {
+ unusedSuppressionRuleCount++;
+ }
+
+ /**
+ * @return the count of unused suppression rules.
+ */
+ public int getUnusedSuppressionRuleCount() {
+ return unusedSuppressionRuleCount;
+ }
+
+ /**
+ * @return whether the analyzer will fail for a unused suppression rule.
+ */
+ public boolean failsForUnusedSuppressionRule() {
+ return shouldFailForUnusedSuppressionRule;
+ }
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java
index 584b9b2a163..1cd1ad432f2 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java
@@ -86,7 +86,7 @@ public class VersionFilterAnalyzer extends AbstractAnalyzer {
/**
* The phase that this analyzer is intended to run in.
*/
- private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION;
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION3;
//
//
@@ -136,7 +136,7 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
final Set remove;
if (dependency.getVersion() != null) {
remove = dependency.getEvidence(EvidenceType.VERSION).stream()
- .filter(e -> !dependency.getVersion().equals(e.getValue()))
+ .filter(e -> !e.isFromHint() && !dependency.getVersion().equals(e.getValue()))
.collect(Collectors.toSet());
} else {
remove = new HashSet<>();
@@ -165,7 +165,8 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
LOGGER.debug("filtering evidence from {}", dependency.getFileName());
for (Evidence e : dependency.getEvidence(EvidenceType.VERSION)) {
- if (!(pomMatch && VERSION.equals(e.getName())
+ if (!e.isFromHint()
+ && !(pomMatch && VERSION.equals(e.getName())
&& (NEXUS.equals(e.getSource()) || CENTRAL.equals(e.getSource()) || POM.equals(e.getSource())))
&& !(fileMatch && VERSION.equals(e.getName()) && FILE.equals(e.getSource()))
&& !(manifestMatch && MANIFEST.equals(e.getSource()) && IMPLEMENTATION_VERSION.equals(e.getName()))) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
index 2e52ad8bc43..25c7f0b58e6 100644
--- a/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
+++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/YarnAuditAnalyzer.java
@@ -17,25 +17,12 @@
*/
package org.owasp.dependencycheck.analyzer;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
-
-import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.SearchException;
@@ -48,18 +35,41 @@
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.URLConnectionFailureException;
import org.owasp.dependencycheck.utils.processing.ProcessReader;
+import org.semver4j.Semver;
+import org.semver4j.SemverException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.springett.parsers.cpe.exceptions.CpeValidationException;
+import jakarta.json.Json;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
@ThreadSafe
public class YarnAuditAnalyzer extends AbstractNpmAnalyzer {
/**
- * The logger.
+ * The Logger for use throughout the class.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(YarnAuditAnalyzer.class);
+ /**
+ * The major version of the Yarn Classic CLI.
+ */
+ private static final int YARN_CLASSIC_MAJOR_VERSION = 1;
+
/**
* The file name to scan.
*/
@@ -83,34 +93,6 @@ public class YarnAuditAnalyzer extends AbstractNpmAnalyzer {
*/
private String yarnPath;
- /**
- * Analyzes the yarn lock file to determine vulnerable dependencies. Uses
- * yarn audit --offline to generate the payload to be sent to the NPM API.
- *
- * @param dependency the yarn lock file
- * @param engine the analysis engine
- * @throws AnalysisException thrown if there is an error analyzing the file
- */
- @Override
- protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
- if (dependency.getDisplayFileName().equals(dependency.getFileName())) {
- engine.removeDependency(dependency);
- }
- final File packageLock = dependency.getActualFile();
- if (!packageLock.isFile() || packageLock.length() == 0 || !shouldProcess(packageLock)) {
- return;
- }
- final File packageJson = new File(packageLock.getParentFile(), "package.json");
- final List advisories;
- final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
- advisories = analyzePackage(packageLock, packageJson, dependency, dependencyMap);
- try {
- processResults(advisories, engine, dependency, dependencyMap);
- } catch (CpeValidationException ex) {
- throw new UnexpectedAnalysisException(ex);
- }
- }
-
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_YARN_AUDIT_ENABLED;
@@ -131,6 +113,49 @@ public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.FINDING_ANALYSIS;
}
+ /**
+ * Extracts the major version from a version string.
+ *
+ * @param dependency the dependency to extract the yarn version from
+ * @return the major version (e.g., `4` from "4.2.1")
+ */
+ private int getYarnMajorVersion(Dependency dependency) {
+ final var yarnVersion = getYarnVersion(dependency);
+ try {
+ final var semver = Semver.coerce(yarnVersion);
+ return semver.getMajor();
+ } catch (SemverException e) {
+ throw new IllegalStateException("Invalid version string format", e);
+ }
+ }
+
+ private String getYarnVersion(Dependency dependency) {
+ final List args = new ArrayList<>();
+ args.add(getYarn());
+ args.add("--version");
+ final ProcessBuilder builder = new ProcessBuilder(args);
+ builder.directory(getDependencyDirectory(dependency));
+ LOGGER.debug("Launching: {}", args);
+ try {
+ final Process process = builder.start();
+ try (ProcessReader processReader = new ProcessReader(process)) {
+ processReader.readAll();
+ final int exitValue = process.waitFor();
+ if (exitValue != 0) {
+ throw new IllegalStateException("Unable to determine yarn version, unexpected response.");
+ }
+ final var yarnVersion = processReader.getOutput();
+ if (StringUtils.isBlank(yarnVersion)) {
+ throw new IllegalStateException("Unable to determine yarn version, blank output.");
+ }
+ return yarnVersion;
+ }
+ } catch (Exception ex) {
+ throw new IllegalStateException("Unable to determine yarn version.", ex);
+ }
+ }
+
+
/**
* Initializes the analyzer once before any analysis is performed.
*
@@ -163,12 +188,14 @@ protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationExcep
case yarnExecutableNotFoundExitValue:
default:
this.setEnabled(false);
- LOGGER.warn("The {} has been disabled. Yarn executable was not found.", getName());
+ LOGGER.warn("The {} has been disabled after receiving exit value {}. Yarn executable was not " +
+ "found or received a non-zero exit value.", getName(), exitValue);
}
}
} catch (Exception ex) {
this.setEnabled(false);
- LOGGER.warn("The {} has been disabled. Yarn executable was not found.", getName());
+ LOGGER.warn("The {} has been disabled after receiving an exception. This can occur when Yarn executable " +
+ "is not found.", getName());
throw new InitializationException("Unable to read yarn audit output.", ex);
}
}
@@ -200,30 +227,15 @@ private String getYarn() {
return value;
}
- private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDependencies) throws AnalysisException {
- final File folder = dependency.getActualFile().getParentFile();
- if (!folder.isDirectory()) {
- throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath()));
- }
+ /**
+ * Workaround 64k limitation of InputStream, redirect stdout to a file that we will read later
+ * instead of reading directly stdout from Process's InputStream which is topped at 64k
+ *
+ * @param builder a reference to the process builder
+ * @return returns the standard out from the process
+ */
+ private String startAndReadStdoutToString(ProcessBuilder builder) throws AnalysisException {
try {
- final List args = new ArrayList<>();
-
- args.add(getYarn());
- args.add("audit");
- //offline audit is not supported - but the audit request is generated in the verbose output
- args.add("--offline");
- if (skipDevDependencies) {
- args.add("--groups");
- args.add("dependencies");
- }
- args.add("--json");
- args.add("--verbose");
- final ProcessBuilder builder = new ProcessBuilder(args);
- builder.directory(folder);
- LOGGER.debug("Launching: {}", args);
- // Workaround 64k limitation of InputStream, redirect stdout to a file that we will read later
- // instead of reading directly stdout from Process's InputStream which is topped at 64k
-
final File tmpFile = getSettings().getTempFile("yarn_audit", "json");
builder.redirectOutput(tmpFile);
final Process process = builder.start();
@@ -235,19 +247,7 @@ private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDepe
LOGGER.debug("Process Error Out: {}", errOutput);
LOGGER.debug("Process Out: {}", processReader.getOutput());
}
- final String verboseJson = FileUtils.readFileToString(tmpFile, StandardCharsets.UTF_8);
- final String auditRequestJson = Arrays.stream(verboseJson.split("\n"))
- .filter(line -> line.contains("Audit Request"))
- .findFirst().get();
- String auditRequest;
- try (JsonReader reader = Json.createReader(IOUtils.toInputStream(auditRequestJson, StandardCharsets.UTF_8))) {
- final JsonObject jsonObject = reader.readObject();
- auditRequest = jsonObject.getString("data");
- auditRequest = auditRequest.substring(15);
- }
- LOGGER.debug("Audit Request: {}", auditRequest);
-
- return Json.createReader(IOUtils.toInputStream(auditRequest, StandardCharsets.UTF_8)).readObject();
+ return new String(Files.readAllBytes(tmpFile.toPath()), StandardCharsets.UTF_8);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new AnalysisException("Yarn audit process was interrupted.", ex);
@@ -257,6 +257,80 @@ private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDepe
}
}
+ /**
+ * Analyzes the yarn lock file to determine vulnerable dependencies. Uses
+ * yarn audit --offline to generate the payload to be sent to the NPM API.
+ *
+ * @param dependency the yarn lock file
+ * @param engine the analysis engine
+ * @throws AnalysisException thrown if there is an error analyzing the file
+ */
+ @Override
+ protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
+ if (dependency.getDisplayFileName().equals(dependency.getFileName())) {
+ engine.removeDependency(dependency);
+ }
+ final File packageLock = dependency.getActualFile();
+ if (!packageLock.isFile() || packageLock.length() == 0 || !shouldProcess(packageLock)) {
+ return;
+ }
+ final File packageJson = new File(packageLock.getParentFile(), "package.json");
+ final List advisories;
+ final MultiValuedMap dependencyMap = new HashSetValuedHashMap<>();
+ final var yarnMajorVersion = getYarnMajorVersion(dependency);
+ if (YARN_CLASSIC_MAJOR_VERSION < yarnMajorVersion) {
+ LOGGER.info("Analyzing using Yarn Berry audit");
+ advisories = analyzePackageWithYarnBerry(dependency);
+ } else {
+ LOGGER.info("Analyzing using Yarn Classic audit");
+ advisories = analyzePackageWithYarnClassic(packageLock, packageJson, dependency, dependencyMap);
+ }
+ try {
+ processResults(advisories, engine, dependency, dependencyMap);
+ } catch (CpeValidationException ex) {
+ throw new UnexpectedAnalysisException(ex);
+ }
+ }
+
+ private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDependencies) throws AnalysisException {
+ final List args = new ArrayList<>();
+ args.add(getYarn());
+ args.add("audit");
+ //offline audit is not supported - but the audit request is generated in the verbose output
+ args.add("--offline");
+ if (skipDevDependencies) {
+ args.add("--groups");
+ args.add("dependencies");
+ }
+ args.add("--json");
+ args.add("--verbose");
+ final ProcessBuilder builder = new ProcessBuilder(args);
+ builder.directory(getDependencyDirectory(dependency));
+ LOGGER.debug("Launching: {}", args);
+
+ final String verboseJson = startAndReadStdoutToString(builder);
+ final String auditRequestJson = Arrays.stream(verboseJson.split("\n"))
+ .filter(line -> line.contains("Audit Request"))
+ .findFirst().get();
+ String auditRequest;
+ try (JsonReader reader = Json.createReader(IOUtils.toInputStream(auditRequestJson, StandardCharsets.UTF_8))) {
+ final JsonObject jsonObject = reader.readObject();
+ auditRequest = jsonObject.getString("data");
+ auditRequest = auditRequest.substring(15);
+ }
+ LOGGER.debug("Audit Request: {}", auditRequest);
+
+ return Json.createReader(IOUtils.toInputStream(auditRequest, StandardCharsets.UTF_8)).readObject();
+ }
+
+ private static File getDependencyDirectory(Dependency dependency) {
+ final File folder = dependency.getActualFile().getParentFile();
+ if (!folder.isDirectory()) {
+ throw new IllegalArgumentException(String.format("%s should have been a directory.", folder.getAbsolutePath()));
+ }
+ return folder;
+ }
+
/**
* Analyzes the package and yarn lock files by extracting dependency
* information, creating a payload to submit to the npm audit API,
@@ -272,17 +346,18 @@ private JsonObject fetchYarnAuditJson(Dependency dependency, boolean skipDevDepe
* @throws AnalysisException thrown when there is an error creating or
* submitting the npm audit API payload
*/
- private List analyzePackage(final File lockFile, final File packageFile,
- Dependency dependency, MultiValuedMap dependencyMap)
+ private List analyzePackageWithYarnClassic(final File lockFile, final File packageFile,
+ Dependency dependency, MultiValuedMap dependencyMap)
throws AnalysisException {
try {
final boolean skipDevDependencies = getSettings().getBoolean(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV, false);
// Retrieves the contents of package-lock.json from the Dependency
final JsonObject lockJson = fetchYarnAuditJson(dependency, skipDevDependencies);
// Retrieves the contents of package-lock.json from the Dependency
- final JsonReader packageReader = Json.createReader(FileUtils.openInputStream(packageFile));
- final JsonObject packageJson = packageReader.readObject();
-
+ final JsonObject packageJson;
+ try (JsonReader packageReader = Json.createReader(Files.newInputStream(packageFile.toPath()))) {
+ packageJson = packageReader.readObject();
+ }
// Modify the payload to meet the NPM Audit API requirements
final JsonObject payload = NpmPayloadBuilder.build(lockJson, packageJson, dependencyMap, skipDevDependencies);
@@ -306,4 +381,106 @@ private List analyzePackage(final File lockFile, final File packageFil
throw ex;
}
}
+
+ private List fetchYarnAdvisories(Dependency dependency, boolean skipDevDependencies) throws AnalysisException {
+ final List args = new ArrayList<>();
+
+ args.add(getYarn());
+ args.add("npm");
+ args.add("audit");
+ if (skipDevDependencies) {
+ args.add("--environment");
+ args.add("production");
+ }
+ args.add("--all");
+ args.add("--recursive");
+ args.add("--json");
+ final ProcessBuilder builder = new ProcessBuilder(args);
+ builder.directory(getDependencyDirectory(dependency));
+
+ final String advisoriesJsons = startAndReadStdoutToString(builder);
+
+ LOGGER.debug("Advisories JSON: {}", advisoriesJsons);
+ final String[] advisoriesJsonArray = Stream.of(advisoriesJsons.split("\n"))
+ .filter(s -> !s.isBlank())
+ .toArray(String[]::new);
+ try {
+ final List advisories = new ArrayList<>();
+ for (String advisoriesJson : advisoriesJsonArray) {
+ advisories.add(new JSONObject(advisoriesJson));
+ }
+
+ return advisories;
+ } catch (JSONException e) {
+ throw new AnalysisException("Failed to parse the response from NPM Audit API "
+ + "(YarnBerryAuditAnalyzer).", e);
+ }
+ }
+
+ /**
+ * Analyzes the package and yarn lock files by calling yarn npm audit and returning the identified advisories.
+ *
+ * @param dependency a reference to the dependency-object for the yarn.lock
+ * @return a list of advisories
+ */
+ private List analyzePackageWithYarnBerry(Dependency dependency) throws AnalysisException {
+ try {
+ final var skipDevDependencies = getSettings().getBoolean(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV, false);
+ final var advisoryJsons = fetchYarnAdvisories(dependency, skipDevDependencies);
+ return parseAdvisoryJsons(advisoryJsons);
+ } catch (JSONException e) {
+ throw new AnalysisException("Failed to parse the response from NPM Audit API "
+ + "(YarnBerryAuditAnalyzer).", e);
+ } catch (SearchException ex) {
+ LOGGER.error("YarnBerryAuditAnalyzer failed on {}", dependency.getActualFilePath());
+ throw ex;
+ }
+ }
+
+ private static List parseAdvisoryJsons(List advisoryJsons) throws JSONException {
+ final List advisories = new ArrayList<>();
+ for (JSONObject advisoryJson : advisoryJsons) {
+ final var advisory = new Advisory();
+ final var object = advisoryJson.getJSONObject("children");
+ final var moduleName = advisoryJson.optString("value", null);
+ final var id = object.getString("ID");
+ final var url = object.optString("URL", null);
+ final var ghsaId = extractGhsaId(url);
+ final var issue = object.optString("Issue", null);
+ final var severity = object.optString("Severity", null);
+ final var vulnerableVersions = object.optString("Vulnerable Versions", null);
+ final var treeVersions = object.optJSONArray("Tree Versions");
+ final var treeVersionsLength = treeVersions == null ? 0 : treeVersions.length();
+ final var versions = new ArrayList();
+ for (int i = 0; i < treeVersionsLength; i++) {
+ versions.add(treeVersions.getString(i));
+ }
+ if (versions.isEmpty()) {
+ versions.add(null);
+ }
+ for (String version : versions) {
+ advisory.setGhsaId(ghsaId);
+ advisory.setTitle(issue);
+ advisory.setOverview("URL:" + url + "ID: " + id);
+ advisory.setSeverity(severity);
+ advisory.setVulnerableVersions(vulnerableVersions);
+ advisory.setModuleName(moduleName);
+ advisory.setVersion(version);
+ advisory.setCwes(new ArrayList<>());
+ advisories.add(advisory);
+ }
+ }
+ return advisories;
+ }
+
+ private static String extractGhsaId(String url) {
+ if (url == null || url.isEmpty()) {
+ return null;
+ }
+ final int lastSlashIndex = url.lastIndexOf('/');
+ if (lastSlashIndex == -1 || lastSlashIndex == url.length() - 1) {
+ return null;
+ }
+ return url.substring(lastSlashIndex + 1);
+ }
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearch.java b/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearch.java
index ef895fc7800..630e8af0d0b 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearch.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearch.java
@@ -19,59 +19,51 @@
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Base64;
import java.util.List;
import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.annotation.concurrent.ThreadSafe;
+import org.apache.hc.core5.http.message.BasicHeader;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Checksum;
-import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.ForbiddenException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.utils.URLConnectionFactory;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
/**
* Class of methods to search Artifactory for hashes and determine Maven GAV
* from there.
*
- * Data classes copied from JFrog's artifactory-client-java project.
+ *
Data classes copied from JFrog's artifactory-client-java project.
*
* @author nhenneaux
*/
@ThreadSafe
-@SuppressWarnings("squid:S2647")
public class ArtifactorySearch {
/**
- * Used for logging.
+ * Required to add all extra information of the found artifact.
+ * Source: https://jfrog.com/help/r/jfrog-rest-apis/property-search
*/
- private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactorySearch.class);
+ @SuppressWarnings("JavadocLinkAsPlainText")
+ public static final String X_RESULT_DETAIL_HEADER = "X-Result-Detail";
/**
- * Pattern to match the path returned by the Artifactory AQL API.
- */
- private static final Pattern PATH_PATTERN = Pattern.compile("^/(?.+)/(?[^/]+)/(?[^/]+)/[^/]+$");
- /**
- * Extracted duplicateArtifactorySearchIT.java comment.
+ * Used for logging.
*/
- private static final String WHILE_ACTUAL_IS = " while actual is ";
+ private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactorySearch.class);
+
/**
* The URL for the Central service.
*/
@@ -80,25 +72,15 @@ public class ArtifactorySearch {
/**
* Whether to use the Proxy when making requests.
*/
- private final boolean useProxy;
+ private final boolean allowUsingProxy;
- /**
- * The configured settings.
- */
- private final Settings settings;
/**
- * Search result reader
- */
- private final ObjectReader objectReader;
-
- /**
- * Creates a NexusSearch for the given repository URL.
+ * Creates a ArtifactorySearch for the given repository URL.
*
* @param settings the configured settings
*/
public ArtifactorySearch(Settings settings) {
- this.settings = settings;
final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_ARTIFACTORY_URL);
@@ -106,20 +88,13 @@ public ArtifactorySearch(Settings settings) {
LOGGER.debug("Artifactory Search URL {}", searchUrl);
if (null != settings.getString(Settings.KEYS.PROXY_SERVER)) {
- boolean useProxySettings = false;
- try {
- useProxySettings = settings.getBoolean(Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY);
- } catch (InvalidSettingException e) {
- LOGGER.error("Settings {} is invalid, only, true/false is valid", Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY, e);
- }
- this.useProxy = useProxySettings;
- LOGGER.debug("Using proxy? {}", useProxy);
+ this.allowUsingProxy = settings.getBoolean(Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY, false);
+ LOGGER.debug("Using proxy configuration? {}", allowUsingProxy);
} else {
- useProxy = false;
- LOGGER.debug("Not using proxy");
+ this.allowUsingProxy = settings.getBoolean(Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY, true);
+ LOGGER.debug("Using default non-legacy proxy configuration");
}
- objectReader = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readerFor(FileImpl.class);
}
/**
@@ -137,50 +112,25 @@ public List search(Dependency dependency) throws IOException {
final String sha1sum = dependency.getSha1sum();
final URL url = buildUrl(sha1sum);
- final HttpURLConnection conn = connect(url);
- final int responseCode = conn.getResponseCode();
- if (responseCode == 200) {
- return processResponse(dependency, conn);
- }
- throw new IOException("Could not connect to Artifactory " + url + " (" + responseCode + "): " + conn.getResponseMessage());
-
- }
-
- /**
- * Makes an connection to the given URL.
- *
- * @param url the URL to connect to
- * @return the HTTP URL Connection
- * @throws IOException thrown if there is an error making the connection
- */
- private HttpURLConnection connect(URL url) throws IOException {
- LOGGER.debug("Searching Artifactory url {}", url);
-
- // Determine if we need to use a proxy. The rules:
- // 1) If the proxy is set, AND the setting is set to true, use the proxy
- // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
- // or proxy is specifically set to false)
- final URLConnectionFactory factory = new URLConnectionFactory(settings);
- final HttpURLConnection conn = factory.createHttpURLConnection(url, useProxy);
- conn.setDoOutput(true);
-
- conn.addRequestProperty("X-Result-Detail", "info");
-
- final String username = settings.getString(Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME);
- final String apiToken = settings.getString(Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN);
- if (username != null && apiToken != null) {
- final String userpassword = username + ":" + apiToken;
- final String encodedAuthorization = Base64.getEncoder().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));
- conn.addRequestProperty("Authorization", "Basic " + encodedAuthorization);
- } else {
- final String bearerToken = settings.getString(Settings.KEYS.ANALYZER_ARTIFACTORY_BEARER_TOKEN);
- if (bearerToken != null) {
- conn.addRequestProperty("Authorization", "Bearer " + bearerToken);
- }
+ final StringBuilder msg = new StringBuilder("Could not connect to Artifactory at")
+ .append(url);
+ try {
+ final BasicHeader artifactoryResultDetail = new BasicHeader(X_RESULT_DETAIL_HEADER, "info");
+ return Downloader.getInstance().fetchAndHandle(
+ url,
+ new ArtifactorySearchResponseHandler(url, dependency),
+ List.of(artifactoryResultDetail),
+ allowUsingProxy
+ );
+ } catch (TooManyRequestsException e) {
+ throw new IOException(msg.append(" (429): Too manu requests").toString(), e);
+ } catch (URISyntaxException e) {
+ throw new IOException(msg.append(" (400): Invalid URL").toString(), e);
+ } catch (ResourceNotFoundException e) {
+ throw new IOException(msg.append(" (404): Not found").toString(), e);
+ } catch (ForbiddenException e) {
+ throw new IOException(msg.append(" (403): Forbidden").toString(), e);
}
-
- conn.connect();
- return conn;
}
/**
@@ -196,99 +146,6 @@ private URL buildUrl(String sha1sum) throws MalformedURLException {
return new URL(rootURL + "/api/search/checksum?sha1=" + sha1sum);
}
- /**
- * Process the Artifactory response.
- *
- * @param dependency the dependency
- * @param conn the HTTP URL Connection
- * @return a list of the Maven Artifact information
- * @throws IOException thrown if there is an I/O error
- */
- protected List processResponse(Dependency dependency, HttpURLConnection conn) throws IOException {
- final List result = new ArrayList<>();
-
- try (InputStreamReader streamReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
- JsonParser parser = objectReader.getFactory().createParser(streamReader)) {
-
- if (init(parser) && parser.nextToken() == com.fasterxml.jackson.core.JsonToken.START_OBJECT) {
- // at least one result
- do {
- final FileImpl file = objectReader.readValue(parser);
-
- checkHashes(dependency, file.getChecksums());
-
- final Matcher pathMatcher = PATH_PATTERN.matcher(file.getPath());
- if (!pathMatcher.matches()) {
- throw new IllegalStateException("Cannot extract the Maven information from the path "
- + "retrieved in Artifactory " + file.getPath());
- }
-
- final String groupId = pathMatcher.group("groupId").replace('/', '.');
- final String artifactId = pathMatcher.group("artifactId");
- final String version = pathMatcher.group("version");
-
- result.add(new MavenArtifact(groupId, artifactId, version, file.getDownloadUri(),
- MavenArtifact.derivePomUrl(artifactId, version, file.getDownloadUri())));
-
- } while (parser.nextToken() == com.fasterxml.jackson.core.JsonToken.START_OBJECT);
- } else {
- throw new FileNotFoundException("Artifact " + dependency + " not found in Artifactory");
- }
- }
-
- return result;
- }
-
- protected boolean init(JsonParser parser) throws IOException {
- com.fasterxml.jackson.core.JsonToken nextToken = parser.nextToken();
- if (nextToken != com.fasterxml.jackson.core.JsonToken.START_OBJECT) {
- throw new IOException("Expected " + com.fasterxml.jackson.core.JsonToken.START_OBJECT + ", got " + nextToken);
- }
-
- do {
- nextToken = parser.nextToken();
- if (nextToken == null) {
- break;
- }
-
- if (nextToken.isStructStart()) {
- if (nextToken == com.fasterxml.jackson.core.JsonToken.START_ARRAY && "results".equals(parser.currentName())) {
- return true;
- } else {
- parser.skipChildren();
- }
- }
- } while (true);
-
- return false;
- }
-
- /**
- * Validates the hashes of the dependency.
- *
- * @param dependency the dependency
- * @param checksums the collection of checksums (md5, sha1, sha256)
- * @throws FileNotFoundException thrown if one of the checksums does not
- * match
- */
- private void checkHashes(Dependency dependency, ChecksumsImpl checksums) throws FileNotFoundException {
- final String md5sum = dependency.getMd5sum();
- if (!checksums.getMd5().equals(md5sum)) {
- throw new FileNotFoundException("Artifact found by API is not matching the md5 "
- + "of the artifact (repository hash is " + checksums.getMd5() + WHILE_ACTUAL_IS + md5sum + ") !");
- }
- final String sha1sum = dependency.getSha1sum();
- if (!checksums.getSha1().equals(sha1sum)) {
- throw new FileNotFoundException("Artifact found by API is not matching the SHA1 "
- + "of the artifact (repository hash is " + checksums.getSha1() + WHILE_ACTUAL_IS + sha1sum + ") !");
- }
- final String sha256sum = dependency.getSha256sum();
- if (checksums.getSha256() != null && !checksums.getSha256().equals(sha256sum)) {
- throw new FileNotFoundException("Artifact found by API is not matching the SHA-256 "
- + "of the artifact (repository hash is " + checksums.getSha256() + WHILE_ACTUAL_IS + sha256sum + ") !");
- }
- }
-
/**
* Performs a pre-flight request to ensure the Artifactory service is
* reachable.
@@ -297,17 +154,20 @@ private void checkHashes(Dependency dependency, ChecksumsImpl checksums) throws
* false.
*/
public boolean preflightRequest() {
+ URL url = null;
try {
- final URL url = buildUrl(Checksum.getSHA1Checksum(UUID.randomUUID().toString()));
- final HttpURLConnection connection = connect(url);
- if (connection.getResponseCode() != 200) {
- LOGGER.warn("Expected 200 result from Artifactory ({}), got {}", url, connection.getResponseCode());
- return false;
- }
+ url = buildUrl(Checksum.getSHA1Checksum(UUID.randomUUID().toString()));
+ Downloader.getInstance().fetchContent(url, StandardCharsets.UTF_8);
return true;
} catch (IOException e) {
LOGGER.error("Cannot connect to Artifactory", e);
return false;
+ } catch (TooManyRequestsException e) {
+ LOGGER.warn("Expected 200 result from Artifactory ({}), got 429", url);
+ return false;
+ } catch (ResourceNotFoundException e) {
+ LOGGER.warn("Expected 200 result from Artifactory ({}), got 404", url);
+ return false;
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearchResponseHandler.java b/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearchResponseHandler.java
new file mode 100644
index 00000000000..711bfc657e0
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/data/artifactory/ArtifactorySearchResponseHandler.java
@@ -0,0 +1,219 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2018 - 2024 Nicolas Henneaux; Hans Aikema. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.data.artifactory;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.owasp.dependencycheck.data.nexus.MavenArtifact;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.owasp.dependencycheck.data.artifactory.ArtifactorySearch.X_RESULT_DETAIL_HEADER;
+
+class ArtifactorySearchResponseHandler implements HttpClientResponseHandler> {
+ /**
+ * Pattern to match the path returned by the Artifactory AQL API.
+ */
+ private static final Pattern PATH_PATTERN = Pattern.compile("^/(?.+)/(?[^/]+)/(?[^/]+)/[^/]+$");
+
+ /**
+ * Used for logging.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactorySearchResponseHandler.class);
+
+ /**
+ * Search result reader
+ */
+ private final ObjectReader fileImplReader;
+
+ /**
+ * The dependency that is expected to be in the response from Artifactory (if found)
+ */
+ private final Dependency expectedDependency;
+
+ /**
+ * The search request URL i.e., the location at which to search artifacts with checksum information
+ */
+ private final URL sourceUrl;
+
+ /**
+ * Creates a response handler for the response on a single dependency-search attempt.
+ *
+ * @param sourceUrl The search request URL
+ * @param dependency The dependency that is expected to be in the response when found (for validating the FileItem(s) in the response)
+ */
+ ArtifactorySearchResponseHandler(URL sourceUrl, Dependency dependency) {
+ this.fileImplReader = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readerFor(FileImpl.class);
+ this.expectedDependency = dependency;
+ this.sourceUrl = sourceUrl;
+ }
+
+ protected boolean init(JsonParser parser) throws IOException {
+ com.fasterxml.jackson.core.JsonToken nextToken = parser.nextToken();
+ if (nextToken != com.fasterxml.jackson.core.JsonToken.START_OBJECT) {
+ throw new IOException("Expected " + com.fasterxml.jackson.core.JsonToken.START_OBJECT + ", got " + nextToken);
+ }
+
+ do {
+ nextToken = parser.nextToken();
+ if (nextToken == null) {
+ break;
+ }
+
+ if (nextToken.isStructStart()) {
+ if (nextToken == com.fasterxml.jackson.core.JsonToken.START_ARRAY && "results".equals(parser.currentName())) {
+ return true;
+ } else {
+ parser.skipChildren();
+ }
+ }
+ } while (true);
+
+ return false;
+ }
+
+ /**
+ * Validates the hashes of the dependency.
+ *
+ * @param checksums the collection of checksums (md5, sha1, [sha256])
+ * @return Whether all available hashes match
+ */
+ private boolean checkHashes(ChecksumsImpl checksums) {
+ final String md5sum = expectedDependency.getMd5sum();
+ final String hashMismatchFormat = "Artifact found by API is not matching the {} of the artifact (repository hash is {} while actual is {}) !";
+ boolean match = true;
+ if (!checksums.getMd5().equals(md5sum)) {
+ LOGGER.warn(hashMismatchFormat, "md5", md5sum, checksums.getMd5());
+ match = false;
+ }
+ final String sha1sum = expectedDependency.getSha1sum();
+ if (!checksums.getSha1().equals(sha1sum)) {
+ LOGGER.warn(hashMismatchFormat, "sha1", sha1sum, checksums.getSha1());
+ match = false;
+ }
+ final String sha256sum = expectedDependency.getSha256sum();
+ /* For SHA-256, we need to validate that the checksum is non-null in the artifactory response.
+ * Extract from Artifactory documentation:
+ * New artifacts that are uploaded to Artifactory 5.5 and later will automatically have their SHA-256 checksum calculated.
+ * However, artifacts that were already hosted in Artifactory before the upgrade will not have their SHA-256 checksum in the database yet.
+ * To make full use of Artifactory's SHA-256 capabilities, you need to Migrate the Database to Include SHA-256 making sure that the record
+ * for each artifact includes its SHA-256 checksum.
+ */
+ if (checksums.getSha256() != null && !checksums.getSha256().equals(sha256sum)) {
+ LOGGER.warn(hashMismatchFormat, "sha256", sha256sum, checksums.getSha256());
+ match = false;
+ }
+ return match;
+ }
+
+ /**
+ * Process the Artifactory response.
+ *
+ * @param response the HTTP response
+ * @return a list of the Maven Artifact information that matches the searched dependency hash
+ * @throws FileNotFoundException When a matching artifact is not found
+ * @throws IOException thrown if there is an I/O error
+ */
+ @Override
+ public List handleResponse(ClassicHttpResponse response) throws IOException {
+ final List result = new ArrayList<>();
+
+ try (InputStreamReader streamReader = new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8);
+ JsonParser parser = fileImplReader.getFactory().createParser(streamReader)) {
+
+ if (init(parser) && parser.nextToken() == JsonToken.START_OBJECT) {
+ // at least one result
+ do {
+ final FileImpl file = fileImplReader.readValue(parser);
+
+ if (file.getChecksums() == null) {
+ LOGGER.warn(
+ "No checksums found in Artifactory search result for '{}'. " +
+ "Specifically, the result set contains URI '{}' but it is missing the 'checksums' property. " +
+ "Please make sure that the '{}' header is retained on any (reverse-)proxy, load-balancer or Web Application Firewall in the network path to your Artifactory server.",
+ sourceUrl, file.getUri(), X_RESULT_DETAIL_HEADER);
+ continue;
+ }
+
+ final Optional validationResult = validateUsability(file);
+ if (validationResult.isEmpty()) {
+ continue;
+ }
+ final Matcher pathMatcher = validationResult.get();
+
+ final String groupId = pathMatcher.group("groupId").replace('/', '.');
+ final String artifactId = pathMatcher.group("artifactId");
+ final String version = pathMatcher.group("version");
+
+ result.add(new MavenArtifact(groupId, artifactId, version, file.getDownloadUri(),
+ MavenArtifact.derivePomUrl(artifactId, version, file.getDownloadUri())));
+
+ } while (parser.nextToken() == JsonToken.START_OBJECT);
+ } else {
+ throw new FileNotFoundException("Artifact " + expectedDependency + " not found in Artifactory");
+ }
+ }
+ if (result.isEmpty()) {
+ throw new FileNotFoundException("Artifact " + expectedDependency
+ + " not found in Artifactory; discovered SHA1 hits not recognized as matching Maven artifacts");
+ }
+ return result;
+ }
+
+ /**
+ * Validate the FileImpl result for usability as a dependency.
+ *
+ * Checks that the file actually matches all known hashes and the path appears to match a maven repository G/A/V pattern.
+ *
+ * @param file The FileImpl from an Artifactory search response
+ * @return An Optional with the Matcher for the file path to retrieve the Maven G/A/V coordinates in case the result is usable for further
+ * processing, otherwise an empty Optional.
+ */
+ private Optional validateUsability(FileImpl file) {
+ final Optional result;
+ if (!checkHashes(file.getChecksums())) {
+ result = Optional.empty();
+ } else {
+ final Matcher pathMatcher = PATH_PATTERN.matcher(file.getPath());
+ if (!pathMatcher.matches()) {
+ LOGGER.debug("Cannot extract the Maven information from the path retrieved in Artifactory {}", file.getPath());
+ result = Optional.empty();
+ } else {
+ result = Optional.of(pathMatcher);
+ }
+ }
+ return result;
+ }
+}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCache.java b/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCache.java
index 9a86e1e74e5..d82f8482d42 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCache.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCache.java
@@ -17,7 +17,7 @@
*/
package org.owasp.dependencycheck.data.cache;
-import org.apache.commons.jcs.access.CacheAccess;
+import org.apache.commons.jcs3.access.CacheAccess;
/**
* A generic wrapper for the Java Caching System (JCS).
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCacheFactory.java b/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCacheFactory.java
index a0c63862f75..b5e8f6b8ddc 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCacheFactory.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/cache/DataCacheFactory.java
@@ -22,11 +22,11 @@
import java.io.InputStream;
import java.util.List;
import java.util.Properties;
-import org.apache.commons.jcs.JCS;
-import org.apache.commons.jcs.access.CacheAccess;
-import org.apache.commons.jcs.access.exception.CacheException;
-import org.apache.commons.jcs.engine.CompositeCacheAttributes;
-import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs3.JCS;
+import org.apache.commons.jcs3.access.CacheAccess;
+import org.apache.commons.jcs3.access.exception.CacheException;
+import org.apache.commons.jcs3.engine.CompositeCacheAttributes;
+import org.apache.commons.jcs3.engine.behavior.ICompositeCacheAttributes;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.data.nodeaudit.Advisory;
import org.owasp.dependencycheck.utils.FileUtils;
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java b/core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java
index 2ad37f41906..3ee1135a1ec 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java
@@ -17,34 +17,35 @@
*/
package org.owasp.dependencycheck.data.central;
+import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.owasp.dependencycheck.utils.DownloadFailedException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.ForbiddenException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
import org.owasp.dependencycheck.utils.TooManyRequestsException;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
-import org.apache.commons.jcs.access.exception.CacheException;
+import org.apache.commons.jcs3.access.exception.CacheException;
import org.owasp.dependencycheck.data.cache.DataCache;
import org.owasp.dependencycheck.data.cache.DataCacheFactory;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.utils.URLConnectionFactory;
-import org.owasp.dependencycheck.utils.XmlUtils;
+import org.owasp.dependencycheck.utils.ToXMLDocumentResponseHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
/**
* Class of methods to search Maven Central via Central.
@@ -105,7 +106,7 @@ public CentralSearch(Settings settings) throws MalformedURLException {
}
this.query = queryStr;
LOGGER.debug("Central Search Full URL: {}", String.format(query, rootURL, "[SHA1]"));
- if (null != settings.getString(Settings.KEYS.PROXY_SERVER)) {
+ if (null != settings.getString(Settings.KEYS.PROXY_SERVER) || null != System.getProperty("https.proxyHost")) {
useProxy = true;
LOGGER.debug("Using proxy");
} else {
@@ -135,14 +136,14 @@ public CentralSearch(Settings settings) throws MalformedURLException {
* @throws TooManyRequestsException if Central has received too many
* requests.
*/
- public List searchSha1(String sha1) throws IOException, TooManyRequestsException {
+ public List searchSha1(String sha1) throws IOException, TooManyRequestsException, ForbiddenException {
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
throw new IllegalArgumentException("Invalid SHA1 format");
}
if (cache != null) {
final List cached = cache.get(sha1);
if (cached != null) {
- LOGGER.debug("cache hit for Central: " + sha1);
+ LOGGER.debug("cache hit for Central: {}", sha1);
if (cached.isEmpty()) {
throw new FileNotFoundException("Artifact not found in Central");
}
@@ -154,68 +155,13 @@ public List searchSha1(String sha1) throws IOException, TooManyRe
LOGGER.trace("Searching Central url {}", url);
- // Determine if we need to use a proxy. The rules:
- // 1) If the proxy is set, AND the setting is set to true, use the proxy
- // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
- // or proxy is specifically set to false)
- final URLConnectionFactory factory = new URLConnectionFactory(settings);
- final HttpURLConnection conn = factory.createHttpURLConnection(url, useProxy);
-
- conn.setDoOutput(true);
-
// JSON would be more elegant, but there's not currently a dependency
// on JSON, so don't want to add one just for this
- conn.addRequestProperty("Accept", "application/xml");
- conn.connect();
-
- if (conn.getResponseCode() == 200) {
- boolean missing = false;
- try {
- final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
- final Document doc = builder.parse(conn.getInputStream());
- final XPath xpath = XPathFactory.newInstance().newXPath();
- final String numFound = xpath.evaluate("/response/result/@numFound", doc);
- if ("0".equals(numFound)) {
- missing = true;
- } else {
- final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
- for (int i = 0; i < docs.getLength(); i++) {
- final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
- LOGGER.trace("GroupId: {}", g);
- final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
- LOGGER.trace("ArtifactId: {}", a);
- final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
- final NodeList attributes = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
- boolean pomAvailable = false;
- boolean jarAvailable = false;
- for (int x = 0; x < attributes.getLength(); x++) {
- final String tmp = xpath.evaluate(".", attributes.item(x));
- if (".pom".equals(tmp)) {
- pomAvailable = true;
- } else if (".jar".equals(tmp)) {
- jarAvailable = true;
- }
- }
- final String centralContentUrl = settings.getString(Settings.KEYS.CENTRAL_CONTENT_URL);
- String artifactUrl = null;
- String pomUrl = null;
- if (jarAvailable) {
- //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
- artifactUrl = centralContentUrl + g.replace('.', '/') + '/' + a + '/'
- + v + '/' + a + '-' + v + ".jar";
- }
- if (pomAvailable) {
- //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
- pomUrl = centralContentUrl + g.replace('.', '/') + '/' + a + '/'
- + v + '/' + a + '-' + v + ".pom";
- }
- result.add(new MavenArtifact(g, a, v, artifactUrl, pomUrl));
- }
- }
- } catch (ParserConfigurationException | IOException | SAXException | XPathExpressionException e) {
- // Anything else is jacked up XML stuff that we really can't recover from well
- throw new IOException(e.getMessage(), e);
- }
+ final BasicHeader acceptHeader = new BasicHeader("Accept", "application/xml");
+ final AbstractHttpClientResponseHandler handler = new ToXMLDocumentResponseHandler();
+ try {
+ final Document doc = Downloader.getInstance().fetchAndHandle(url, handler, List.of(acceptHeader), useProxy);
+ final boolean missing = addMavenArtifacts(doc, result);
if (missing) {
if (cache != null) {
@@ -223,12 +169,21 @@ public List searchSha1(String sha1) throws IOException, TooManyRe
}
throw new FileNotFoundException("Artifact not found in Central");
}
- } else if (conn.getResponseCode() == 429) {
+ } catch (XPathExpressionException e) {
+ final String errorMessage = "Failed to parse MavenCentral XML Response: " + e.getMessage();
+ throw new IOException(errorMessage, e);
+ } catch (TooManyRequestsException e) {
final String errorMessage = "Too many requests sent to MavenCentral; additional requests are being rejected.";
- throw new TooManyRequestsException(errorMessage);
- } else {
- final String errorMessage = "Could not connect to MavenCentral (" + conn.getResponseCode() + "): " + conn.getResponseMessage();
- throw new IOException(errorMessage);
+ throw new TooManyRequestsException(errorMessage, e);
+ } catch (ResourceNotFoundException | DownloadFailedException e) {
+ final String errorMessage = "Could not connect to MavenCentral " + e.getMessage();
+ throw new IOException(errorMessage, e);
+ } catch (URISyntaxException e) {
+ final String errorMessage = "Could not convert central search URL to a URI " + e.getMessage();
+ throw new IOException(errorMessage, e);
+ } catch (ForbiddenException e) {
+ final String errorMessage = "Forbidden access to MavenCentral " + e.getMessage();
+ throw new ForbiddenException(errorMessage, e);
}
if (cache != null) {
cache.put(sha1, result);
@@ -236,6 +191,56 @@ public List searchSha1(String sha1) throws IOException, TooManyRe
return result;
}
+ /**
+ * Collect the artifacts from a MavenCentral search result and add them to the list.
+ * @param doc The Document received in response to the SHA1 search-request
+ * @param result The list of MavenArtifacts to which found artifacts will be added
+ * @return Whether the given document holds no search results
+ */
+ private boolean addMavenArtifacts(Document doc, List result) throws XPathExpressionException {
+ boolean missing = false;
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final String numFound = xpath.evaluate("/response/result/@numFound", doc);
+ if ("0".equals(numFound)) {
+ missing = true;
+ } else {
+ final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
+ for (int i = 0; i < docs.getLength(); i++) {
+ final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
+ LOGGER.trace("GroupId: {}", g);
+ final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
+ LOGGER.trace("ArtifactId: {}", a);
+ final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
+ final NodeList attributes = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
+ boolean pomAvailable = false;
+ boolean jarAvailable = false;
+ for (int x = 0; x < attributes.getLength(); x++) {
+ final String tmp = xpath.evaluate(".", attributes.item(x));
+ if (".pom".equals(tmp)) {
+ pomAvailable = true;
+ } else if (".jar".equals(tmp)) {
+ jarAvailable = true;
+ }
+ }
+ final String centralContentUrl = settings.getString(Settings.KEYS.CENTRAL_CONTENT_URL);
+ String artifactUrl = null;
+ String pomUrl = null;
+ if (jarAvailable) {
+ //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
+ artifactUrl = centralContentUrl + g.replace('.', '/') + '/' + a + '/'
+ + v + '/' + a + '-' + v + ".jar";
+ }
+ if (pomAvailable) {
+ //org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
+ pomUrl = centralContentUrl + g.replace('.', '/') + '/' + a + '/'
+ + v + '/' + a + '-' + v + ".pom";
+ }
+ result.add(new MavenArtifact(g, a, v, artifactUrl, pomUrl));
+ }
+ }
+ return missing;
+ }
+
/**
* Tests to determine if the given URL is invalid.
*
@@ -252,4 +257,5 @@ private boolean isInvalidURL(String url) {
}
return false;
}
+
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java b/core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java
index e3b4bae65f5..2155b30fcef 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java
@@ -20,19 +20,20 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.stream.JsonParsingException;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import jakarta.json.stream.JsonParsingException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
/**
- * Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected.
+ * Parses a Composer.lock file from an input stream. In a separate class so it
+ * can hopefully be injected.
*
* @author colezlaw
*/
@@ -43,12 +44,14 @@ public class ComposerLockParser {
* The JsonReader for parsing JSON
*/
private final JsonReader jsonReader;
-
/**
* The List of ComposerDependencies found
*/
private final List composerDependencies;
-
+ /**
+ * Whether to skip dev dependencies.
+ */
+ private final boolean skipDev;
/**
* The LOGGER
*/
@@ -58,11 +61,13 @@ public class ComposerLockParser {
* Creates a ComposerLockParser from a JsonReader and an InputStream.
*
* @param inputStream the InputStream to parse
+ * @param skipDev whether to skip dev dependencies
*/
- public ComposerLockParser(InputStream inputStream) {
+ public ComposerLockParser(InputStream inputStream, boolean skipDev) {
LOGGER.debug("Creating a ComposerLockParser");
this.jsonReader = Json.createReader(inputStream);
this.composerDependencies = new ArrayList<>();
+ this.skipDev = skipDev;
}
/**
@@ -76,26 +81,14 @@ public void process() {
LOGGER.debug("Found packages");
final JsonArray packages = composer.getJsonArray("packages");
for (JsonObject pkg : packages.getValuesAs(JsonObject.class)) {
- if (pkg.containsKey("name")) {
- final String groupName = pkg.getString("name");
- if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) {
- if (pkg.containsKey("version")) {
- final String group = groupName.substring(0, groupName.indexOf('/'));
- final String project = groupName.substring(groupName.indexOf('/') + 1);
- String version = pkg.getString("version");
- // Some version numbers begin with v - which doesn't end up matching CPE's
- if (version.startsWith("v")) {
- version = version.substring(1);
- }
- LOGGER.debug("Got package {}/{}/{}", group, project, version);
- composerDependencies.add(new ComposerDependency(group, project, version));
- } else {
- LOGGER.debug("Group/package {} does not have a version", groupName);
- }
- } else {
- LOGGER.debug("Got a dependency with no name");
- }
- }
+ processPackageEntry(pkg);
+ }
+ }
+ if (composer.containsKey("packages-dev") && !skipDev) {
+ LOGGER.debug("Found packages-dev");
+ final JsonArray devPackages = composer.getJsonArray("packages-dev");
+ for (JsonObject pkg : devPackages.getValuesAs(JsonObject.class)) {
+ processPackageEntry(pkg);
}
}
} catch (JsonParsingException jsonpe) {
@@ -109,6 +102,29 @@ public void process() {
}
}
+ protected void processPackageEntry(JsonObject pkg) {
+ if (pkg.containsKey("name")) {
+ final String groupName = pkg.getString("name");
+ if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) {
+ if (pkg.containsKey("version")) {
+ final String group = groupName.substring(0, groupName.indexOf('/'));
+ final String project = groupName.substring(groupName.indexOf('/') + 1);
+ String version = pkg.getString("version");
+ // Some version numbers begin with v - which doesn't end up matching CPE's
+ if (version.startsWith("v")) {
+ version = version.substring(1);
+ }
+ LOGGER.debug("Got package {}/{}/{}", group, project, version);
+ composerDependencies.add(new ComposerDependency(group, project, version));
+ } else {
+ LOGGER.debug("Group/package {} does not have a version", groupName);
+ }
+ } else {
+ LOGGER.debug("Got a dependency with no name");
+ }
+ }
+ }
+
/**
* Gets the list of dependencies.
*
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/cpe/AbstractMemoryIndex.java b/core/src/main/java/org/owasp/dependencycheck/data/cpe/AbstractMemoryIndex.java
index d3613a73c8c..5f1b35c5fff 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/cpe/AbstractMemoryIndex.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/cpe/AbstractMemoryIndex.java
@@ -50,6 +50,7 @@
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.slf4j.bridge.SLF4JBridgeHandler;
/**
*
@@ -67,6 +68,12 @@
@ThreadSafe
public abstract class AbstractMemoryIndex implements MemoryIndex {
+ static {
+ // Ensure Lucene uses SLF4J for logging
+ SLF4JBridgeHandler.removeHandlersForRootLogger();
+ SLF4JBridgeHandler.install();
+ }
+
/**
* The logger.
*/
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/elixir/MixAuditJsonParser.java b/core/src/main/java/org/owasp/dependencycheck/data/elixir/MixAuditJsonParser.java
index c6c85dab80f..3832cf0d82e 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/elixir/MixAuditJsonParser.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/elixir/MixAuditJsonParser.java
@@ -23,16 +23,16 @@
import javax.annotation.concurrent.NotThreadSafe;
-import javax.json.stream.JsonParsingException;
+import jakarta.json.stream.JsonParsingException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.JsonString;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import jakarta.json.JsonString;
/**
* Parses json output from `mix_audit --format json`.
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModDependency.java b/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModDependency.java
index 9975329210d..4fa77a00cef 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModDependency.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModDependency.java
@@ -19,13 +19,6 @@
import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURLBuilder;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
@@ -33,12 +26,20 @@
import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
import org.owasp.dependencycheck.dependency.naming.Identifier;
import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
+import org.owasp.dependencycheck.utils.Checksum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
import static org.owasp.dependencycheck.analyzer.GolangModAnalyzer.DEPENDENCY_ECOSYSTEM;
import static org.owasp.dependencycheck.analyzer.GolangModAnalyzer.GO_MOD;
-import org.owasp.dependencycheck.utils.Checksum;
/**
* Represents a Go module dependency.
@@ -185,7 +186,6 @@ private Dependency createDependency(Dependency parentDependency, String name, St
* Extracts the content of the license file into the dependency's license
* field.
*
- *
* @param dependency the dependency being analyzed
* @param file the license file
*/
@@ -195,7 +195,7 @@ private void extractLicense(Dependency dependency, File file) {
for (File f : files) {
if (LICENSE_FILES.contains(f.getName().toUpperCase())) {
try {
- final String license = FileUtils.readFileToString(f, StandardCharsets.UTF_8);
+ final String license = new String(Files.readAllBytes(f.toPath()), StandardCharsets.UTF_8);
dependency.setLicense(license);
break;
} catch (IOException ex) {
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModJsonParser.java b/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModJsonParser.java
index 17d9d9d1a40..7f683295cea 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModJsonParser.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/golang/GoModJsonParser.java
@@ -23,13 +23,13 @@
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.JsonReaderFactory;
-import javax.json.stream.JsonParsingException;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonException;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import jakarta.json.JsonReaderFactory;
+import jakarta.json.stream.JsonParsingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericFilter.java b/core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericFilter.java
index ae0e8862dea..aa5b326248c 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericFilter.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericFilter.java
@@ -28,9 +28,10 @@
/**
* A simple alphanumeric filter that removes non-alphanumeric characters from
* the terms. If a term contains a non-alphanumeric character it may be split
- * into multiple terms:
+ * into multiple terms.
*
- *
+ *
+ *
Filtering examples
*
term
results in
*
bob
bob
*
bob-cat
bob cat
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
index 4670966fe19..264d0a84c09 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
@@ -13,76 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
+ * Copyright (c) 2023 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nexus;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import org.owasp.dependencycheck.utils.Settings;
-
-import org.owasp.dependencycheck.utils.URLConnectionFactory;
-import org.owasp.dependencycheck.utils.XmlUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-/**
- * Class of methods to search Nexus repositories.
- *
- * @author colezlaw
- */
-@ThreadSafe
-public class NexusSearch {
-
- /**
- * The root URL for the Nexus repository service.
- */
- private final URL rootURL;
-
- /**
- * Whether to use the Proxy when making requests.
- */
- private final boolean useProxy;
- /**
- * The configured settings.
- */
- private final Settings settings;
- /**
- * Used for logging.
- */
- private static final Logger LOGGER = LoggerFactory.getLogger(NexusSearch.class);
-
- /**
- * Creates a NexusSearch for the given repository URL.
- *
- * @param settings the configured settings
- * @param useProxy flag indicating if the proxy settings should be used
- * @throws java.net.MalformedURLException thrown if the configured URL is
- * invalid
- */
- public NexusSearch(Settings settings, boolean useProxy) throws MalformedURLException {
- this.settings = settings;
- this.useProxy = useProxy;
-
- final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
- LOGGER.debug("Nexus Search URL: {}", searchUrl);
- this.rootURL = new URL(searchUrl);
-
- }
+public interface NexusSearch {
/**
* Searches the configured Nexus repository for the given sha1 hash. If the
* artifact is found, a MavenArtifact is populated with the
@@ -91,135 +28,14 @@ public NexusSearch(Settings settings, boolean useProxy) throws MalformedURLExcep
* @param sha1 The SHA-1 hash string for which to search
* @return the populated Maven coordinates
* @throws IOException if it's unable to connect to the specified repository
- * or if the specified artifact is not found.
+ * or if the specified artifact is not found.
*/
- public MavenArtifact searchSha1(String sha1) throws IOException {
- if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
- throw new IllegalArgumentException("Invalid SHA1 format");
- }
-
- final URL url = new URL(rootURL, String.format("identify/sha1/%s",
- sha1.toLowerCase()));
-
- LOGGER.debug("Searching Nexus url {}", url);
-
- // Determine if we need to use a proxy. The rules:
- // 1) If the proxy is set, AND the setting is set to true, use the proxy
- // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
- // or proxy is specifically set to false
- final HttpURLConnection conn;
- final URLConnectionFactory factory = new URLConnectionFactory(settings);
- conn = factory.createHttpURLConnection(url, useProxy);
- conn.setDoOutput(true);
- final String authHeader = buildHttpAuthHeaderValue();
- if (!authHeader.isEmpty()) {
- conn.addRequestProperty("Authorization", authHeader);
- }
-
- // JSON would be more elegant, but there's not currently a dependency
- // on JSON, so don't want to add one just for this
- conn.addRequestProperty("Accept", "application/xml");
- conn.connect();
-
- switch (conn.getResponseCode()) {
- case 200:
- try {
- final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
- final Document doc = builder.parse(conn.getInputStream());
- final XPath xpath = XPathFactory.newInstance().newXPath();
- final String groupId = xpath
- .evaluate(
- "/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
- doc);
- final String artifactId = xpath.evaluate(
- "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
- doc);
- final String version = xpath
- .evaluate(
- "/org.sonatype.nexus.rest.model.NexusArtifact/version",
- doc);
- final String link = xpath
- .evaluate(
- "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
- doc);
- final String pomLink = xpath
- .evaluate(
- "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink",
- doc);
- final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
- if (link != null && !link.isEmpty()) {
- ma.setArtifactUrl(link);
- }
- if (pomLink != null && !pomLink.isEmpty()) {
- ma.setPomUrl(pomLink);
- }
- return ma;
- } catch (ParserConfigurationException | IOException | SAXException | XPathExpressionException e) {
- // Anything else is jacked-up XML stuff that we really can't recover
- // from well
- throw new IOException(e.getMessage(), e);
- }
- case 404:
- throw new FileNotFoundException("Artifact not found in Nexus");
- default:
- LOGGER.debug("Could not connect to Nexus received response code: {} {}",
- conn.getResponseCode(), conn.getResponseMessage());
- throw new IOException("Could not connect to Nexus");
- }
- }
+ MavenArtifact searchSha1(String sha1) throws IOException;
/**
* Do a preflight request to see if the repository is actually working.
*
- * @return whether the repository is listening and returns the /status URL
- * correctly
- */
- public boolean preflightRequest() {
- final HttpURLConnection conn;
- try {
- final URL url = new URL(rootURL, "status");
- final URLConnectionFactory factory = new URLConnectionFactory(settings);
- conn = factory.createHttpURLConnection(url, useProxy);
- conn.addRequestProperty("Accept", "application/xml");
- final String authHeader = buildHttpAuthHeaderValue();
- if (!authHeader.isEmpty()) {
- conn.addRequestProperty("Authorization", authHeader);
- }
- conn.connect();
- if (conn.getResponseCode() != 200) {
- LOGGER.warn("Expected 200 result from Nexus, got {}", conn.getResponseCode());
- return false;
- }
- final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
-
- final Document doc = builder.parse(conn.getInputStream());
- if (!"status".equals(doc.getDocumentElement().getNodeName())) {
- LOGGER.warn("Expected root node name of status, got {}", doc.getDocumentElement().getNodeName());
- return false;
- }
- } catch (IOException | ParserConfigurationException | SAXException e) {
- LOGGER.warn("Pre-flight request to Nexus failed: ", e);
- return false;
- }
- return true;
- }
-
- /**
- * Constructs the base64 encoded basic authentication header value.
- *
- * @return the base64 encoded basic authentication header value
+ * @return whether the repository is listening and returns the expected status response
*/
- private String buildHttpAuthHeaderValue() {
- final String user = settings.getString(Settings.KEYS.ANALYZER_NEXUS_USER, "");
- final String pass = settings.getString(Settings.KEYS.ANALYZER_NEXUS_PASSWORD, "");
- String result = "";
- if (user.isEmpty() || pass.isEmpty()) {
- LOGGER.debug("Skip authentication as user and/or password for nexus is empty");
- } else {
- final String auth = user + ':' + pass;
- final String base64Auth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
- result = "Basic " + base64Auth;
- }
- return result;
- }
+ boolean preflightRequest();
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV2Search.java b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV2Search.java
new file mode 100644
index 00000000000..9e2401fc3e8
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV2Search.java
@@ -0,0 +1,174 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.data.nexus;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import javax.annotation.concurrent.ThreadSafe;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.hc.client5.http.HttpResponseException;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.owasp.dependencycheck.utils.DownloadFailedException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.ForbiddenException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
+import org.owasp.dependencycheck.utils.Settings;
+
+import org.owasp.dependencycheck.utils.ToXMLDocumentResponseHandler;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+/**
+ * Class of methods to search Nexus repositories.
+ *
+ * @author colezlaw
+ */
+@ThreadSafe
+public class NexusV2Search implements NexusSearch {
+
+ /**
+ * The root URL for the Nexus repository service.
+ */
+ private final URL rootURL;
+
+ /**
+ * Whether to use the Proxy when making requests.
+ */
+ private final boolean useProxy;
+ /**
+ * The configured settings.
+ */
+ private final Settings settings;
+ /**
+ * Used for logging.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(NexusV2Search.class);
+
+ /**
+ * Creates a NexusSearch for the given repository URL.
+ *
+ * @param settings the configured settings
+ * @param useProxy flag indicating if the proxy settings should be used
+ * @throws java.net.MalformedURLException thrown if the configured URL is
+ * invalid
+ */
+ public NexusV2Search(Settings settings, boolean useProxy) throws MalformedURLException {
+ this.settings = settings;
+ this.useProxy = useProxy;
+
+ final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
+ LOGGER.debug("Nexus Search URL: {}", searchUrl);
+ this.rootURL = new URL(searchUrl);
+
+ }
+
+ @Override
+ public MavenArtifact searchSha1(String sha1) throws IOException {
+ if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
+ throw new IllegalArgumentException("Invalid SHA1 format");
+ }
+
+ final URL url = new URL(rootURL, String.format("identify/sha1/%s",
+ sha1.toLowerCase()));
+
+ LOGGER.debug("Searching Nexus url {}", url);
+
+ try {
+ // JSON would be more elegant, but there's not currently a dependency
+ // on JSON, so don't want to add one just for this
+ final ToXMLDocumentResponseHandler handler = new ToXMLDocumentResponseHandler();
+ final Document doc = Downloader.getInstance().fetchAndHandle(url, handler, List.of(new BasicHeader(HttpHeaders.ACCEPT,
+ ContentType.APPLICATION_XML)));
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final String groupId = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
+ doc);
+ final String artifactId = xpath.evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
+ doc);
+ final String version = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/version",
+ doc);
+ final String link = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
+ doc);
+ final String pomLink = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/pomLink",
+ doc);
+ final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
+ if (link != null && !link.isEmpty()) {
+ ma.setArtifactUrl(link);
+ }
+ if (pomLink != null && !pomLink.isEmpty()) {
+ ma.setPomUrl(pomLink);
+ }
+ return ma;
+ } catch (DownloadFailedException | TooManyRequestsException e) {
+ if (LOGGER.isDebugEnabled()) {
+ int responseCode = -1;
+ String responseMessage = "";
+ if (e.getCause() instanceof HttpResponseException) {
+ final HttpResponseException cause = (HttpResponseException) e.getCause();
+ responseCode = cause.getStatusCode();
+ responseMessage = cause.getReasonPhrase();
+ }
+ LOGGER.debug("Could not connect to Nexus received response code: {} {}",
+ responseCode, responseMessage);
+ }
+ throw new IOException("Could not connect to Nexus");
+ } catch (ResourceNotFoundException e) {
+ throw new FileNotFoundException("Artifact not found in Nexus");
+ } catch (XPathExpressionException | URISyntaxException | ForbiddenException e) {
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean preflightRequest() {
+ try {
+ final URL url = new URL(rootURL, "status");
+ final ToXMLDocumentResponseHandler handler = new ToXMLDocumentResponseHandler();
+ final Document doc = Downloader.getInstance().fetchAndHandle(url, handler, List.of(new BasicHeader(HttpHeaders.ACCEPT,
+ ContentType.APPLICATION_XML)));
+ if (!"status".equals(doc.getDocumentElement().getNodeName())) {
+ LOGGER.warn("Pre-flight request to Nexus failed; expected root node name of status, got {}", doc.getDocumentElement().getNodeName());
+ return false;
+ }
+ } catch (IOException | TooManyRequestsException | ResourceNotFoundException | URISyntaxException e) {
+ LOGGER.warn("Pre-flight request to Nexus failed: ", e);
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV3Search.java b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV3Search.java
new file mode 100644
index 00000000000..8bb31bc7573
--- /dev/null
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusV3Search.java
@@ -0,0 +1,287 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (c) 2023 Hans Aikema. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.data.nexus;
+
+import org.apache.hc.client5.http.HttpResponseException;
+import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.jetbrains.annotations.Nullable;
+import org.owasp.dependencycheck.utils.DownloadFailedException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.ForbiddenException;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
+import org.owasp.dependencycheck.utils.Settings;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Class of methods to search Nexus v3 repositories.
+ *
+ * @author Hans Aikema
+ */
+@ThreadSafe
+public class NexusV3Search implements NexusSearch {
+
+ /**
+ * By default, NexusV3Search accepts only classifier-less artifacts.
+ *
+ * This prevents, among others, sha1-collisions for empty jars on empty javadoc/sources jars.
+ * See e.g. issues #5559 and #5118
+ */
+ private final Set acceptedClassifiers = new HashSet<>();
+
+ /**
+ * The root URL for the Nexus repository service.
+ */
+ private final URL rootURL;
+
+ /**
+ * Whether to use the Proxy when making requests.
+ */
+ private final boolean useProxy;
+ /**
+ * The configured settings.
+ */
+ private final Settings settings;
+ /**
+ * Used for logging.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(NexusV3Search.class);
+
+ /**
+ * Creates a NexusV3Search for the given repository URL.
+ *
+ * @param settings the configured settings
+ * @param useProxy flag indicating if the proxy settings should be used
+ * @throws MalformedURLException thrown if the configured URL is
+ * invalid
+ */
+ public NexusV3Search(Settings settings, boolean useProxy) throws MalformedURLException {
+ this.settings = settings;
+ this.useProxy = useProxy;
+ this.acceptedClassifiers.add(null);
+ final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
+ LOGGER.debug("Nexus Search URL: {}", searchUrl);
+ this.rootURL = new URL(searchUrl);
+
+ }
+
+ @Override
+ public MavenArtifact searchSha1(String sha1) throws IOException {
+ if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
+ throw new IllegalArgumentException("Invalid SHA1 format");
+ }
+
+ final List collectedMatchingArtifacts = new ArrayList<>(1);
+ try (CloseableHttpClient client = Downloader.getInstance().getHttpClient(useProxy)) {
+ String continuationToken = retrievePageAndAddMatchingArtifact(client, collectedMatchingArtifacts, sha1, null);
+ while (continuationToken != null && collectedMatchingArtifacts.isEmpty()) {
+ continuationToken = retrievePageAndAddMatchingArtifact(client, collectedMatchingArtifacts, sha1, continuationToken);
+ }
+ }
+ if (collectedMatchingArtifacts.isEmpty()) {
+ throw new FileNotFoundException("Artifact not found in Nexus");
+ } else {
+ return collectedMatchingArtifacts.get(0);
+ }
+ }
+
+ private String retrievePageAndAddMatchingArtifact(CloseableHttpClient client, List collectedMatchingArtifacts, String sha1,
+ @Nullable String continuationToken) throws IOException {
+ final URL url;
+ LOGGER.debug("Search with continuation token {}", continuationToken);
+ if (continuationToken == null) {
+ url = new URL(rootURL, String.format("v1/search/?sha1=%s",
+ sha1.toLowerCase()));
+ } else {
+ url = new URL(rootURL, String.format("v1/search/?sha1=%s&continuationToken=%s",
+ sha1.toLowerCase(), continuationToken));
+ }
+
+ LOGGER.debug("Searching Nexus url {}", url);
+ // Determine if we need to use a proxy. The rules:
+ // 1) If the proxy is set, AND the setting is set to true, use the proxy
+ // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
+ // or proxy is specifically set to false
+ final NexusV3SearchResponseHandler handler = new NexusV3SearchResponseHandler(collectedMatchingArtifacts, sha1, acceptedClassifiers);
+ try {
+ return Downloader.getInstance().fetchAndHandle(client, url, handler, List.of(new BasicHeader(HttpHeaders.ACCEPT,
+ ContentType.APPLICATION_JSON)));
+ } catch (TooManyRequestsException | ResourceNotFoundException | DownloadFailedException | ForbiddenException e) {
+ if (LOGGER.isDebugEnabled()) {
+ int responseCode = -1;
+ String responseMessage = "";
+ if (e.getCause() instanceof HttpResponseException) {
+ final HttpResponseException cause = (HttpResponseException) e.getCause();
+ responseCode = cause.getStatusCode();
+ responseMessage = cause.getReasonPhrase();
+ }
+ LOGGER.debug("Could not connect to Nexus received response code: {} {}",
+ responseCode, responseMessage);
+ }
+ throw new IOException("Could not connect to Nexus", e);
+ }
+ }
+
+ private static final class NexusV3SearchResponseHandler extends AbstractHttpClientResponseHandler {
+
+ /**
+ * The list to which matching artifacts are to be added
+ */
+ private final List matchingArtifacts;
+ /**
+ * The sha1 for which the search results are being handled
+ */
+ private final String sha1;
+ /**
+ * The classifiers to be accepted
+ */
+ private final Set acceptedClassifiers;
+
+ private NexusV3SearchResponseHandler(List matchingArtifacts, String sha1, Set acceptedClassifiers) {
+ this.matchingArtifacts = matchingArtifacts;
+ this.sha1 = sha1;
+ this.acceptedClassifiers = acceptedClassifiers;
+ }
+
+ @Override
+ public @Nullable String handleEntity(HttpEntity entity) throws IOException {
+ try (InputStream in = entity.getContent();
+ InputStreamReader isReader = new InputStreamReader(in, StandardCharsets.UTF_8);
+ BufferedReader reader = new BufferedReader(isReader);
+ ) {
+ final String jsonString = reader.lines().collect(Collectors.joining("\n"));
+ LOGGER.debug("JSON String was >>>{}<<<", jsonString);
+ final JsonObject jsonResponse;
+ try (
+ StringReader stringReader = new StringReader(jsonString);
+ JsonReader jsonReader = Json.createReader(stringReader)
+ ) {
+ jsonResponse = jsonReader.readObject();
+ }
+ LOGGER.debug("Response: {}", jsonResponse);
+ final JsonArray components = jsonResponse.getJsonArray("items");
+ LOGGER.debug("Items: {}", components);
+ final String continuationToken = jsonResponse.getString("continuationToken", null);
+ boolean found = false;
+ for (int i = 0; i < components.size() && !found; i++) {
+ boolean jarFound = false;
+ boolean pomFound = false;
+ String downloadUrl = null;
+ String groupId = null;
+ String artifactId = null;
+ String version = null;
+ String pomUrl = null;
+
+ final JsonObject component = components.getJsonObject(i);
+
+ final String format = component.getString("format", "unknown");
+ if ("maven2".equals(format)) {
+ LOGGER.debug("Checking Maven2 artifact for {}", component);
+ final JsonArray assets = component.getJsonArray("assets");
+ for (int j = 0; !found && j < assets.size(); j++) {
+ final JsonObject asset = assets.getJsonObject(j);
+ LOGGER.debug("Checking {}", asset);
+ final JsonObject checksums = asset.getJsonObject("checksum");
+ final JsonObject maven2 = asset.getJsonObject("maven2");
+ if (maven2 != null) {
+ // logical names for the jar acceptance routine
+ final boolean shaMatch = checksums != null && sha1.equals(checksums.getString("sha1", null));
+ final boolean hasAcceptedClassifier = acceptedClassifiers.contains(maven2.getString("classifier", null));
+ final boolean isAJar = "jar".equals(maven2.getString("extension", null));
+ LOGGER.debug("shaMatch {}", shaMatch);
+ LOGGER.debug("hasAcceptedClassifier {}", hasAcceptedClassifier);
+ LOGGER.debug("isAJar {}", isAJar);
+ if (
+ isAJar
+ && hasAcceptedClassifier
+ && shaMatch
+ ) {
+ downloadUrl = asset.getString("downloadUrl");
+ groupId = maven2.getString("groupId");
+ artifactId = maven2.getString("artifactId");
+ version = maven2.getString("version");
+
+ jarFound = true;
+ } else if ("pom".equals(maven2.getString("extension"))) {
+ LOGGER.debug("pom found {}", asset);
+ pomFound = true;
+ pomUrl = asset.getString("downloadUrl");
+ }
+ }
+ if (pomFound && jarFound) {
+ found = true;
+ }
+ }
+ if (found) {
+ matchingArtifacts.add(new MavenArtifact(groupId, artifactId, version, downloadUrl, pomUrl));
+ } else if (jarFound) {
+ final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version, downloadUrl);
+ ma.setPomUrl(MavenArtifact.derivePomUrl(artifactId, version, downloadUrl));
+ matchingArtifacts.add(ma);
+ found = true;
+ }
+ }
+ }
+ return continuationToken;
+ }
+ }
+ }
+
+ @Override
+ public boolean preflightRequest() {
+ try {
+ final URL url = new URL(rootURL, "v1/status");
+ final String response = Downloader.getInstance().fetchContent(url, useProxy, StandardCharsets.UTF_8);
+ if (response == null || !response.isEmpty()) {
+ LOGGER.warn("Expected empty OK response (content-length 0), got {}", response == null ? "null" : response.length());
+ return false;
+ }
+ } catch (IOException | TooManyRequestsException | ResourceNotFoundException e) {
+ LOGGER.warn("Pre-flight request to Nexus failed: ", e);
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/Advisory.java b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/Advisory.java
index a6f044f9dbe..97fab27f268 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/Advisory.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/Advisory.java
@@ -17,8 +17,9 @@
*/
package org.owasp.dependencycheck.data.nodeaudit;
-import org.owasp.dependencycheck.dependency.CvssV3;
+
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV3;
import java.io.Serializable;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NodeAuditSearch.java b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NodeAuditSearch.java
index 2d4b7aefbbb..c1f058ca6eb 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NodeAuditSearch.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NodeAuditSearch.java
@@ -17,29 +17,32 @@
*/
package org.owasp.dependencycheck.data.nodeaudit;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
+import java.util.ArrayList;
import java.util.List;
import javax.annotation.concurrent.ThreadSafe;
+import org.apache.hc.client5.http.HttpResponseException;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.json.JSONException;
import org.json.JSONObject;
+import org.owasp.dependencycheck.utils.DownloadFailedException;
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.ResourceNotFoundException;
import org.owasp.dependencycheck.utils.Settings;
-import org.owasp.dependencycheck.utils.URLConnectionFactory;
+import org.owasp.dependencycheck.utils.TooManyRequestsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import org.apache.commons.jcs.access.exception.CacheException;
+import jakarta.json.JsonObject;
+import org.apache.commons.jcs3.access.exception.CacheException;
import static org.owasp.dependencycheck.analyzer.NodeAuditAnalyzer.DEFAULT_URL;
@@ -48,7 +51,6 @@
import org.owasp.dependencycheck.data.cache.DataCache;
import org.owasp.dependencycheck.data.cache.DataCacheFactory;
import org.owasp.dependencycheck.utils.Checksum;
-import org.owasp.dependencycheck.utils.URLConnectionFailureException;
/**
* Class of methods to search via Node Audit API.
@@ -146,80 +148,64 @@ public List submitPackage(JsonObject packageJson) throws SearchExcepti
* @throws IOException if it's unable to connect to Node Audit API
*/
private List submitPackage(JsonObject packageJson, String key, int count) throws SearchException, IOException {
- try {
- if (LOGGER.isTraceEnabled()) {
- LOGGER.trace("----------------------------------------");
- LOGGER.trace("Node Audit Payload:");
- LOGGER.trace(packageJson.toString());
- LOGGER.trace("----------------------------------------");
- LOGGER.trace("----------------------------------------");
- }
- final byte[] packageDatabytes = packageJson.toString().getBytes(StandardCharsets.UTF_8);
- final URLConnectionFactory factory = new URLConnectionFactory(settings);
- final HttpURLConnection conn = factory.createHttpURLConnection(nodeAuditUrl, useProxy);
- conn.setDoOutput(true);
- conn.setDoInput(true);
- conn.setRequestMethod("POST");
- conn.setRequestProperty("user-agent", "npm/6.1.0 node/v10.5.0 linux x64");
- conn.setRequestProperty("npm-in-ci", "false");
- conn.setRequestProperty("npm-scope", "");
- conn.setRequestProperty("npm-session", generateRandomSession());
- conn.setRequestProperty("content-type", "application/json");
- conn.setRequestProperty("Content-Length", Integer.toString(packageDatabytes.length));
- conn.connect();
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("----------------------------------------");
+ LOGGER.trace("Node Audit Payload:");
+ LOGGER.trace(packageJson.toString());
+ LOGGER.trace("----------------------------------------");
+ LOGGER.trace("----------------------------------------");
+ }
+ final List additionalHeaders = new ArrayList<>();
+ additionalHeaders.add(new BasicHeader(HttpHeaders.USER_AGENT, "npm/6.1.0 node/v10.5.0 linux x64"));
+ additionalHeaders.add(new BasicHeader("npm-in-ci", "false"));
+ additionalHeaders.add(new BasicHeader("npm-scope", ""));
+ additionalHeaders.add(new BasicHeader("npm-session", generateRandomSession()));
- try (OutputStream os = new BufferedOutputStream(conn.getOutputStream())) {
- os.write(packageDatabytes);
- os.flush();
+ try {
+ final String response = Downloader.getInstance().postBasedFetchContent(nodeAuditUrl.toURI(),
+ packageJson.toString(), ContentType.APPLICATION_JSON, additionalHeaders);
+ final JSONObject jsonResponse = new JSONObject(response);
+ final NpmAuditParser parser = new NpmAuditParser();
+ final List advisories = parser.parse(jsonResponse);
+ if (cache != null) {
+ cache.put(key, advisories);
}
-
- switch (conn.getResponseCode()) {
- case 200:
- try (InputStream in = new BufferedInputStream(conn.getInputStream());
- JsonReader jsonReader = Json.createReader(in)) {
- final JSONObject jsonResponse = new JSONObject(jsonReader.readObject().toString());
- final NpmAuditParser parser = new NpmAuditParser();
- final List advisories = parser.parse(jsonResponse);
- if (cache != null) {
- cache.put(key, advisories);
- }
- return advisories;
- } catch (Exception ex) {
- LOGGER.debug("Error connecting to Node Audit API. Error: {}",
- ex.getMessage());
- throw new SearchException("Could not connect to Node Audit API: " + ex.getMessage(), ex);
- }
- case 503:
- LOGGER.debug("Node Audit API returned `{} {}` - retrying request.",
- conn.getResponseCode(), conn.getResponseMessage());
- if (count < 5) {
- final int next = count + 1;
- try {
- Thread.sleep(1500L * next);
- } catch (InterruptedException ex) {
- Thread.currentThread().interrupt();
- throw new UnexpectedAnalysisException(ex);
+ return advisories;
+ } catch (RuntimeException | URISyntaxException | JSONException | TooManyRequestsException | ResourceNotFoundException ex) {
+ LOGGER.debug("Error connecting to Node Audit API. Error: {}",
+ ex.getMessage());
+ throw new SearchException("Could not connect to Node Audit API: " + ex.getMessage(), ex);
+ } catch (DownloadFailedException e) {
+ if (e.getCause() instanceof HttpResponseException) {
+ final HttpResponseException hre = (HttpResponseException) e.getCause();
+ switch (hre.getStatusCode()) {
+ case 503:
+ LOGGER.debug("Node Audit API returned `{} {}` - retrying request.",
+ hre.getStatusCode(), hre.getReasonPhrase());
+ if (count < 5) {
+ final int next = count + 1;
+ try {
+ Thread.sleep(1500L * next);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ throw new UnexpectedAnalysisException(ex);
+ }
+ return submitPackage(packageJson, key, next);
}
- return submitPackage(packageJson, key, next);
- }
- throw new SearchException("Could not perform Node Audit analysis - service returned a 503.");
- case 400:
- LOGGER.debug("Invalid payload submitted to Node Audit API. Received response code: {} {}",
- conn.getResponseCode(), conn.getResponseMessage());
- throw new SearchException("Could not perform Node Audit analysis. Invalid payload submitted to Node Audit API.");
- default:
- LOGGER.debug("Could not connect to Node Audit API. Received response code: {} {}",
- conn.getResponseCode(), conn.getResponseMessage());
- throw new IOException("Could not connect to Node Audit API");
- }
- } catch (IOException ex) {
- if (ex instanceof javax.net.ssl.SSLHandshakeException
- && ex.getMessage().contains("unable to find valid certification path to requested target")) {
- final String msg = String.format("Unable to connect to '%s' - the Java trust store does not contain a trusted root for the cert. "
- + " Please see https://github.com/jeremylong/InstallCert for one method of updating the trusted certificates.", nodeAuditUrl);
- throw new URLConnectionFailureException(msg, ex);
+ throw new SearchException("Could not perform Node Audit analysis - service returned a 503.", e);
+ case 400:
+ LOGGER.debug("Invalid payload submitted to Node Audit API. Received response code: {} {}",
+ hre.getStatusCode(), hre.getReasonPhrase());
+ throw new SearchException("Could not perform Node Audit analysis. Invalid payload submitted to Node Audit API.", e);
+ default:
+ LOGGER.debug("Could not connect to Node Audit API. Received response code: {} {}",
+ hre.getStatusCode(), hre.getReasonPhrase());
+ throw new IOException("Could not connect to Node Audit API", e);
+ }
+ } else {
+ LOGGER.debug("Could not connect to Node Audit API. Received generic DownloadException", e);
+ throw new IOException("Could not connect to Node Audit API", e);
}
- throw ex;
}
}
@@ -235,6 +221,6 @@ private String generateRandomSession() {
while (sb.length() < length) {
sb.append(Integer.toHexString(r.nextInt()));
}
- return sb.toString().substring(0, length);
+ return sb.substring(0, length);
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmAuditParser.java b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmAuditParser.java
index 5f0cf87d155..5c5b01fc416 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmAuditParser.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmAuditParser.java
@@ -17,15 +17,17 @@
*/
package org.owasp.dependencycheck.data.nodeaudit;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV3;
import org.json.JSONArray;
import org.json.JSONObject;
-import org.owasp.dependencycheck.dependency.CvssV3;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.json.JSONException;
+import org.owasp.dependencycheck.utils.CvssUtil;
/**
* Parser for NPM Audit API response. This parser is derived from:
@@ -118,7 +120,7 @@ private Advisory parseAdvisory(JSONObject object) throws JSONException {
}
final JSONObject jsonCvss = object.optJSONObject("cvss");
if (jsonCvss != null) {
- float baseScore = -1.0f;
+ double baseScore = -1.0;
final String score = jsonCvss.optString("score");
if (score != null) {
try {
@@ -130,17 +132,17 @@ private Advisory parseAdvisory(JSONObject object) throws JSONException {
}
if (baseScore >= 0.0) {
final String vector = jsonCvss.optString("vectorString");
- if (vector != null) {
+ if (vector != null && !"null".equals(vector)) {
if (vector.startsWith("CVSS:3") && baseScore >= 0.0) {
try {
- final CvssV3 cvss = new CvssV3(vector, baseScore);
+ final CvssV3 cvss = CvssUtil.vectorToCvssV3(vector, baseScore);
advisory.setCvssV3(cvss);
} catch (IllegalArgumentException iae) {
- LOGGER.warn("Invalid CVSS vector format encountered in NPM Audit results '{}' ", vector, iae);
+ LOGGER.warn("Invalid CVSS vector format encountered in NPM Audit results '{}': {} ", vector, iae.getMessage());
}
} else {
LOGGER.warn("Unsupported CVSS vector format in NPM Audit results, please file a feature "
- + "request at https://github.com/jeremylong/DependencyCheck/issues/new/choose to "
+ + "request at https://github.com/dependency-check/DependencyCheck/issues/new/choose to "
+ "support vector format '{}' ", vector);
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
index 982c9896585..478c1d5f2bc 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nodeaudit/NpmPayloadBuilder.java
@@ -24,11 +24,11 @@
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonObjectBuilder;
-import javax.json.JsonString;
-import javax.json.JsonValue;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
import javax.annotation.concurrent.ThreadSafe;
import org.apache.commons.collections4.MultiValuedMap;
@@ -40,6 +40,7 @@
*/
@ThreadSafe
public final class NpmPayloadBuilder {
+
/**
* Private constructor for utility class.
*/
@@ -108,13 +109,23 @@ public static JsonObject build(JsonObject lockJson, JsonObject packageJson,
}
if (dependencies != null) {
- dependencies.forEach((key, value) -> {
+ dependencies.forEach((k, value) -> {
+ String key = k;
final int indexOfNodeModule = key.lastIndexOf(NodePackageAnalyzer.NODE_MODULES_DIRNAME + "/");
if (indexOfNodeModule >= 0) {
key = key.substring(indexOfNodeModule + NodePackageAnalyzer.NODE_MODULES_DIRNAME.length() + 1);
}
- final JsonObject dep = ((JsonObject) value);
+ JsonObject dep = ((JsonObject) value);
+
+ //After Version 3, dependencies can't be taken directly from package-lock.json
+ if (lockJsonVersion > 2 && dep.containsKey("dependencies") && dep.get("dependencies") instanceof JsonObject) {
+ final JsonObjectBuilder depBuilder = Json.createObjectBuilder(dep);
+ depBuilder.remove("dependencies");
+ depBuilder.add("requires", dep.get("dependencies"));
+ dep = depBuilder.build();
+ }
+
final String version = dep.getString("version", "");
final boolean isDev = dep.getBoolean("dev", false);
if (skipDevDependencies && isDev) {
@@ -144,7 +155,7 @@ public static JsonObject build(JsonObject lockJson, JsonObject packageJson,
* @return the JSON payload for NPN Audit
*/
public static JsonObject build(JsonObject packageJson, MultiValuedMap dependencyMap,
- final boolean skipDevDependencies) {
+ final boolean skipDevDependencies) {
final JsonObjectBuilder payloadBuilder = Json.createObjectBuilder();
addProjectInfo(packageJson, payloadBuilder);
@@ -236,15 +247,23 @@ private static void addConstantElements(final JsonObjectBuilder payloadBuilder)
private static JsonObject buildDependencies(JsonObject dep, MultiValuedMap dependencyMap) {
final JsonObjectBuilder depBuilder = Json.createObjectBuilder();
Optional.ofNullable(dep.getJsonString("version"))
- .map(JsonString::getString)
- .ifPresent(version -> depBuilder.add("version", version));
+ .map(JsonString::getString)
+ .ifPresent(version -> depBuilder.add("version", version));
//not installed package (like, dependency of an optional dependency) doesn't contains integrity
if (dep.containsKey("integrity")) {
depBuilder.add("integrity", dep.getString("integrity"));
}
if (dep.containsKey("requires")) {
- depBuilder.add("requires", dep.getJsonObject("requires"));
+ final JsonObjectBuilder requiresBuilder = Json.createObjectBuilder();
+ dep.getJsonObject("requires").forEach((key, value) -> {
+ if (NodePackageAnalyzer.shouldSkipDependency(key, ((JsonString) value).getString())) {
+ return;
+ }
+
+ requiresBuilder.add(key, value);
+ });
+ depBuilder.add("requires", requiresBuilder.build());
}
if (dep.containsKey("dependencies")) {
final JsonObjectBuilder dependeciesBuilder = Json.createObjectBuilder();
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/CveEcosystemMapper.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/CveEcosystemMapper.java
index 8424707b425..f201ffddae7 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/CveEcosystemMapper.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/CveEcosystemMapper.java
@@ -13,18 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (c) 2020 The OWASP Foundation. All Rights Reserved.
+ * Copyright (c) 2023 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.nvd.ecosystem;
+import io.github.jeremylong.openvulnerability.client.nvd.Config;
+import io.github.jeremylong.openvulnerability.client.nvd.CpeMatch;
+import io.github.jeremylong.openvulnerability.client.nvd.Node;
+import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.concurrent.NotThreadSafe;
-import org.owasp.dependencycheck.data.nvd.json.CpeMatchStreamCollector;
-import org.owasp.dependencycheck.data.nvd.json.DefCpeMatch;
-
-import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
-import org.owasp.dependencycheck.data.nvd.json.NodeFlatteningCollector;
/**
* Utility for mapping CVEs to their ecosystems.
@@ -83,17 +82,23 @@ public String getEcosystem(DefCveItem cve) {
* null
*/
private boolean hasMultipleVendorProductConfigurations(DefCveItem cve) {
- final List cpeEntries = cve.getConfigurations().getNodes().stream()
- .collect(NodeFlatteningCollector.getInstance())
- .collect(CpeMatchStreamCollector.getInstance())
- .filter(defCpeMatch -> defCpeMatch.getCpe23Uri() != null)
- .collect(Collectors.toList());
- if (!cpeEntries.isEmpty() && cpeEntries.size() > 1) {
- final DefCpeMatch firstMatch = cpeEntries.get(0);
- final String uri = firstMatch.getCpe23Uri();
- final int pos = uri.indexOf(":", uri.indexOf(":", 10) + 1);
- final String match = uri.substring(0, pos + 1);
- return !cpeEntries.stream().allMatch(e -> e.getCpe23Uri().startsWith(match));
+ if (cve.getCve().getConfigurations() != null && !cve.getCve().getConfigurations().isEmpty()) {
+ final List cpeEntries = cve.getCve().getConfigurations().stream()
+ .filter(config -> config.getNodes() != null)
+ .map(Config::getNodes)
+ .flatMap(List::stream)
+ .filter(cpe -> cpe.getCpeMatch() != null)
+ .map(Node::getCpeMatch)
+ .flatMap(List::stream)
+ .filter(match -> match.getCriteria() != null)
+ .collect(Collectors.toList());
+ if (!cpeEntries.isEmpty() && cpeEntries.size() > 1) {
+ final CpeMatch firstMatch = cpeEntries.get(0);
+ final String uri = firstMatch.getCriteria();
+ final int pos = uri.indexOf(":", uri.indexOf(":", 10) + 1);
+ final String match = uri.substring(0, pos + 1);
+ return !cpeEntries.stream().allMatch(e -> e.getCriteria().startsWith(match));
+ }
}
return false;
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/DescriptionEcosystemMapper.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/DescriptionEcosystemMapper.java
index d4dae989047..1d325ec8bff 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/DescriptionEcosystemMapper.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/DescriptionEcosystemMapper.java
@@ -18,7 +18,7 @@
package org.owasp.dependencycheck.data.nvd.ecosystem;
import org.apache.commons.lang3.StringUtils;
-import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
+import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
import java.util.HashMap;
import java.util.Map;
@@ -179,7 +179,7 @@ protected void increment(int i, int[] ecosystemMap) {
*/
public String getEcosystem(DefCveItem cve) {
final int[] ecosystemMap = new int[ECOSYSTEMS.length];
- cve.getCve().getDescription().getDescriptionData().stream()
+ cve.getCve().getDescriptions().stream()
.filter((langString) -> (langString.getLang().equals("en")))
.forEachOrdered((langString) -> search(langString.getValue(), ecosystemMap));
return getResult(ecosystemMap);
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/UrlEcosystemMapper.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/UrlEcosystemMapper.java
index 8721ed54b1c..bd48613e95f 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/UrlEcosystemMapper.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvd/ecosystem/UrlEcosystemMapper.java
@@ -23,13 +23,13 @@
import javax.annotation.concurrent.NotThreadSafe;
-import org.owasp.dependencycheck.data.nvd.json.CVEJSON40Min11;
-import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
-import org.owasp.dependencycheck.data.nvd.json.Reference;
-import org.owasp.dependencycheck.data.nvd.json.References;
+import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
+import io.github.jeremylong.openvulnerability.client.nvd.Reference;
import com.hankcs.algorithm.AhoCorasickDoubleArrayTrie;
import com.hankcs.algorithm.AhoCorasickDoubleArrayTrie.Hit;
+import io.github.jeremylong.openvulnerability.client.nvd.CveItem;
+import java.util.List;
@NotThreadSafe
public class UrlEcosystemMapper {
@@ -69,14 +69,13 @@ public UrlEcosystemMapper() {
* @return the ecosystem
*/
public String getEcosystem(DefCveItem cve) {
- final References references = Optional.ofNullable(cve)
+ final List references = Optional.ofNullable(cve)
.map(DefCveItem::getCve)
- .map(CVEJSON40Min11::getReferences)
+ .map(CveItem::getReferences)
.orElse(null);
if (Objects.nonNull(references)) {
- for (Reference r : references.getReferenceData()) {
-
+ for (Reference r : references) {
final Hit ecosystem = search.findFirst(r.getUrl());
if (ecosystem != null) {
return ecosystem.value;
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/CpeMatchStreamCollector.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/CpeMatchStreamCollector.java
deleted file mode 100644
index 652e45a2ef2..00000000000
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/CpeMatchStreamCollector.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * This file is part of dependency-check-core.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (c) 2018 Jeremy Long. All Rights Reserved.
- */
-package org.owasp.dependencycheck.data.nvd.json;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.BinaryOperator;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collector;
-import java.util.stream.Stream;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- *
- * @author Jeremy Long
- *
- */
-@ThreadSafe
-public final class CpeMatchStreamCollector implements Collector, Stream> {
-
- /**
- * The singleton instance.
- */
- private static final CpeMatchStreamCollector INSTANCE;
-
- static {
- INSTANCE = new CpeMatchStreamCollector();
- }
-
- public static CpeMatchStreamCollector getInstance() {
- return INSTANCE;
- }
-
- private CpeMatchStreamCollector() {
- }
-
- @Override
- public Supplier> supplier() {
- return ArrayList::new;
- }
-
- @Override
- public BiConsumer, DefNode> accumulator() {
- return (match, nodes) -> match.addAll(nodes.getCpeMatch());
- }
-
- @Override
- public BinaryOperator> combiner() {
- return (map, other) -> {
- map.addAll(other);
- return map;
- };
- }
-
- @Override
- public Function, Stream> finisher() {
- return Collection::stream;
- }
-
- @Override
- public Set characteristics() {
- return EnumSet.of(Characteristics.UNORDERED);
- }
-
-}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/MetaProperties.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/MetaProperties.java
deleted file mode 100644
index 322ba5c02da..00000000000
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/MetaProperties.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * This file is part of dependency-check-core.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (c) 2019 Jeremy Long. All Rights Reserved.
- */
-package org.owasp.dependencycheck.data.nvd.json;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.util.Properties;
-import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
-
-/**
- * Meta properties object to hold information about the NVD CVE data.
- *
- * @author Jeremy Long
- */
-public class MetaProperties {
-
- /**
- * The SHA256 of the NVD file.
- */
- private final String sha256;
- /**
- * The last modified date of the NVD file in epoch time.
- */
- private final long lastModifiedDate;
- /**
- * The size of the NVD file.
- */
- private final long size;
- /**
- * The size of the zipped NVD file.
- */
- private final long zipSize;
- /**
- * The size of the gzipped NVD file.
- */
- private final long gzSize;
-
- /**
- * Get the value of gzSize.
- *
- * @return the value of gzSize
- */
- public long getGzSize() {
- return gzSize;
- }
-
- /**
- * Get the value of zipSize.
- *
- * @return the value of zipSize
- */
- public long getZipSize() {
- return zipSize;
- }
-
- /**
- * Get the value of size.
- *
- * @return the value of size
- */
- public long getSize() {
- return size;
- }
-
- /**
- * Get the value of lastModifiedDate in epoch time.
- *
- * @return the value of lastModifiedDate
- */
- public long getLastModifiedDate() {
- return lastModifiedDate;
- }
-
- /**
- * Get the value of SHA256.
- *
- * @return the value of SHA256
- */
- public String getSha256() {
- return sha256;
- }
-
- /**
- * Constructs a new MetaProperties object to hold information about the NVD
- * data.
- *
- * @param contents the contents of the meta file
- * @throws InvalidDataException thrown if the meta file contents cannot be
- * parsed
- */
- public MetaProperties(String contents) throws InvalidDataException {
- final Properties properties = new Properties();
- try (Reader r = new StringReader(contents)) {
- properties.load(r);
- } catch (IOException ex) {
- throw new InvalidDataException("Unable to parse meta file data", ex);
- }
- this.sha256 = properties.getProperty("sha256");
- try {
- final String date = properties.getProperty("lastModifiedDate");
- if (date == null) {
- throw new InvalidDataException("lastModifiedDate not found in meta file");
- }
- this.lastModifiedDate = ZonedDateTime.parse(date, DateTimeFormatter.ISO_OFFSET_DATE_TIME).toEpochSecond();
- } catch (DateTimeParseException ex) {
- throw new InvalidDataException("Meta file lastModifiedDate cannot be parsed: "
- + properties.getProperty("lastModifiedDate"), ex);
- }
- try {
- this.zipSize = Long.parseLong(properties.getProperty("zipSize"));
- } catch (NumberFormatException ex) {
- throw new InvalidDataException("Meta file zip size cannot be parsed: "
- + properties.getProperty("zipSize"), ex);
- }
- try {
- this.gzSize = Long.parseLong(properties.getProperty("gzSize"));
- } catch (NumberFormatException ex) {
- throw new InvalidDataException("Meta file gz size cannot be parsed: "
- + properties.getProperty("gzSize"), ex);
- }
- try {
- this.size = Long.parseLong(properties.getProperty("size"));
- } catch (NumberFormatException ex) {
- throw new InvalidDataException("Meta file size cannot be parsed: "
- + properties.getProperty("size"), ex);
- }
- }
-}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/NodeFlatteningCollector.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/NodeFlatteningCollector.java
deleted file mode 100644
index 7dfe7e291ff..00000000000
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/NodeFlatteningCollector.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * This file is part of dependency-check-core.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (c) 2018 Jeremy Long. All Rights Reserved.
- */
-package org.owasp.dependencycheck.data.nvd.json;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.BinaryOperator;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collector;
-import java.util.stream.Stream;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Used to flatten a hierarchical list of nodes with children.
- *
- * @author Jeremy Long
- */
-@ThreadSafe
-public final class NodeFlatteningCollector implements Collector, Stream> {
-
- /**
- * Singleton instance variable.
- */
- private static final NodeFlatteningCollector INSTANCE;
-
- static {
- INSTANCE = new NodeFlatteningCollector();
- }
-
- public static NodeFlatteningCollector getInstance() {
- return INSTANCE;
- }
-
- private NodeFlatteningCollector() {
- }
-
- /**
- * Flattens the hierarchical list of nodes.
- *
- * @param node the node with children to flatten
- * @return the flattened list of nodes
- */
- private List flatten(DefNode node) {
- final List result = new ArrayList<>();
- result.add(node);
- return flatten(result, node.getChildren());
- }
-
- /**
- * Flattens the hierarchical list of nodes.
- *
- * @param result the results
- * @param nodes the nodes
- * @return the flattened list of nodes
- */
- private List flatten(List result, List nodes) {
- nodes.forEach(n -> {
- flatten(result, n.getChildren());
- result.add(n);
- });
- return result;
- }
-
- @Override
- public Supplier> supplier() {
- return ArrayList::new;
- }
-
- @Override
- public BiConsumer, DefNode> accumulator() {
- return (nodes, n) -> nodes.addAll(flatten(n));
- }
-
- @Override
- public BinaryOperator> combiner() {
- return (map, other) -> {
- map.addAll(other);
- return map;
- };
- }
-
- @Override
- public Function, Stream> finisher() {
- return Collection::stream;
- }
-
- @Override
- public Set characteristics() {
- return EnumSet.of(Characteristics.UNORDERED);
- }
-}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/package-info.java b/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/package-info.java
deleted file mode 100644
index cd090a6f6c0..00000000000
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvd/json/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Contains utility classes used to work with the generated code from the
- * NVD CVE JSON data.
- */
-package org.owasp.dependencycheck.data.nvd.json;
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
index 752597623ef..1e4b64baff1 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java
@@ -20,7 +20,9 @@
import com.google.common.io.Resources;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import org.apache.commons.collections.map.ReferenceMap;
+import io.github.jeremylong.openvulnerability.client.nvd.Config;
+import io.github.jeremylong.openvulnerability.client.nvd.CpeMatch;
+import org.apache.commons.collections4.map.ReferenceMap;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.*;
@@ -42,24 +44,24 @@
import java.util.stream.Collectors;
import org.anarres.jdiagnostics.DefaultQuery;
-import static org.apache.commons.collections.map.AbstractReferenceMap.HARD;
-import static org.apache.commons.collections.map.AbstractReferenceMap.SOFT;
+import static org.apache.commons.collections4.map.AbstractReferenceMap.ReferenceStrength.HARD;
+import static org.apache.commons.collections4.map.AbstractReferenceMap.ReferenceStrength.SOFT;
import org.owasp.dependencycheck.analyzer.exception.LambdaExceptionWrapper;
import org.owasp.dependencycheck.analyzer.exception.UnexpectedAnalysisException;
-import org.owasp.dependencycheck.data.nvd.json.BaseMetricV2;
-import org.owasp.dependencycheck.data.nvd.json.BaseMetricV3;
-import org.owasp.dependencycheck.data.nvd.json.CpeMatchStreamCollector;
-import org.owasp.dependencycheck.data.nvd.json.DefCpeMatch;
-import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
-import org.owasp.dependencycheck.data.nvd.json.LangString;
-import org.owasp.dependencycheck.data.nvd.json.NodeFlatteningCollector;
-import org.owasp.dependencycheck.data.nvd.json.ProblemtypeDatum;
-import org.owasp.dependencycheck.data.nvd.json.Reference;
+import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
import org.owasp.dependencycheck.data.update.cpe.CpeEcosystemCache;
import org.owasp.dependencycheck.data.update.cpe.CpePlus;
-import org.owasp.dependencycheck.dependency.CvssV2;
-import org.owasp.dependencycheck.dependency.CvssV3;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV2;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV2Data;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV3;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV3Data;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV4;
+import io.github.jeremylong.openvulnerability.client.nvd.CvssV4Data;
+import io.github.jeremylong.openvulnerability.client.nvd.LangString;
+import io.github.jeremylong.openvulnerability.client.nvd.Node;
+import io.github.jeremylong.openvulnerability.client.nvd.Reference;
+import io.github.jeremylong.openvulnerability.client.nvd.Weakness;
import org.owasp.dependencycheck.dependency.VulnerableSoftwareBuilder;
import us.springett.parsers.cpe.Cpe;
import us.springett.parsers.cpe.CpeBuilder;
@@ -143,8 +145,7 @@ public int updateEcosystemCache() {
final URL url = Resources.getResource(DB_ECOSYSTEM_CACHE);
final List sql = Resources.readLines(url, StandardCharsets.UTF_8);
- try (Connection conn = databaseManager.getConnection();
- Statement statement = conn.createStatement()) {
+ try (Connection conn = databaseManager.getConnection(); Statement statement = conn.createStatement()) {
for (String single : sql) {
updateCount += statement.executeUpdate(single);
}
@@ -461,8 +462,7 @@ DatabaseProperties reloadProperties() {
*/
public Set getCPEs(String vendor, String product) {
final Set cpe = new HashSet<>();
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement ps = getPreparedStatement(conn, SELECT_CPE_ENTRIES)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, SELECT_CPE_ENTRIES)) {
//part, vendor, product, version, update_version, edition,
//lang, sw_edition, target_sw, target_hw, other, ecosystem
ps.setString(1, vendor);
@@ -567,8 +567,7 @@ public Properties getProperties() {
*/
public void saveProperty(String key, String value) {
clearCache();
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement mergeProperty = getPreparedStatement(conn, MERGE_PROPERTY)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement mergeProperty = getPreparedStatement(conn, MERGE_PROPERTY)) {
if (mergeProperty != null) {
mergeProperty.setString(1, key);
mergeProperty.setString(2, value);
@@ -623,8 +622,7 @@ public List getVulnerabilities(Cpe cpe) throws DatabaseException
}
final List vulnerabilities = new ArrayList<>();
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement ps = getPreparedStatement(conn, SELECT_CVE_FROM_SOFTWARE)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, SELECT_CVE_FROM_SOFTWARE)) {
ps.setString(1, cpe.getVendor());
ps.setString(2, cpe.getProduct());
try (ResultSet rs = ps.executeQuery()) {
@@ -714,8 +712,7 @@ public Vulnerability getVulnerability(String cve, Connection conn) throws Databa
final VulnerableSoftwareBuilder vulnerableSoftwareBuilder = new VulnerableSoftwareBuilder();
Vulnerability vuln = null;
try {
- try (PreparedStatement psV = getPreparedStatement(conn, SELECT_VULNERABILITY, cve);
- ResultSet rsV = psV.executeQuery()) {
+ try (PreparedStatement psV = getPreparedStatement(conn, SELECT_VULNERABILITY, cve); ResultSet rsV = psV.executeQuery()) {
if (rsV.next()) {
//1.id, 2.description,
cveId = rsV.getInt(1);
@@ -729,44 +726,320 @@ public Vulnerability getVulnerability(String cve, Connection conn) throws Databa
//12.v2AccessVector, 13.v2AccessComplexity, 14.v2Authentication, 15.v2ConfidentialityImpact,
//16.v2IntegrityImpact, 17.v2AvailabilityImpact, 18.v2Version,
if (rsV.getObject(11) != null) {
- final CvssV2 cvss = new CvssV2(rsV.getFloat(11), rsV.getString(12),
- rsV.getString(13), rsV.getString(14), rsV.getString(15),
- rsV.getString(16), rsV.getString(17), rsV.getString(3),
- getFloatValue(rsV, 4), getFloatValue(rsV, 5),
- getBooleanValue(rsV, 6), getBooleanValue(rsV, 7), getBooleanValue(rsV, 8),
- getBooleanValue(rsV, 9), getBooleanValue(rsV, 10), rsV.getString(18));
+
+ final CvssV2Data.AccessVectorType accessVector = CvssV2Data.AccessVectorType.fromValue(rsV.getString(12));
+ final CvssV2Data.AccessComplexityType accessComplexity = CvssV2Data.AccessComplexityType.fromValue(rsV.getString(13));
+ final CvssV2Data.AuthenticationType authentication = CvssV2Data.AuthenticationType.fromValue(rsV.getString(14));
+ final CvssV2Data.CiaType confidentialityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(15));
+ final CvssV2Data.CiaType integrityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(16));
+ final CvssV2Data.CiaType availabilityImpact = CvssV2Data.CiaType.fromValue(rsV.getString(17));
+ final String vector = String.format("/AV:%s/AC:%s/Au:%s/C:%s/I:%s/A:%s",
+ accessVector == null ? "" : accessVector.value().substring(0, 1),
+ accessComplexity == null ? "" : accessComplexity.value().substring(0, 1),
+ authentication == null ? "" : authentication.value().substring(0, 1),
+ confidentialityImpact == null ? "" : confidentialityImpact.value().substring(0, 1),
+ integrityImpact == null ? "" : integrityImpact.value().substring(0, 1),
+ availabilityImpact == null ? "" : availabilityImpact.value().substring(0, 1));
+
+ final CvssV2Data cvssData = new CvssV2Data(CvssV2Data.Version._2_0, vector, accessVector,
+ accessComplexity, authentication, confidentialityImpact,
+ integrityImpact, availabilityImpact, rsV.getDouble(11), rsV.getString(3),
+ null, null, null, null, null, null, null, null, null, null);
+ final CvssV2 cvss = new CvssV2(null, CvssV2.Type.PRIMARY, cvssData, rsV.getString(3),
+ rsV.getDouble(4), rsV.getDouble(5), rsV.getBoolean(6), rsV.getBoolean(7),
+ rsV.getBoolean(8), rsV.getBoolean(9), rsV.getBoolean(10));
vuln.setCvssV2(cvss);
}
//19.v3ExploitabilityScore, 20.v3ImpactScore, 21.v3AttackVector, 22.v3AttackComplexity, 23.v3PrivilegesRequired,
//24.v3UserInteraction, 25.v3Scope, 26.v3ConfidentialityImpact, 27.v3IntegrityImpact, 28.v3AvailabilityImpact,
- //29.v3BaseScore, 30.v3BaseSeverity, 21.v3Version
+ //29.v3BaseScore, 30.v3BaseSeverity, 31.v3Version
if (rsV.getObject(21) != null) {
- final CvssV3 cvss = new CvssV3(rsV.getString(21), rsV.getString(22),
- rsV.getString(23), rsV.getString(24), rsV.getString(25),
- rsV.getString(26), rsV.getString(27), rsV.getString(28),
- rsV.getFloat(29), rsV.getString(30), getFloatValue(rsV, 19),
- getFloatValue(rsV, 20), rsV.getString(31));
+ //some older test data may not correctly have the version set.
+ String cveVersion = "3.1";
+ if (rsV.getString(31) != null) {
+ cveVersion = rsV.getString(31);
+ }
+ final CvssV3Data.Version version = CvssV3Data.Version.fromValue(cveVersion);
+ final CvssV3Data.AttackVectorType attackVector = CvssV3Data.AttackVectorType.fromValue(rsV.getString(21));
+ final CvssV3Data.AttackComplexityType attackComplexity = CvssV3Data.AttackComplexityType.fromValue(rsV.getString(22));
+ final CvssV3Data.PrivilegesRequiredType privilegesRequired = CvssV3Data.PrivilegesRequiredType.fromValue(rsV.getString(23));
+ final CvssV3Data.UserInteractionType userInteraction = CvssV3Data.UserInteractionType.fromValue(rsV.getString(24));
+ final CvssV3Data.ScopeType scope = CvssV3Data.ScopeType.fromValue(rsV.getString(25));
+ final CvssV3Data.CiaType confidentialityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(26));
+ final CvssV3Data.CiaType integrityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(27));
+ final CvssV3Data.CiaType availabilityImpact = CvssV3Data.CiaType.fromValue(rsV.getString(28));
+ final CvssV3Data.SeverityType baseSeverity = CvssV3Data.SeverityType.fromValue(rsV.getString(30));
+ final String vector = String.format("CVSS:%s/AV:%s/AC:%s/PR:%s/UI:%s/S:%s/C:%s/I:%s/A:%s",
+ version == null ? "" : version,
+ attackVector == null ? "" : attackVector.value().substring(0, 1),
+ attackComplexity == null ? "" : attackComplexity.value().substring(0, 1),
+ privilegesRequired == null ? "" : privilegesRequired.value().substring(0, 1),
+ userInteraction == null ? "" : userInteraction.value().substring(0, 1),
+ scope == null ? "" : scope.value().substring(0, 1),
+ confidentialityImpact == null ? "" : confidentialityImpact.value().substring(0, 1),
+ integrityImpact == null ? "" : integrityImpact.value().substring(0, 1),
+ availabilityImpact == null ? "" : availabilityImpact.value().substring(0, 1));
+
+ final CvssV3Data cvssData = new CvssV3Data(version, vector, attackVector, attackComplexity, privilegesRequired,
+ userInteraction, scope, confidentialityImpact, integrityImpact, availabilityImpact,
+ rsV.getDouble(29), baseSeverity, CvssV3Data.ExploitCodeMaturityType.PROOF_OF_CONCEPT,
+ CvssV3Data.RemediationLevelType.NOT_DEFINED, CvssV3Data.ConfidenceType.REASONABLE, 0.0,
+ CvssV3Data.SeverityType.MEDIUM, CvssV3Data.CiaRequirementType.NOT_DEFINED,
+ CvssV3Data.CiaRequirementType.NOT_DEFINED, CvssV3Data.CiaRequirementType.NOT_DEFINED,
+ CvssV3Data.ModifiedAttackVectorType.ADJACENT_NETWORK, CvssV3Data.ModifiedAttackComplexityType.NOT_DEFINED,
+ CvssV3Data.ModifiedPrivilegesRequiredType.NOT_DEFINED, CvssV3Data.ModifiedUserInteractionType.NOT_DEFINED,
+ CvssV3Data.ModifiedScopeType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED,
+ CvssV3Data.ModifiedCiaType.NOT_DEFINED, CvssV3Data.ModifiedCiaType.NOT_DEFINED, 1.0,
+ CvssV3Data.SeverityType.NONE);
+ final CvssV3 cvss = new CvssV3(null, null, cvssData, rsV.getDouble(19), rsV.getDouble(20));
vuln.setCvssV3(cvss);
}
+// 32.v4version, 33.v4attackVector, 34.v4attackComplexity, 35.v4attackRequirements, 36.v4privilegesRequired,
+// 37.v4userInteraction, 38.v4vulnConfidentialityImpact, 39.v4vulnIntegrityImpact, 40.v4vulnAvailabilityImpact,
+// 41.v4subConfidentialityImpact, 42.v4subIntegrityImpact, 43.v4subAvailabilityImpact, 44.v4exploitMaturity,
+// 45.v4confidentialityRequirement, 46.v4integrityRequirement, 47.v4availabilityRequirement, 48.v4modifiedAttackVector,
+// 49.v4modifiedAttackComplexity, 50.v4modifiedAttackRequirements, 51.v4modifiedPrivilegesRequired, 52.v4modifiedUserInteraction,
+// 53.v4modifiedVulnConfidentialityImpact, 54.v4modifiedVulnIntegrityImpact, 55.v4modifiedVulnAvailabilityImpact,
+// 56.v4modifiedSubConfidentialityImpact, 57.v4modifiedSubIntegrityImpact, 58.v4modifiedSubAvailabilityImpact,
+// 59.v4safety, 60.v4automatable, 61.v4recovery, 62.v4valueDensity, 63.v4vulnerabilityResponseEffort, 64.v4providerUrgency,
+// 65.v4baseScore, 66.v4baseSeverity, 67.v4threatScore, 68.v4threatSeverity, 69.v4environmentalScore, 70.v4environmentalSeverity
+// 71.v4source, 72.v4type
+ if (rsV.getObject(33) != null) {
+ String vectorString = null;
+
+ String value = rsV.getString(32);
+ final CvssV4Data.Version version = CvssV4Data.Version.fromValue(value);
+ CvssV4Data.AttackVectorType attackVector = null;
+ value = rsV.getString(33);
+ if (value != null) {
+ attackVector = CvssV4Data.AttackVectorType.fromValue(value);
+ }
+ CvssV4Data.AttackComplexityType attackComplexity = null;
+ value = rsV.getString(34);
+ if (value != null) {
+ attackComplexity = CvssV4Data.AttackComplexityType.fromValue(value);
+ }
+ CvssV4Data.AttackRequirementsType attackRequirements = null;
+ value = rsV.getString(35);
+ if (value != null) {
+ attackRequirements = CvssV4Data.AttackRequirementsType.fromValue(value);
+ }
+ CvssV4Data.PrivilegesRequiredType privilegesRequired = null;
+ value = rsV.getString(36);
+ if (value != null) {
+ privilegesRequired = CvssV4Data.PrivilegesRequiredType.fromValue(value);
+ }
+ CvssV4Data.UserInteractionType userInteraction = null;
+ value = rsV.getString(37);
+ if (value != null) {
+ userInteraction = CvssV4Data.UserInteractionType.fromValue(value);
+ }
+ CvssV4Data.CiaType vulnConfidentialityImpact = null;
+ value = rsV.getString(38);
+ if (value != null) {
+ vulnConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.CiaType vulnIntegrityImpact = null;
+ value = rsV.getString(39);
+ if (value != null) {
+ vulnIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.CiaType vulnAvailabilityImpact = null;
+ value = rsV.getString(40);
+ if (value != null) {
+ vulnAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.CiaType subConfidentialityImpact = null;
+ value = rsV.getString(41);
+ if (value != null) {
+ subConfidentialityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.CiaType subIntegrityImpact = null;
+ value = rsV.getString(42);
+ if (value != null) {
+ subIntegrityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.CiaType subAvailabilityImpact = null;
+ value = rsV.getString(43);
+ if (value != null) {
+ subAvailabilityImpact = CvssV4Data.CiaType.fromValue(value);
+ }
+ CvssV4Data.ExploitMaturityType exploitMaturity = null;
+ value = rsV.getString(44);
+ if (value != null) {
+ exploitMaturity = CvssV4Data.ExploitMaturityType.fromValue(value);
+ }
+ CvssV4Data.CiaRequirementType confidentialityRequirement = null;
+ value = rsV.getString(45);
+ if (value != null) {
+ confidentialityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
+ }
+ CvssV4Data.CiaRequirementType integrityRequirement = null;
+ value = rsV.getString(46);
+ if (value != null) {
+ integrityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
+ }
+ CvssV4Data.CiaRequirementType availabilityRequirement = null;
+ value = rsV.getString(47);
+ if (value != null) {
+ availabilityRequirement = CvssV4Data.CiaRequirementType.fromValue(value);
+ }
+ CvssV4Data.ModifiedAttackVectorType modifiedAttackVector = null;
+ value = rsV.getString(48);
+ if (value != null) {
+ modifiedAttackVector = CvssV4Data.ModifiedAttackVectorType.fromValue(value);
+ }
+ CvssV4Data.ModifiedAttackComplexityType modifiedAttackComplexity = null;
+ value = rsV.getString(49);
+ if (value != null) {
+ modifiedAttackComplexity = CvssV4Data.ModifiedAttackComplexityType.fromValue(value);
+ }
+ CvssV4Data.ModifiedAttackRequirementsType modifiedAttackRequirements = null;
+ value = rsV.getString(50);
+ if (value != null) {
+ modifiedAttackRequirements = CvssV4Data.ModifiedAttackRequirementsType.fromValue(value);
+ }
+ CvssV4Data.ModifiedPrivilegesRequiredType modifiedPrivilegesRequired = null;
+ value = rsV.getString(51);
+ if (value != null) {
+ modifiedPrivilegesRequired = CvssV4Data.ModifiedPrivilegesRequiredType.fromValue(value);
+ }
+ CvssV4Data.ModifiedUserInteractionType modifiedUserInteraction = null;
+ value = rsV.getString(52);
+ if (value != null) {
+ modifiedUserInteraction = CvssV4Data.ModifiedUserInteractionType.fromValue(value);
+ }
+ CvssV4Data.ModifiedCiaType modifiedVulnConfidentialityImpact = null;
+ value = rsV.getString(53);
+ if (value != null) {
+ modifiedVulnConfidentialityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
+ }
+ CvssV4Data.ModifiedCiaType modifiedVulnIntegrityImpact = null;
+ value = rsV.getString(54);
+ if (value != null) {
+ modifiedVulnIntegrityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
+ }
+ CvssV4Data.ModifiedCiaType modifiedVulnAvailabilityImpact = null;
+ value = rsV.getString(55);
+ if (value != null) {
+ modifiedVulnAvailabilityImpact = CvssV4Data.ModifiedCiaType.fromValue(value);
+ }
+ CvssV4Data.ModifiedSubCType modifiedSubConfidentialityImpact = null;
+ value = rsV.getString(56);
+ if (value != null) {
+ modifiedSubConfidentialityImpact = CvssV4Data.ModifiedSubCType.fromValue(value);
+ }
+ CvssV4Data.ModifiedSubIaType modifiedSubIntegrityImpact = null;
+ value = rsV.getString(57);
+ if (value != null) {
+ modifiedSubIntegrityImpact = CvssV4Data.ModifiedSubIaType.fromValue(value);
+ }
+ CvssV4Data.ModifiedSubIaType modifiedSubAvailabilityImpact = null;
+ value = rsV.getString(58);
+ if (value != null) {
+ modifiedSubAvailabilityImpact = CvssV4Data.ModifiedSubIaType.fromValue(value);
+ }
+ CvssV4Data.SafetyType safety = null;
+ value = rsV.getString(59);
+ if (value != null) {
+ safety = CvssV4Data.SafetyType.fromValue(value);
+ }
+ CvssV4Data.AutomatableType automatable = null;
+ value = rsV.getString(60);
+ if (value != null) {
+ automatable = CvssV4Data.AutomatableType.fromValue(value);
+ }
+ CvssV4Data.RecoveryType recovery = null;
+ value = rsV.getString(61);
+ if (value != null) {
+ recovery = CvssV4Data.RecoveryType.fromValue(value);
+ }
+ CvssV4Data.ValueDensityType valueDensity = null;
+ value = rsV.getString(62);
+ if (value != null) {
+ valueDensity = CvssV4Data.ValueDensityType.fromValue(value);
+ }
+ CvssV4Data.VulnerabilityResponseEffortType vulnerabilityResponseEffort = null;
+ value = rsV.getString(63);
+ if (value != null) {
+ vulnerabilityResponseEffort = CvssV4Data.VulnerabilityResponseEffortType.fromValue(value);
+ }
+ CvssV4Data.ProviderUrgencyType providerUrgency = null;
+ value = rsV.getString(64);
+ if (value != null) {
+ providerUrgency = CvssV4Data.ProviderUrgencyType.fromValue(value);
+ }
+ Double baseScore = null;
+ if (rsV.getObject(65) != null) {
+ baseScore = rsV.getDouble(65);
+ }
+ CvssV4Data.SeverityType baseSeverity = null;
+ value = rsV.getString(66);
+ if (value != null) {
+ baseSeverity = CvssV4Data.SeverityType.fromValue(value);
+ }
+ Double threatScore = null;
+ if (rsV.getObject(67) != null) {
+ threatScore = rsV.getDouble(67);
+ }
+ CvssV4Data.SeverityType threatSeverity = null;
+ value = rsV.getString(68);
+ if (value != null) {
+ threatSeverity = CvssV4Data.SeverityType.fromValue(value);
+ }
+ Double environmentalScore = null;
+ if (rsV.getObject(69) != null) {
+ environmentalScore = rsV.getDouble(69);
+ }
+ CvssV4Data.SeverityType environmentalSeverity = null;
+ value = rsV.getString(70);
+ if (value != null) {
+ environmentalSeverity = CvssV4Data.SeverityType.fromValue(value);
+ }
+ //initializing data twice to get the vector string. I really should have designed the object better...
+ CvssV4Data data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
+ userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
+ subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
+ availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
+ modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
+ modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
+ modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
+ providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
+ vectorString = data.toString();
+ data = new CvssV4Data(version, vectorString, attackVector, attackComplexity, attackRequirements, privilegesRequired,
+ userInteraction, vulnConfidentialityImpact, vulnIntegrityImpact, vulnAvailabilityImpact, subConfidentialityImpact,
+ subIntegrityImpact, subAvailabilityImpact, exploitMaturity, confidentialityRequirement, integrityRequirement,
+ availabilityRequirement, modifiedAttackVector, modifiedAttackComplexity, modifiedAttackRequirements,
+ modifiedPrivilegesRequired, modifiedUserInteraction, modifiedVulnConfidentialityImpact, modifiedVulnIntegrityImpact,
+ modifiedVulnAvailabilityImpact, modifiedSubConfidentialityImpact, modifiedSubIntegrityImpact,
+ modifiedSubAvailabilityImpact, safety, automatable, recovery, valueDensity, vulnerabilityResponseEffort,
+ providerUrgency, baseScore, baseSeverity, threatScore, threatSeverity, environmentalScore, environmentalSeverity);
+
+ final String source = rsV.getString(71);
+ CvssV4.Type cvssType = null;
+ value = rsV.getString(72);
+ if (value != null) {
+ cvssType = CvssV4.Type.fromValue(value);
+ }
+ final CvssV4 cvssv4 = new CvssV4(source, cvssType, data);
+ vuln.setCvssV4(cvssv4);
+ }
} else {
LOGGER.debug(cve + " does not exist in the database");
return null;
}
}
- try (PreparedStatement psCWE = getPreparedStatement(conn, SELECT_VULNERABILITY_CWE, cveId);
- ResultSet rsC = psCWE.executeQuery()) {
+ try (PreparedStatement psCWE = getPreparedStatement(conn, SELECT_VULNERABILITY_CWE, cveId); ResultSet rsC = psCWE.executeQuery()) {
while (rsC.next()) {
vuln.addCwe(rsC.getString(1));
}
}
- try (PreparedStatement psR = getPreparedStatement(conn, SELECT_REFERENCES, cveId);
- ResultSet rsR = psR.executeQuery()) {
+ try (PreparedStatement psR = getPreparedStatement(conn, SELECT_REFERENCES, cveId); ResultSet rsR = psR.executeQuery()) {
while (rsR.next()) {
vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
}
}
- try (PreparedStatement psS = getPreparedStatement(conn, SELECT_SOFTWARE, cveId);
- ResultSet rsS = psS.executeQuery()) {
+ try (PreparedStatement psS = getPreparedStatement(conn, SELECT_SOFTWARE, cveId); ResultSet rsS = psS.executeQuery()) {
//1 part, 2 vendor, 3 product, 4 version, 5 update_version, 6 edition, 7 lang,
//8 sw_edition, 9 target_sw, 10 target_hw, 11 other, 12 versionEndExcluding,
//13 versionEndIncluding, 14 versionStartExcluding, 15 versionStartIncluding, 16 vulnerable
@@ -810,13 +1083,13 @@ public Vulnerability getVulnerability(String cve, Connection conn) throws Databa
*/
public void updateVulnerability(DefCveItem cve, String baseEcosystem) {
clearCache();
- final String cveId = cve.getCve().getCVEDataMeta().getId();
+ final String cveId = cve.getCve().getId();
try {
- final String description = cveItemConverter.extractDescription(cve);
- if (cveItemConverter.isRejected(description)) {
+ if (cve.getCve().getVulnStatus() != null && cve.getCve().getVulnStatus().toUpperCase().startsWith("REJECT")) {
deleteVulnerability(cveId);
} else {
if (cveItemConverter.testCveCpeStartWithFilter(cve)) {
+ final String description = cveItemConverter.extractDescription(cve);
final int vulnerabilityId = updateOrInsertVulnerability(cve, description);
updateVulnerabilityInsertCwe(vulnerabilityId, cve);
updateVulnerabilityInsertReferences(vulnerabilityId, cve);
@@ -825,15 +1098,14 @@ public void updateVulnerability(DefCveItem cve, String baseEcosystem) {
updateVulnerabilityInsertSoftware(vulnerabilityId, cveId, software, baseEcosystem);
}
}
-
} catch (SQLException ex) {
- final String msg = String.format("Error updating '%s'", cveId);
+ final String msg = String.format("Error updating '%s'; %s", cveId, ex.getMessage());
LOGGER.debug(msg, ex);
- throw new DatabaseException(msg, ex);
+ throw new DatabaseException(msg);
} catch (CpeValidationException ex) {
- final String msg = String.format("Error parsing CPE entry from '%s'", cveId);
+ final String msg = String.format("Error parsing CPE entry from '%s'; %s", cveId, ex.getMessage());
LOGGER.debug(msg, ex);
- throw new DatabaseException(msg, ex);
+ throw new DatabaseException(msg);
}
}
@@ -858,8 +1130,7 @@ private void loadCpeEcosystemCache() {
private void saveCpeEcosystemCache() {
final Map, String> map = CpeEcosystemCache.getChanged();
if (map != null && !map.isEmpty()) {
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement ps = getPreparedStatement(conn, MERGE_CPE_ECOSYSTEM)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, MERGE_CPE_ECOSYSTEM)) {
for (Map.Entry, String> entry : map.entrySet()) {
ps.setString(1, entry.getKey().getLeft());
ps.setString(2, entry.getKey().getRight());
@@ -894,8 +1165,7 @@ private int updateOrInsertVulnerability(DefCveItem cve, String description) {
loadCpeEcosystemCache();
}
final int vulnerabilityId;
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement callUpdate = getPreparedStatement(conn, UPDATE_VULNERABILITY)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement callUpdate = getPreparedStatement(conn, UPDATE_VULNERABILITY)) {
// String 1.cve, String 2.description, String 3.v2Severity, Float 4.v2ExploitabilityScore,
// Float 5.v2ImpactScore, Boolean 6.v2AcInsufInfo, Boolean 7.v2ObtainAllPrivilege,
// Boolean 8.v2ObtainUserPrivilege, Boolean 9.v2ObtainOtherPrivilege, Boolean 10.v2UserInteractionRequired,
@@ -906,88 +1176,213 @@ private int updateOrInsertVulnerability(DefCveItem cve, String description) {
// String 23.v3PrivilegesRequired, String 24.v3UserInteraction, String 25.v3Scope,
// String 26.v3ConfidentialityImpact, String 27.v3IntegrityImpact, String 28.v3AvailabilityImpact,
// Float 29.v3BaseScore, String 30.v3BaseSeverity, String 31.v3Version
- callUpdate.setString(1, cve.getCve().getCVEDataMeta().getId());
+// . String 32.v4version, String 33.v4attackVector, String 34.v4attackComplexity, String 35.v4attackRequirements,
+// String 36.v4privilegesRequired, String 37.v4userInteraction, String 38.v4vulnConfidentialityImpact,
+// String 39.v4vulnIntegrityImpact, String 40.v4vulnAvailabilityImpact, String 41.v4subConfidentialityImpact,
+// String 42.v4subIntegrityImpact, String 43.v4subAvailabilityImpact, String 44.v4exploitMaturity,
+// String 45.v4confidentialityRequirement, String 46.v4integrityRequirement, String 47.v4availabilityRequirement,
+// String 48.v4modifiedAttackVector, String 49.v4modifiedAttackComplexity, String 50.v4modifiedAttackRequirements,
+// String 51.v4modifiedPrivilegesRequired, String 52.v4modifiedUserInteraction, String 53.v4modifiedVulnConfidentialityImpact,
+// String 54.v4modifiedVulnIntegrityImpact, String 55.v4modifiedVulnAvailabilityImpact, String 56.v4modifiedSubConfidentialityImpact,
+// String 57.v4modifiedSubIntegrityImpact, String 58.v4modifiedSubAvailabilityImpact, String 59.v4safety,
+// String 60.v4automatable, String 61.v4recovery, String 62.v4valueDensity, String 63.v4vulnerabilityResponseEffort,
+// String 64.v4providerUrgency, Float 65.v4baseScore, String 66.v4baseSeverity, Float 67.v4threatScore,
+// String 68.v4threatSeverity, Float 69.v4environmentalScore, String 70.v4environmentalSeverity
+// . String 71.v4Source, String 72.v4type
+ callUpdate.setString(1, cve.getCve().getId());
callUpdate.setString(2, description);
- if (cve.getImpact().getBaseMetricV2() != null) {
- final BaseMetricV2 cvssv2 = cve.getImpact().getBaseMetricV2();
- Map props = cvssv2.getAdditionalProperties();
- callUpdate.setString(3, cvssv2.getSeverity());
- setFloatValue(callUpdate, 4, props, "exploitabilityScore");
- setFloatValue(callUpdate, 5, props, "impactScore");
- setBooleanValue(callUpdate, 6, props, "acInsufInfo");
- setBooleanValue(callUpdate, 7, props, "obtainAllPrivilege");
- setBooleanValue(callUpdate, 8, props, "obtainUserPrivilege");
- setBooleanValue(callUpdate, 9, props, "obtainOtherPrivilege");
- setBooleanValue(callUpdate, 10, props, "userInteractionRequired");
- callUpdate.setFloat(11, cvssv2.getCvssV2().getBaseScore().floatValue());
- callUpdate.setString(12, cvssv2.getCvssV2().getAccessVector().value());
- callUpdate.setString(13, cvssv2.getCvssV2().getAccessComplexity().value());
- callUpdate.setString(14, cvssv2.getCvssV2().getAuthentication().value());
- callUpdate.setString(15, cvssv2.getCvssV2().getConfidentialityImpact().value());
- callUpdate.setString(16, cvssv2.getCvssV2().getIntegrityImpact().value());
- callUpdate.setString(17, cvssv2.getCvssV2().getAvailabilityImpact().value());
- props = cvssv2.getCvssV2().getAdditionalProperties();
- setStringValue(callUpdate, 18, props, "version");
+ Optional optCvssv2 = null;
+ if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV2() != null) {
+ optCvssv2 = cve.getCve().getMetrics().getCvssMetricV2().stream().sorted(Comparator.comparing(CvssV2::getType)).findFirst();
+ }
+ if (optCvssv2 != null && optCvssv2.isPresent()) {
+ final CvssV2 cvssv2 = optCvssv2.get();
+ setUpdateColumn(callUpdate, 3, cvssv2.getBaseSeverity());
+ setUpdateColumn(callUpdate, 4, cvssv2.getExploitabilityScore());
+ setUpdateColumn(callUpdate, 5, cvssv2.getImpactScore());
+ setUpdateColumn(callUpdate, 6, cvssv2.getAcInsufInfo());
+ setUpdateColumn(callUpdate, 7, cvssv2.getObtainAllPrivilege());
+ setUpdateColumn(callUpdate, 8, cvssv2.getObtainUserPrivilege());
+ setUpdateColumn(callUpdate, 9, cvssv2.getObtainOtherPrivilege());
+ setUpdateColumn(callUpdate, 10, cvssv2.getUserInteractionRequired());
+ setUpdateColumn(callUpdate, 11, cvssv2.getCvssData().getBaseScore());
+ setUpdateColumn(callUpdate, 12, cvssv2.getCvssData().getAccessVector());
+ setUpdateColumn(callUpdate, 13, cvssv2.getCvssData().getAccessComplexity());
+ setUpdateColumn(callUpdate, 14, cvssv2.getCvssData().getAuthentication());
+ setUpdateColumn(callUpdate, 15, cvssv2.getCvssData().getConfidentialityImpact());
+ setUpdateColumn(callUpdate, 16, cvssv2.getCvssData().getIntegrityImpact());
+ setUpdateColumn(callUpdate, 17, cvssv2.getCvssData().getAvailabilityImpact());
+ setUpdateColumn(callUpdate, 18, cvssv2.getCvssData().getVersion());
+ } else {
+ callUpdate.setNull(3, java.sql.Types.VARCHAR);
+ callUpdate.setNull(4, java.sql.Types.DOUBLE);
+ callUpdate.setNull(5, java.sql.Types.DOUBLE);
+ callUpdate.setNull(6, java.sql.Types.VARCHAR);
+ //TODO this is may also be an issue for MS SQL, if an issue is created we'll just need
+ // to create an isMsSQL flag. See todo below in setUpdateColum
+ if (isOracle) {
+ callUpdate.setNull(7, java.sql.Types.BIT);
+ callUpdate.setNull(8, java.sql.Types.BIT);
+ callUpdate.setNull(9, java.sql.Types.BIT);
+ callUpdate.setNull(10, java.sql.Types.BIT);
+ } else {
+ callUpdate.setNull(7, java.sql.Types.BOOLEAN);
+ callUpdate.setNull(8, java.sql.Types.BOOLEAN);
+ callUpdate.setNull(9, java.sql.Types.BOOLEAN);
+ callUpdate.setNull(10, java.sql.Types.BOOLEAN);
+ }
+ callUpdate.setNull(11, java.sql.Types.DOUBLE);
+ callUpdate.setNull(12, java.sql.Types.VARCHAR);
+ callUpdate.setNull(13, java.sql.Types.VARCHAR);
+ callUpdate.setNull(14, java.sql.Types.VARCHAR);
+ callUpdate.setNull(15, java.sql.Types.VARCHAR);
+ callUpdate.setNull(16, java.sql.Types.VARCHAR);
+ callUpdate.setNull(17, java.sql.Types.VARCHAR);
+ callUpdate.setNull(18, java.sql.Types.VARCHAR);
+ }
+ Optional optCvssv30 = Optional.empty();
+ if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV30() != null) {
+ optCvssv30 = cve.getCve().getMetrics().getCvssMetricV30().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
+ }
+ Optional optCvssv31 = Optional.empty();
+ if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV31() != null) {
+ optCvssv31 = cve.getCve().getMetrics().getCvssMetricV31().stream().sorted(Comparator.comparing(CvssV3::getType)).findFirst();
+ }
+
+ CvssV3 cvssv3 = null;
+ if (optCvssv31.isPresent()) {
+ cvssv3 = optCvssv31.get();
+ } else if (optCvssv30.isPresent()) {
+ cvssv3 = optCvssv30.get();
+ }
+ if (cvssv3 != null) {
+ setUpdateColumn(callUpdate, 19, cvssv3.getExploitabilityScore());
+ setUpdateColumn(callUpdate, 20, cvssv3.getImpactScore());
+ setUpdateColumn(callUpdate, 21, cvssv3.getCvssData().getAttackVector());
+ setUpdateColumn(callUpdate, 22, cvssv3.getCvssData().getAttackComplexity());
+ setUpdateColumn(callUpdate, 23, cvssv3.getCvssData().getPrivilegesRequired());
+ setUpdateColumn(callUpdate, 24, cvssv3.getCvssData().getUserInteraction());
+ setUpdateColumn(callUpdate, 25, cvssv3.getCvssData().getScope());
+ setUpdateColumn(callUpdate, 26, cvssv3.getCvssData().getConfidentialityImpact());
+ setUpdateColumn(callUpdate, 27, cvssv3.getCvssData().getIntegrityImpact());
+ setUpdateColumn(callUpdate, 28, cvssv3.getCvssData().getAvailabilityImpact());
+ setUpdateColumn(callUpdate, 29, cvssv3.getCvssData().getBaseScore());
+ setUpdateColumn(callUpdate, 30, cvssv3.getCvssData().getBaseSeverity());
+ setUpdateColumn(callUpdate, 31, cvssv3.getCvssData().getVersion());
} else {
- callUpdate.setNull(3, java.sql.Types.NULL);
- callUpdate.setNull(4, java.sql.Types.NULL);
- callUpdate.setNull(5, java.sql.Types.NULL);
- callUpdate.setNull(6, java.sql.Types.NULL);
- callUpdate.setNull(7, java.sql.Types.NULL);
- callUpdate.setNull(8, java.sql.Types.NULL);
- callUpdate.setNull(9, java.sql.Types.NULL);
- callUpdate.setNull(10, java.sql.Types.NULL);
- callUpdate.setNull(11, java.sql.Types.NULL);
- callUpdate.setNull(12, java.sql.Types.NULL);
- callUpdate.setNull(13, java.sql.Types.NULL);
- callUpdate.setNull(14, java.sql.Types.NULL);
- callUpdate.setNull(15, java.sql.Types.NULL);
- callUpdate.setNull(16, java.sql.Types.NULL);
- callUpdate.setNull(17, java.sql.Types.NULL);
- callUpdate.setNull(18, java.sql.Types.NULL);
+ callUpdate.setNull(19, java.sql.Types.DOUBLE);
+ callUpdate.setNull(20, java.sql.Types.DOUBLE);
+ callUpdate.setNull(21, java.sql.Types.VARCHAR);
+ callUpdate.setNull(22, java.sql.Types.VARCHAR);
+ callUpdate.setNull(23, java.sql.Types.VARCHAR);
+ callUpdate.setNull(24, java.sql.Types.VARCHAR);
+ callUpdate.setNull(25, java.sql.Types.VARCHAR);
+ callUpdate.setNull(26, java.sql.Types.VARCHAR);
+ callUpdate.setNull(27, java.sql.Types.VARCHAR);
+ callUpdate.setNull(28, java.sql.Types.VARCHAR);
+ callUpdate.setNull(29, java.sql.Types.DOUBLE);
+ callUpdate.setNull(30, java.sql.Types.VARCHAR);
+ callUpdate.setNull(31, java.sql.Types.VARCHAR);
}
- if (cve.getImpact().getBaseMetricV3() != null) {
- final BaseMetricV3 cvssv3 = cve.getImpact().getBaseMetricV3();
- Map props = cvssv3.getAdditionalProperties();
- setFloatValue(callUpdate, 19, props, "exploitabilityScore");
- setFloatValue(callUpdate, 20, props, "impactScore");
-
- callUpdate.setString(21, cvssv3.getCvssV3().getAttackVector().value());
- callUpdate.setString(22, cvssv3.getCvssV3().getAttackComplexity().value());
- callUpdate.setString(23, cvssv3.getCvssV3().getPrivilegesRequired().value());
- callUpdate.setString(24, cvssv3.getCvssV3().getUserInteraction().value());
- callUpdate.setString(25, cvssv3.getCvssV3().getScope().value());
- callUpdate.setString(26, cvssv3.getCvssV3().getConfidentialityImpact().value());
- callUpdate.setString(27, cvssv3.getCvssV3().getIntegrityImpact().value());
- callUpdate.setString(28, cvssv3.getCvssV3().getAvailabilityImpact().value());
- callUpdate.setFloat(29, cvssv3.getCvssV3().getBaseScore().floatValue());
- callUpdate.setString(30, cvssv3.getCvssV3().getBaseSeverity().value());
-
- props = cvssv3.getCvssV3().getAdditionalProperties();
- setStringValue(callUpdate, 31, props, "version");
+
+ Optional optCvssv4 = null;
+ if (cve.getCve().getMetrics() != null && cve.getCve().getMetrics().getCvssMetricV40() != null) {
+ optCvssv4 = cve.getCve().getMetrics().getCvssMetricV40().stream().sorted(Comparator.comparing(CvssV4::getType)).findFirst();
+ }
+ if (optCvssv4 != null && optCvssv4.isPresent()) {
+ final CvssV4 cvssv4 = optCvssv4.get();
+ setUpdateColumn(callUpdate, 32, cvssv4.getCvssData().getVersion());
+ setUpdateColumn(callUpdate, 33, cvssv4.getCvssData().getAttackVector());
+ setUpdateColumn(callUpdate, 34, cvssv4.getCvssData().getAttackComplexity());
+ setUpdateColumn(callUpdate, 35, cvssv4.getCvssData().getAttackRequirements());
+ setUpdateColumn(callUpdate, 36, cvssv4.getCvssData().getPrivilegesRequired());
+ setUpdateColumn(callUpdate, 37, cvssv4.getCvssData().getUserInteraction());
+ setUpdateColumn(callUpdate, 38, cvssv4.getCvssData().getVulnConfidentialityImpact());
+ setUpdateColumn(callUpdate, 39, cvssv4.getCvssData().getVulnIntegrityImpact());
+ setUpdateColumn(callUpdate, 40, cvssv4.getCvssData().getVulnAvailabilityImpact());
+ setUpdateColumn(callUpdate, 41, cvssv4.getCvssData().getSubConfidentialityImpact());
+ setUpdateColumn(callUpdate, 42, cvssv4.getCvssData().getSubIntegrityImpact());
+ setUpdateColumn(callUpdate, 43, cvssv4.getCvssData().getSubAvailabilityImpact());
+ setUpdateColumn(callUpdate, 44, cvssv4.getCvssData().getExploitMaturity());
+ setUpdateColumn(callUpdate, 45, cvssv4.getCvssData().getConfidentialityRequirement());
+ setUpdateColumn(callUpdate, 46, cvssv4.getCvssData().getIntegrityRequirement());
+ setUpdateColumn(callUpdate, 47, cvssv4.getCvssData().getAvailabilityRequirement());
+ setUpdateColumn(callUpdate, 48, cvssv4.getCvssData().getModifiedAttackVector());
+ setUpdateColumn(callUpdate, 49, cvssv4.getCvssData().getModifiedAttackComplexity());
+ setUpdateColumn(callUpdate, 50, cvssv4.getCvssData().getModifiedAttackRequirements());
+ setUpdateColumn(callUpdate, 51, cvssv4.getCvssData().getModifiedPrivilegesRequired());
+ setUpdateColumn(callUpdate, 52, cvssv4.getCvssData().getModifiedUserInteraction());
+ setUpdateColumn(callUpdate, 53, cvssv4.getCvssData().getModifiedVulnConfidentialityImpact());
+ setUpdateColumn(callUpdate, 54, cvssv4.getCvssData().getModifiedVulnIntegrityImpact());
+ setUpdateColumn(callUpdate, 55, cvssv4.getCvssData().getModifiedVulnAvailabilityImpact());
+ setUpdateColumn(callUpdate, 56, cvssv4.getCvssData().getModifiedSubConfidentialityImpact());
+ setUpdateColumn(callUpdate, 57, cvssv4.getCvssData().getModifiedSubIntegrityImpact());
+ setUpdateColumn(callUpdate, 58, cvssv4.getCvssData().getModifiedSubAvailabilityImpact());
+ setUpdateColumn(callUpdate, 59, cvssv4.getCvssData().getSafety());
+ setUpdateColumn(callUpdate, 60, cvssv4.getCvssData().getAutomatable());
+ setUpdateColumn(callUpdate, 61, cvssv4.getCvssData().getRecovery());
+ setUpdateColumn(callUpdate, 62, cvssv4.getCvssData().getValueDensity());
+ setUpdateColumn(callUpdate, 63, cvssv4.getCvssData().getVulnerabilityResponseEffort());
+ setUpdateColumn(callUpdate, 64, cvssv4.getCvssData().getProviderUrgency());
+ setUpdateColumn(callUpdate, 65, cvssv4.getCvssData().getBaseScore());
+ setUpdateColumn(callUpdate, 66, cvssv4.getCvssData().getBaseSeverity());
+ setUpdateColumn(callUpdate, 67, cvssv4.getCvssData().getThreatScore());
+ setUpdateColumn(callUpdate, 68, cvssv4.getCvssData().getThreatSeverity());
+ setUpdateColumn(callUpdate, 69, cvssv4.getCvssData().getEnvironmentalScore());
+ setUpdateColumn(callUpdate, 70, cvssv4.getCvssData().getEnvironmentalSeverity());
+ setUpdateColumn(callUpdate, 71, cvssv4.getSource());
+ setUpdateColumn(callUpdate, 72, cvssv4.getType());
} else {
- callUpdate.setNull(19, java.sql.Types.NULL);
- callUpdate.setNull(20, java.sql.Types.NULL);
- callUpdate.setNull(21, java.sql.Types.NULL);
- callUpdate.setNull(22, java.sql.Types.NULL);
- callUpdate.setNull(23, java.sql.Types.NULL);
- callUpdate.setNull(24, java.sql.Types.NULL);
- callUpdate.setNull(25, java.sql.Types.NULL);
- callUpdate.setNull(26, java.sql.Types.NULL);
- callUpdate.setNull(27, java.sql.Types.NULL);
- callUpdate.setNull(28, java.sql.Types.NULL);
- callUpdate.setNull(29, java.sql.Types.NULL);
- callUpdate.setNull(30, java.sql.Types.NULL);
- callUpdate.setNull(31, java.sql.Types.NULL);
+ callUpdate.setNull(32, java.sql.Types.VARCHAR);
+ callUpdate.setNull(33, java.sql.Types.VARCHAR);
+ callUpdate.setNull(34, java.sql.Types.VARCHAR);
+ callUpdate.setNull(35, java.sql.Types.VARCHAR);
+ callUpdate.setNull(36, java.sql.Types.VARCHAR);
+ callUpdate.setNull(37, java.sql.Types.VARCHAR);
+ callUpdate.setNull(38, java.sql.Types.VARCHAR);
+ callUpdate.setNull(39, java.sql.Types.VARCHAR);
+ callUpdate.setNull(40, java.sql.Types.VARCHAR);
+ callUpdate.setNull(41, java.sql.Types.VARCHAR);
+ callUpdate.setNull(42, java.sql.Types.VARCHAR);
+ callUpdate.setNull(43, java.sql.Types.VARCHAR);
+ callUpdate.setNull(44, java.sql.Types.VARCHAR);
+ callUpdate.setNull(45, java.sql.Types.VARCHAR);
+ callUpdate.setNull(46, java.sql.Types.VARCHAR);
+ callUpdate.setNull(47, java.sql.Types.VARCHAR);
+ callUpdate.setNull(48, java.sql.Types.VARCHAR);
+ callUpdate.setNull(49, java.sql.Types.VARCHAR);
+ callUpdate.setNull(50, java.sql.Types.VARCHAR);
+ callUpdate.setNull(51, java.sql.Types.VARCHAR);
+ callUpdate.setNull(52, java.sql.Types.VARCHAR);
+ callUpdate.setNull(53, java.sql.Types.VARCHAR);
+ callUpdate.setNull(54, java.sql.Types.VARCHAR);
+ callUpdate.setNull(55, java.sql.Types.VARCHAR);
+ callUpdate.setNull(56, java.sql.Types.VARCHAR);
+ callUpdate.setNull(57, java.sql.Types.VARCHAR);
+ callUpdate.setNull(58, java.sql.Types.VARCHAR);
+ callUpdate.setNull(59, java.sql.Types.VARCHAR);
+ callUpdate.setNull(60, java.sql.Types.VARCHAR);
+ callUpdate.setNull(61, java.sql.Types.VARCHAR);
+ callUpdate.setNull(62, java.sql.Types.VARCHAR);
+ callUpdate.setNull(63, java.sql.Types.VARCHAR);
+ callUpdate.setNull(64, java.sql.Types.VARCHAR);
+ callUpdate.setNull(65, java.sql.Types.DOUBLE);
+ callUpdate.setNull(66, java.sql.Types.VARCHAR);
+ callUpdate.setNull(67, java.sql.Types.DOUBLE);
+ callUpdate.setNull(68, java.sql.Types.VARCHAR);
+ callUpdate.setNull(69, java.sql.Types.DOUBLE);
+ callUpdate.setNull(70, java.sql.Types.VARCHAR);
+ callUpdate.setNull(71, java.sql.Types.VARCHAR);
+ callUpdate.setNull(72, java.sql.Types.VARCHAR);
}
if (isOracle) {
try {
final CallableStatement cs = (CallableStatement) callUpdate;
- cs.registerOutParameter(32, JDBCType.INTEGER);
+ cs.registerOutParameter(73, JDBCType.INTEGER);
cs.executeUpdate();
- vulnerabilityId = cs.getInt(32);
+ vulnerabilityId = cs.getInt(73);
} catch (SQLException ex) {
- final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getCVEDataMeta().getId());
+ final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
throw new DatabaseException(msg, ex);
}
} else {
@@ -995,7 +1390,7 @@ private int updateOrInsertVulnerability(DefCveItem cve, String description) {
rs.next();
vulnerabilityId = rs.getInt(1);
} catch (SQLException ex) {
- final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getCVEDataMeta().getId());
+ final String msg = String.format("Unable to retrieve id for new vulnerability for '%s'", cve.getCve().getId());
throw new DatabaseException(msg, ex);
}
}
@@ -1013,22 +1408,24 @@ private int updateOrInsertVulnerability(DefCveItem cve, String description) {
* @throws SQLException thrown if there is an error inserting the data
*/
private void updateVulnerabilityInsertCwe(int vulnerabilityId, DefCveItem cve) throws SQLException {
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement insertCWE = getPreparedStatement(conn, INSERT_CWE, vulnerabilityId)) {
- for (ProblemtypeDatum datum : cve.getCve().getProblemtype().getProblemtypeData()) {
- for (LangString desc : datum.getDescription()) {
- if ("en".equals(desc.getLang())) {
- insertCWE.setString(2, desc.getValue());
- if (isBatchInsertEnabled()) {
- insertCWE.addBatch();
- } else {
- insertCWE.execute();
+ if (cve.getCve() != null && cve.getCve().getWeaknesses() != null) {
+ try (Connection conn = databaseManager.getConnection();
+ PreparedStatement insertCWE = getPreparedStatement(conn, INSERT_CWE, vulnerabilityId)) {
+ for (Weakness weakness : cve.getCve().getWeaknesses()) {
+ for (LangString desc : weakness.getDescription()) {
+ if ("en".equals(desc.getLang())) {
+ insertCWE.setString(2, desc.getValue());
+ if (isBatchInsertEnabled()) {
+ insertCWE.addBatch();
+ } else {
+ insertCWE.execute();
+ }
}
}
}
- }
- if (isBatchInsertEnabled()) {
- insertCWE.executeBatch();
+ if (isBatchInsertEnabled()) {
+ insertCWE.executeBatch();
+ }
}
}
}
@@ -1112,8 +1509,7 @@ public void updateKnownExploitedVulnerabilities(
private void updateVulnerabilityInsertSoftware(int vulnerabilityId, String cveId,
List software, String baseEcosystem)
throws DatabaseException, SQLException {
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement insertSoftware = getPreparedStatement(conn, INSERT_SOFTWARE)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement insertSoftware = getPreparedStatement(conn, INSERT_SOFTWARE)) {
for (VulnerableSoftware parsedCpe : software) {
insertSoftware.setInt(1, vulnerabilityId);
insertSoftware.setString(2, parsedCpe.getPart().getAbbreviation());
@@ -1167,14 +1563,29 @@ private void updateVulnerabilityInsertSoftware(int vulnerabilityId, String cveId
* @throws SQLException thrown if there is an error inserting the data
*/
private void updateVulnerabilityInsertReferences(int vulnerabilityId, DefCveItem cve) throws SQLException {
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement insertReference = getPreparedStatement(conn, INSERT_REFERENCE)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement insertReference = getPreparedStatement(conn, INSERT_REFERENCE)) {
if (cve.getCve().getReferences() != null) {
- for (Reference r : cve.getCve().getReferences().getReferenceData()) {
+ for (Reference r : cve.getCve().getReferences()) {
insertReference.setInt(1, vulnerabilityId);
- insertReference.setString(2, r.getName());
- insertReference.setString(3, r.getUrl());
- insertReference.setString(4, r.getRefsource());
+ String name = null;
+ if (r.getTags() != null) {
+ name = r.getTags().stream().sorted().collect(Collectors.joining(",")).toUpperCase().replaceAll("\\s", "_");
+ }
+ if (name != null) {
+ insertReference.setString(2, name);
+ } else {
+ insertReference.setNull(2, java.sql.Types.VARCHAR);
+ }
+ if (r.getUrl() != null && !r.getUrl().isEmpty()) {
+ insertReference.setString(3, r.getUrl());
+ } else {
+ insertReference.setNull(3, java.sql.Types.VARCHAR);
+ }
+ if (r.getSource() != null && !r.getSource().isEmpty()) {
+ insertReference.setString(4, r.getSource());
+ } else {
+ insertReference.setNull(4, java.sql.Types.VARCHAR);
+ }
if (isBatchInsertEnabled()) {
insertReference.addBatch();
} else {
@@ -1198,20 +1609,24 @@ private void updateVulnerabilityInsertReferences(int vulnerabilityId, DefCveItem
*/
private List parseCpes(DefCveItem cve) throws CpeValidationException {
final List software = new ArrayList<>();
- final List cpeEntries = cve.getConfigurations().getNodes().stream()
- .collect(NodeFlatteningCollector.getInstance())
- .collect(CpeMatchStreamCollector.getInstance())
- .filter(predicate -> predicate.getCpe23Uri() != null)
- .filter(predicate -> predicate.getCpe23Uri().startsWith(cpeStartsWithFilter))
+
+ final List cpeEntries = cve.getCve().getConfigurations().stream()
+ .filter(config -> config.getNodes() != null)
+ .map(Config::getNodes)
+ .flatMap(List::stream)
+ .map(Node::getCpeMatch)
+ .flatMap(List::stream)
+ .filter(predicate -> predicate.getCriteria() != null)
+ .filter(predicate -> predicate.getCriteria().startsWith(cpeStartsWithFilter))
//this single CPE entry causes nearly 100% FP - so filtering it at the source.
- .filter(entry -> !("CVE-2009-0754".equals(cve.getCve().getCVEDataMeta().getId())
- && "cpe:2.3:a:apache:apache:*:*:*:*:*:*:*:*".equals(entry.getCpe23Uri())))
+ .filter(entry -> !("CVE-2009-0754".equals(cve.getCve().getId())
+ && "cpe:2.3:a:apache:apache:*:*:*:*:*:*:*:*".equals(entry.getCriteria())))
.collect(Collectors.toList());
final VulnerableSoftwareBuilder builder = new VulnerableSoftwareBuilder();
try {
cpeEntries.forEach(entry -> {
- builder.cpe(parseCpe(entry, cve.getCve().getCVEDataMeta().getId()))
+ builder.cpe(parseCpe(entry, cve.getCve().getId()))
.versionEndExcluding(entry.getVersionEndExcluding())
.versionStartExcluding(entry.getVersionStartExcluding())
.versionEndIncluding(entry.getVersionEndIncluding())
@@ -1240,22 +1655,14 @@ private List parseCpes(DefCveItem cve) throws CpeValidationE
* @throws DatabaseException thrown if there is an error converting the
* CpeMatch into a CPE object
*/
- private Cpe parseCpe(DefCpeMatch cpe, String cveId) throws DatabaseException {
- Cpe parsedCpe;
+ private Cpe parseCpe(CpeMatch cpe, String cveId) throws DatabaseException {
+ final Cpe parsedCpe;
try {
//the replace is a hack as the NVD does not properly escape backslashes in their JSON
- parsedCpe = CpeParser.parse(cpe.getCpe23Uri(), true);
+ parsedCpe = CpeParser.parse(cpe.getCriteria(), true);
} catch (CpeParsingException ex) {
- LOGGER.debug("NVD (" + cveId + ") contain an invalid 2.3 CPE: " + cpe.getCpe23Uri());
- if (cpe.getCpe22Uri() != null && !cpe.getCpe22Uri().isEmpty()) {
- try {
- parsedCpe = CpeParser.parse(cpe.getCpe22Uri(), true);
- } catch (CpeParsingException ex2) {
- throw new DatabaseException("Unable to parse CPE: " + cpe.getCpe23Uri(), ex);
- }
- } else {
- throw new DatabaseException("Unable to parse CPE: " + cpe.getCpe23Uri(), ex);
- }
+ LOGGER.debug("NVD (" + cveId + ") contain an invalid 2.3 CPE: " + cpe.getCriteria());
+ throw new DatabaseException("Unable to parse CPE: " + cpe.getCriteria(), ex);
}
return parsedCpe;
}
@@ -1336,8 +1743,8 @@ public boolean dataExists() {
}
LOGGER.error("Unable to access the local database.\n\nEnsure that '{}' is a writable directory. "
+ "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
- + "create a log file (see documentation at https://jeremylong.github.io/DependencyCheck/) and open a ticket at "
- + "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
+ + "create a log file (see documentation at https://dependency-check.github.io/DependencyCheck/) and open a ticket at "
+ + "https://github.com/dependency-check/DependencyCheck/issues and include the log file.\n\n",
dd, dd, settings.getString(Settings.KEYS.APPLICATION_NAME));
LOGGER.debug("", ex);
}
@@ -1399,8 +1806,7 @@ public void persistEcosystemCache() {
public void defrag() {
if (isH2) {
final long start = System.currentTimeMillis();
- try (Connection conn = databaseManager.getConnection();
- CallableStatement psCompaxt = conn.prepareCall("SHUTDOWN DEFRAG")) {
+ try (Connection conn = databaseManager.getConnection(); CallableStatement psCompaxt = conn.prepareCall("SHUTDOWN DEFRAG")) {
LOGGER.info("Begin database defrag");
psCompaxt.execute();
final long millis = System.currentTimeMillis() - start;
@@ -1447,8 +1853,7 @@ VulnerableSoftware getMatchingSoftware(Cpe cpe, Set vulnerab
*/
public void deleteUnusedCpe() {
clearCache();
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement ps = getPreparedStatement(conn, DELETE_UNUSED_DICT_CPE)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, DELETE_UNUSED_DICT_CPE)) {
ps.executeUpdate();
} catch (SQLException ex) {
LOGGER.error("Unable to delete CPE dictionary entries", ex);
@@ -1468,8 +1873,7 @@ public void deleteUnusedCpe() {
*/
public void addCpe(String cpe, String vendor, String product) {
clearCache();
- try (Connection conn = databaseManager.getConnection();
- PreparedStatement ps = getPreparedStatement(conn, ADD_DICT_CPE)) {
+ try (Connection conn = databaseManager.getConnection(); PreparedStatement ps = getPreparedStatement(conn, ADD_DICT_CPE)) {
ps.setString(1, cpe);
ps.setString(2, vendor);
ps.setString(3, product);
@@ -1528,6 +1932,340 @@ private void addNullableStringParameter(PreparedStatement ps, int pos, String va
}
}
+ private void setUpdateColumn(PreparedStatement ps, int i, Double value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.DOUBLE);
+ } else {
+ ps.setDouble(i, value);
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AuthenticationType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.CiaType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.Version value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessComplexityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV2Data.AccessVectorType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, String value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value);
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4.Type value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, Boolean value) throws SQLException {
+ if (value == null) {
+ //TODO this is may also be an issue for MS SQL, if an issue is created we'll just need
+ // to create an isMsSQL flag. See todo above in updateOrInsertVulnerability.
+ if (isOracle) {
+ ps.setNull(i, java.sql.Types.BIT);
+ } else {
+ ps.setNull(i, java.sql.Types.BOOLEAN);
+ }
+ } else {
+ ps.setBoolean(i, value);
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackVectorType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.AttackComplexityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.PrivilegesRequiredType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.UserInteractionType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.ScopeType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.SeverityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.CiaType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV3Data.Version value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.Version value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackVectorType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackComplexityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AttackRequirementsType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.PrivilegesRequiredType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.UserInteractionType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ExploitMaturityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.CiaRequirementType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackVectorType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackComplexityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedAttackRequirementsType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedPrivilegesRequiredType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedUserInteractionType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedCiaType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedSubCType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ModifiedSubIaType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SafetyType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.AutomatableType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.RecoveryType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ValueDensityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.VulnerabilityResponseEffortType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.ProviderUrgencyType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
+ private void setUpdateColumn(PreparedStatement ps, int i, CvssV4Data.SeverityType value) throws SQLException {
+ if (value == null) {
+ ps.setNull(i, java.sql.Types.VARCHAR);
+ } else {
+ ps.setString(i, value.value());
+ }
+ }
+
/**
* Sets the float parameter on a prepared statement from a properties map.
*
@@ -1542,10 +2280,10 @@ private void setFloatValue(PreparedStatement ps, int i, Map prop
try {
ps.setFloat(i, Float.parseFloat(props.get(key).toString()));
} catch (NumberFormatException nfe) {
- ps.setNull(i, java.sql.Types.NULL);
+ ps.setNull(i, java.sql.Types.FLOAT);
}
} else {
- ps.setNull(i, java.sql.Types.NULL);
+ ps.setNull(i, java.sql.Types.FLOAT);
}
}
@@ -1562,7 +2300,7 @@ private void setStringValue(PreparedStatement ps, int i, Map pro
if (props != null && props.containsKey(key)) {
ps.setString(i, props.get(key).toString());
} else {
- ps.setNull(i, java.sql.Types.NULL);
+ ps.setNull(i, java.sql.Types.VARCHAR);
}
}
@@ -1579,7 +2317,7 @@ private void setBooleanValue(PreparedStatement ps, int i, Map pr
if (props != null && props.containsKey(key)) {
ps.setBoolean(i, Boolean.parseBoolean(props.get(key).toString()));
} else {
- ps.setNull(i, java.sql.Types.NULL);
+ ps.setNull(i, java.sql.Types.BOOLEAN);
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveItemOperator.java b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveItemOperator.java
index 87866186e72..9d22ec4093b 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveItemOperator.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveItemOperator.java
@@ -17,13 +17,16 @@
*/
package org.owasp.dependencycheck.data.nvdcve;
+import io.github.jeremylong.openvulnerability.client.nvd.Config;
+
+import java.util.Objects;
import java.util.stream.Collectors;
import org.owasp.dependencycheck.data.nvd.ecosystem.Ecosystem;
-import org.owasp.dependencycheck.data.nvd.json.CpeMatchStreamCollector;
-import org.owasp.dependencycheck.data.nvd.json.DefCveItem;
-import org.owasp.dependencycheck.data.nvd.json.LangString;
-import org.owasp.dependencycheck.data.nvd.json.NodeFlatteningCollector;
+import io.github.jeremylong.openvulnerability.client.nvd.DefCveItem;
+import io.github.jeremylong.openvulnerability.client.nvd.LangString;
+import io.github.jeremylong.openvulnerability.client.nvd.Node;
+import java.util.List;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
/**
@@ -57,7 +60,7 @@ public CveItemOperator(String cpeStartsWithFilter) {
* @return the English descriptions from the CVE object
*/
public String extractDescription(DefCveItem cve) {
- return cve.getCve().getDescription().getDescriptionData().stream().filter((desc)
+ return cve.getCve().getDescriptions().stream().filter((desc)
-> "en".equals(desc.getLang())).map(LangString::getValue).collect(Collectors.joining(" "));
}
@@ -215,12 +218,20 @@ public boolean isRejected(String description) {
* @return true if the CVE affects CPEs identified by the
* configured CPE Starts with filter
*/
- protected boolean testCveCpeStartWithFilter(final DefCveItem cve) {
- //cycle through to see if this is a CPE we care about (use the CPE filters
- return cve.getConfigurations().getNodes().stream()
- .collect(NodeFlatteningCollector.getInstance())
- .collect(CpeMatchStreamCollector.getInstance())
- .filter(cpe -> cpe.getCpe23Uri() != null)
- .anyMatch(cpe -> cpe.getCpe23Uri().startsWith(cpeStartsWithFilter));
+ boolean testCveCpeStartWithFilter(final DefCveItem cve) {
+ if (cve.getCve().getConfigurations() != null) {
+ //cycle through to see if this is a CPE we care about (use the CPE filters
+ return cve.getCve().getConfigurations().stream()
+ .filter(config -> config.getNodes() != null)
+ .map(Config::getNodes)
+ .flatMap(List::stream)
+ .filter(Objects::nonNull)
+ .map(Node::getCpeMatch)
+ .filter(Objects::nonNull)
+ .flatMap(List::stream)
+ .filter(cpe -> cpe != null && cpe.getCriteria() != null)
+ .anyMatch(cpe -> cpe.getCriteria().startsWith(cpeStartsWithFilter));
+ }
+ return false;
}
}
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseManager.java b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseManager.java
index f2ad3472e4f..b1553ebf988 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseManager.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseManager.java
@@ -70,7 +70,7 @@ public final class DatabaseManager {
/**
* The URL that discusses upgrading non-H2 databases.
*/
- public static final String UPGRADE_HELP_URL = "https://jeremylong.github.io/DependencyCheck/data/upgrade.html";
+ public static final String UPGRADE_HELP_URL = "https://dependency-check.github.io/DependencyCheck/data/upgrade.html";
/**
* The database driver used to connect to the database.
*/
@@ -197,6 +197,10 @@ private void initialize() throws DatabaseException {
LOGGER.debug("Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database", ex);
}
+ } else if (isH2 && ex.getMessage().contains("file version or invalid file header")) {
+ LOGGER.error("Incompatible or corrupt database found. To resolve this issue please remove the existing "
+ + "database by running purge");
+ throw new DatabaseException("Incompatible or corrupt database found; run the purge command to resolve the issue");
} else {
LOGGER.debug("Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database", ex);
diff --git a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java
index f1ef704d3f1..698e0bcd749 100644
--- a/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java
+++ b/core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java
@@ -17,8 +17,6 @@
*/
package org.owasp.dependencycheck.data.nvdcve;
-import java.time.Instant;
-import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
@@ -27,8 +25,7 @@
import java.util.TreeMap;
import javax.annotation.concurrent.ThreadSafe;
-import org.owasp.dependencycheck.data.update.nvd.NvdCveInfo;
-import org.owasp.dependencycheck.data.update.exception.UpdateException;
+import org.owasp.dependencycheck.utils.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,26 +43,21 @@ public class DatabaseProperties {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseProperties.class);
/**
- * Modified key word, used as a key to store information about the modified
- * file (i.e. the containing the last 8 days of updates)..
+ * The last modified request data for the NVD API.
*/
- public static final String MODIFIED = "Modified";
+ public static final String NVD_API_LAST_MODIFIED = "nvd.api.last.modified";
/**
- * The properties file key for the last checked field - used to store the
- * last check time of the Modified NVD CVE xml file.
+ * The date the NVD API was last checked for an update.
*/
- public static final String LAST_CHECKED = "NVD CVE Checked";
+ public static final String NVD_API_LAST_CHECKED = "nvd.api.last.checked";
/**
- * The properties file key for the last updated field - used to store the
- * last updated time of the Modified NVD CVE xml file.
+ * The date the NVD cache was last checked for an update.
*/
- public static final String LAST_UPDATED = "NVD CVE Modified";
+ public static final String NVD_CACHE_LAST_CHECKED = "nvd.cache.last.checked";
/**
- * Stores the last updated time for each of the NVD CVE files. These
- * timestamps should be updated if we process the modified file within 7
- * days of the last update.
+ * The date the NVD cache data was last modified/updated.
*/
- public static final String LAST_UPDATED_BASE = "NVD CVE ";
+ public static final String NVD_CACHE_LAST_MODIFIED = "nvd.cache.last.modified";
/**
* The key for the last time the CPE data was updated.
*/
@@ -74,7 +66,6 @@ public class DatabaseProperties {
* The key for the database schema version.
*/
public static final String VERSION = "version";
-
/**
* The key for the last check time for the Known Exploited Vulnerabilities.
*/
@@ -83,7 +74,6 @@ public class DatabaseProperties {
* The key for the version the Known Exploited Vulnerabilities.
*/
public static final String KEV_VERSION = "kev.version";
-
/**
* A collection of properties about the data.
*/
@@ -112,27 +102,13 @@ public synchronized boolean isEmpty() {
return properties == null || properties.isEmpty();
}
- /**
- * Saves the last updated information to the properties file.
- *
- * @param updatedValue the updated NVD CVE entry
- * @throws UpdateException is thrown if there is an update exception
- */
- public synchronized void save(NvdCveInfo updatedValue) throws UpdateException {
- if (updatedValue == null) {
- return;
- }
- save(LAST_UPDATED_BASE + updatedValue.getId(), String.valueOf(updatedValue.getTimestamp()));
- }
-
/**
* Saves the key value pair to the properties store.
*
* @param key the property key
* @param value the property value
- * @throws UpdateException is thrown if there is an update exception
*/
- public synchronized void save(String key, String value) throws UpdateException {
+ public synchronized void save(String key, String value) {
properties.put(key, value);
cveDB.saveProperty(key, value);
}
@@ -181,21 +157,100 @@ public synchronized Map getMetaData() {
for (Entry