Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ARG GID=1000
ENV user=dependencycheck
ENV JAVA_HOME=/opt/jdk
ENV JAVA_OPTS="-Danalyzer.assembly.dotnet.path=/usr/bin/dotnet -Danalyzer.bundle.audit.path=/usr/bin/bundle-audit -Danalyzer.golang.path=/usr/local/go/bin/go"
ENV ODC_NAME=dependency-check-docker

COPY --from=jlink /jlinked /opt/jdk/
COPY --from=go /usr/local/go/ /usr/local/go/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.SeverityUtil;
import org.owasp.dependencycheck.utils.scarf.TelemetryCollector;
import org.slf4j.impl.StaticLoggerBinder;

//CSOFF: MethodCount
Expand Down Expand Up @@ -1335,6 +1336,7 @@ protected void executeWithContextClassloader() throws BuildException {
} catch (InvalidSettingException e) {
throw new BuildException(e);
}
TelemetryCollector.send(getSettings());
try (Engine engine = new Engine(Check.class.getClassLoader(), getSettings())) {
for (Resource resource : getPath()) {
final FileProvider provider = resource.as(FileProvider.class);
Expand Down
1 change: 1 addition & 0 deletions ant/src/main/resources/task.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# the path to the data directory
data.directory=data/11.0
odc.application.name=dependency-check-ant
23 changes: 18 additions & 5 deletions cli/src/main/java/org/owasp/dependencycheck/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

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;
Expand All @@ -39,6 +40,7 @@
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.scarf.TelemetryCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -49,7 +51,9 @@
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;

/**
Expand Down Expand Up @@ -189,6 +193,7 @@ public int run(String[] args) {
try {
populateSettings(cli);
Downloader.getInstance().configure(settings);
TelemetryCollector.send(settings);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage(), ex);
LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
Expand Down Expand Up @@ -254,7 +259,7 @@ public int run(String[] args) {
* collection.
*/
private int runScan(String reportDirectory, String[] outputFormats, String applicationName, String[] files,
String[] excludes, int symLinkDepth, float cvssFailScore) throws DatabaseException,
String[] excludes, int symLinkDepth, float cvssFailScore) throws DatabaseException,
ExceptionCollection, ReportException {
Engine engine = null;
try {
Expand Down Expand Up @@ -341,10 +346,10 @@ private int determineReturnCode(Engine engine, float cvssFailScore) {
if (addName) {
addName = false;
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(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(')');
Expand Down Expand Up @@ -450,6 +455,7 @@ private void runUpdateOnly() throws UpdateException, DatabaseException {
}

//CSOFF: MethodLength

/**
* Updates the global Settings.
*
Expand All @@ -459,6 +465,12 @@ private void runUpdateOnly() throws UpdateException, DatabaseException {
* file is unable to be loaded.
*/
protected void populateSettings(CliParser cli) throws InvalidSettingException {
String name = System.getenv("ODC_NAME") != null ? System.getenv("ODC_NAME") : "dependency-check-cli";
if (name.isBlank()) {
name = "dependency-check-cli";
}
name = name.replace("/", "-").replace(" ", "_");
settings.setString(Settings.KEYS.APPLICATION_NAME, name);
final File propertiesFile = cli.getFileArgument(CliParser.ARGUMENT.PROP);
if (propertiesFile != null) {
try {
Expand Down Expand Up @@ -731,6 +743,7 @@ protected void populateSettings(CliParser cli) throws InvalidSettingException {
}

//CSON: MethodLength

/**
* Creates a file appender and adds it to logback.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.SeverityUtil;
import org.owasp.dependencycheck.utils.scarf.TelemetryCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -888,6 +889,8 @@ public void setPropertiesFilePath(String propertiesFilePath) {
@SuppressWarnings("squid:S2095")
private Engine executeDependencyCheck() throws ExceptionCollection {
populateSettings();
String version = settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown");
TelemetryCollector.send(settings, "dependency-check-scan-agent", version);
final Engine engine;
try {
engine = new Engine(settings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ private boolean isNodeAuditEnabled(Engine engine) {
try {
((AbstractNpmAnalyzer) a).prepareFileTypeAnalyzer(engine);
} catch (InitializationException ex) {
String message = "Error initializing the " + a.getName();
final String message = "Error initializing the " + a.getName();
LOGGER.debug(message, ex);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@
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;

/**
* Enrich dependency information from Sonatype OSS index.
Expand Down Expand Up @@ -131,13 +131,14 @@ 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);
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,11 @@ public String toString() {
return sb.toString();
}

/**
* Returns the NVD search URL for this vulnerable software.
*
* @return the NVD search URL
*/
public String toNvdSearchUrl() {
return CpeIdentifier.nvdSearchUrlFor(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.utils.scarf.TelemetryCollector;

/**
* Maven Plugin that checks project dependencies and the dependencies of all
Expand Down Expand Up @@ -69,6 +70,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
*/
@Override
protected ExceptionCollection scanDependencies(final Engine engine) throws MojoExecutionException {
TelemetryCollector.send(getSettings());
ExceptionCollection exCol = scanArtifacts(getProject(), engine, true);
for (MavenProject childProject : getDescendants(this.getProject())) {
//TODO consider the following as to whether a child should be skipped per #2152
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.utils.scarf.TelemetryCollector;

/**
* Maven Plugin that checks the project dependencies to see if they have any
Expand Down Expand Up @@ -106,6 +107,7 @@ public String getDescription(Locale locale) {
*/
@Override
protected ExceptionCollection scanDependencies(final Engine engine) throws MojoExecutionException {
TelemetryCollector.send(getSettings());
return scanArtifacts(getProject(), engine);
}

Expand Down
1 change: 1 addition & 0 deletions maven/src/main/resources/mojo.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
####
data.directory=[JAR]/../../dependency-check-data/11.0
analyzer.central.enabled=false
odc.application.name=dependency-check-maven
4 changes: 4 additions & 0 deletions src/site/markdown/data/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ OWASP dependency-check includes support to consult the [Sonatype OSS Index](http
to enrich the report with supplemental vulnerability information.

For more details on this integration see [Sonatype OSS Index](./ossindex.html).

## Telemetry

See the [telemetry documentation](../general/telemetry.html) for more information about telemetry data collection.
5 changes: 5 additions & 0 deletions src/site/markdown/general/telemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Telemetry

## Scarf

OWASP dependency-check uses [Scarf](https://about.scarf.sh/) to collect anonymous usage data to help us understand how the software is being used and how we can improve it. You can opt out of telemetry collection by setting the environment variable `SCARF_NO_ANALYTICS` or `DO_NOT_TRACK` to `true`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.owasp.dependencycheck.utils.scarf;

import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.Settings;

import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicBoolean;


/**
* A utility class to collect and send telemetry data to scarf.
* <p>
* Originally from https://github.com/apache/sedona/blob/4e4791d08ddafcf0b46c3d2c092f750eb5dcf2ef/common/src/main/java/org/apache/sedona/common/utils/TelemetryCollector.java#L26
*/
public class TelemetryCollector {

private static final String BASE_URL = "https://dependency-check.gateway.scarf.sh/scan/";
private static final AtomicBoolean telemetrySubmitted = new AtomicBoolean(false);

public static void send(Settings settings) {
try {
String tool = settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check");
String version = settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown");
send(settings, tool, version);
} catch (Exception e) {
// Silent catch block
}
}
public static void send(Settings settings, String tool, String version) {
if (!telemetrySubmitted.compareAndSet(false, true)) {
return;
}
// Check for user opt-out
if (System.getenv("SCARF_NO_ANALYTICS") != null
&& System.getenv("SCARF_NO_ANALYTICS").equalsIgnoreCase("true")
|| System.getenv("DO_NOT_TRACK") != null
&& System.getenv("DO_NOT_TRACK").equalsIgnoreCase("true")
|| System.getProperty("SCARF_NO_ANALYTICS") != null
&& System.getProperty("SCARF_NO_ANALYTICS").equalsIgnoreCase("true")
|| System.getProperty("DO_NOT_TRACK") != null
&& System.getProperty("DO_NOT_TRACK").equalsIgnoreCase("true")) {
return;
}
try {
URL telemetryUrl = new URL(BASE_URL
+ URLEncoder.encode(tool, StandardCharsets.UTF_8)
+ "/"
+ URLEncoder.encode(version, StandardCharsets.UTF_8));
Thread telemetryThread = createThread(settings, telemetryUrl);
telemetryThread.start();
} catch (Exception e) {
// Silent catch block
}
}

private static Thread createThread(Settings settings, URL url) {
Thread telemetryThread =
new Thread("telemetry-thread") {
@Override
public void run() {
try {
Downloader downloader = Downloader.getInstance();
downloader.configure(settings);
downloader.fetchContent(url, StandardCharsets.UTF_8);
} catch (Exception e) {
// Silent catch block
}
}
};
telemetryThread.setDaemon(true);
return telemetryThread;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.owasp.dependencycheck.utils.scarf;

import org.junit.jupiter.api.Test;
import org.owasp.dependencycheck.utils.BaseTest;
import org.owasp.dependencycheck.utils.Settings;

class TelemetryCollectorTest extends BaseTest {

@Test
void testSendTelemetry() throws InterruptedException {
String version = getSettings().getString(Settings.KEYS.APPLICATION_VERSION, "Unknown");
TelemetryCollector.send(getSettings(), "build", version);
Thread.sleep(1000);
}
}