From 07ca0e595a78b6abef98d59ca5a8256235a6a4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Thu, 26 Oct 2023 17:38:25 +0200 Subject: [PATCH] Add NullAway to IAST module and fix errors --- dd-java-agent/agent-iast/build.gradle | 34 ++++++++++++- .../java/com/datadog/iast/Dependencies.java | 41 ++++++++++++++++ .../com/datadog/iast/HasDependencies.java | 45 ----------------- .../com/datadog/iast/IastRequestContext.java | 17 ++++--- .../java/com/datadog/iast/IastSystem.java | 49 ++++++++----------- .../main/java/com/datadog/iast/Reporter.java | 6 +-- .../com/datadog/iast/RequestEndedHandler.java | 1 - .../datadog/iast/RequestStartedHandler.java | 1 - .../java/com/datadog/iast/model/Evidence.java | 7 ++- .../java/com/datadog/iast/model/Location.java | 31 +++++++----- .../java/com/datadog/iast/model/Source.java | 12 +++-- .../com/datadog/iast/model/Vulnerability.java | 7 ++- .../iast/model/VulnerabilityBatch.java | 6 ++- .../datadog/iast/model/VulnerabilityType.java | 22 ++++++--- .../iast/model/json/AdapterFactory.java | 5 +- .../iast/model/json/EvidenceAdapter.java | 31 +++++++++--- .../iast/model/json/SourceAdapter.java | 3 +- .../model/json/TruncatedVulnerabilities.java | 6 ++- .../com/datadog/iast/overhead/Operation.java | 6 ++- .../com/datadog/iast/overhead/Operations.java | 6 ++- .../iast/overhead/OverheadController.java | 18 ++++--- .../propagation/PropagationModuleImpl.java | 6 ++- .../iast/propagation/StringModuleImpl.java | 14 +++--- .../sensitive/AbstractRegexTokenizer.java | 3 +- .../iast/sensitive/SensitiveHandlerImpl.java | 2 +- .../iast/sensitive/SqlRegexpTokenizer.java | 4 -- .../sensitive/TaintedRangeBasedTokenizer.java | 7 ++- .../iast/sink/CommandInjectionModuleImpl.java | 5 ++ .../sink/HstsMissingHeaderModuleImpl.java | 7 ++- .../sink/HttpResponseHeaderModuleImpl.java | 5 ++ .../iast/sink/LdapInjectionModuleImpl.java | 5 ++ .../iast/sink/PathTraversalModuleImpl.java | 5 ++ .../com/datadog/iast/sink/SinkModuleBase.java | 26 +++++----- .../iast/sink/SqlInjectionModuleImpl.java | 5 ++ .../com/datadog/iast/sink/SsrfModuleImpl.java | 5 ++ .../TrustBoundaryViolationModuleImpl.java | 6 +++ .../sink/UnvalidatedRedirectModuleImpl.java | 5 ++ .../iast/sink/WeakCipherModuleImpl.java | 6 +-- .../datadog/iast/sink/WeakHashModuleImpl.java | 6 +-- .../iast/sink/WeakRandomnessModuleImpl.java | 5 ++ .../iast/sink/XContentTypeModuleImpl.java | 5 ++ .../iast/sink/XPathInjectionModuleImpl.java | 6 +++ .../com/datadog/iast/sink/XssModuleImpl.java | 5 ++ .../java/com/datadog/iast/taint/Ranges.java | 19 +++++-- .../com/datadog/iast/taint/TaintedMap.java | 6 ++- .../com/datadog/iast/taint/TaintedObject.java | 2 +- .../datadog/iast/taint/TaintedObjects.java | 1 + .../java/com/datadog/iast/taint/Tainteds.java | 9 +++- .../TelemetryRequestStartedHandler.java | 2 +- .../taint/TaintedObjectsWithTelemetry.java | 3 +- .../iast/util/CookieSecurityParser.java | 5 +- .../com/datadog/iast/util/HttpHeader.java | 2 + .../com/datadog/iast/util/ObjectVisitor.java | 4 +- .../java/com/datadog/iast/util/Ranged.java | 4 +- .../com/datadog/iast/util/RangedDeque.java | 11 ++++- .../iast/IastModuleImplTestBase.groovy | 8 +-- .../iast/RequestEndedHandlerTest.groovy | 1 - .../iast/RequestStartedHandlerTest.groovy | 1 - .../iast/model/VulnerabilityTypeTest.groovy | 9 ++-- .../sink/CommandInjectionModuleTest.groovy | 2 +- .../sink/HstsMissingHeaderModuleTest.groovy | 19 +------ .../sink/HttpResponseHeaderModuleTest.groovy | 6 +-- .../iast/sink/InsecureCookieModuleTest.groovy | 2 +- .../iast/sink/LdapInjectionModuleTest.groovy | 2 +- .../iast/sink/NoHttpCookieModuleTest.groovy | 2 +- .../sink/NoSameSiteCookieModuleTest.groovy | 2 +- .../iast/sink/PathTraversalModuleTest.groovy | 2 +- .../iast/sink/SqlInjectionModuleTest.groovy | 2 +- .../datadog/iast/sink/SsrfModuleTest.groovy | 2 +- .../TrustBoundaryViolationModuleTest.groovy | 2 +- .../sink/UnvalidatedRedirectModuleTest.groovy | 4 +- .../iast/sink/WeakCipherModuleTest.groovy | 2 +- .../iast/sink/WeakHashModuleTest.groovy | 2 +- .../iast/sink/WeakRandomnessModuleTest.groovy | 2 +- .../sink/XContentTypeOptionsModuleTest.groovy | 17 +------ .../iast/sink/XPathInjectionModuleTest.groovy | 2 +- .../datadog/iast/sink/XssModuleTest.groovy | 2 +- .../AbstractTelemetryCallbackTest.groovy | 2 +- .../iast/test/NoopOverheadController.groovy | 5 +- .../iast/telemetry/IastMetricCollector.java | 2 +- 80 files changed, 410 insertions(+), 257 deletions(-) create mode 100644 dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Dependencies.java delete mode 100644 dd-java-agent/agent-iast/src/main/java/com/datadog/iast/HasDependencies.java diff --git a/dd-java-agent/agent-iast/build.gradle b/dd-java-agent/agent-iast/build.gradle index 3a42e0871f4..068bbf5b61d 100644 --- a/dd-java-agent/agent-iast/build.gradle +++ b/dd-java-agent/agent-iast/build.gradle @@ -1,13 +1,29 @@ +import net.ltgt.gradle.errorprone.CheckSeverity + plugins { id 'com.github.johnrengelman.shadow' id 'me.champeau.jmh' id 'java-test-fixtures' id 'com.google.protobuf' version '0.8.18' + id 'net.ltgt.errorprone' version '3.1.0' } apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/gradle/version.gradle" +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } + sourceCompatibility = 1.8 + targetCompatibility = 1.8 +} + +tasks.withType(AbstractCompile).configureEach { + // ensure no APIs beyond JDK8 are used + options.compilerArgs.addAll(['--release', '8']) +} + // First version with Mac M1 support def grpcVersion = '1.42.2' protobuf { @@ -49,6 +65,10 @@ dependencies { jmh project(':dd-java-agent:agent-builder') jmh project(':dd-java-agent:instrumentation:iast-instrumenter') jmh project(':dd-java-agent:instrumentation:java-lang') + + compileOnly('org.jetbrains:annotations:24.0.0') + errorprone('com.uber.nullaway:nullaway:0.10.15') + errorprone('com.google.errorprone:error_prone_core:2.23.0') } shadowJar { @@ -80,7 +100,6 @@ ext { tasks.withType(Test).configureEach { jvmArgs += ['-Ddd.iast.enabled=true'] } -def rootDir = project.rootDir spotless { java { target 'src/**/*.java' @@ -104,3 +123,16 @@ sourceSets { } } } + +tasks.withType(JavaCompile).configureEach { + if (name == 'compileJava') { + options.errorprone { + check("NullAway", CheckSeverity.ERROR) + option("NullAway:AnnotatedPackages", "com.datadog.iast") + disableAllWarnings = true // only errors for now + } + } else { + // disable null away for test and jmh + options.errorprone.enabled = false + } +} diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Dependencies.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Dependencies.java new file mode 100644 index 00000000000..e4df7602205 --- /dev/null +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Dependencies.java @@ -0,0 +1,41 @@ +package com.datadog.iast; + +import com.datadog.iast.overhead.OverheadController; +import datadog.trace.api.Config; +import datadog.trace.util.stacktrace.StackWalker; +import javax.annotation.Nonnull; + +public class Dependencies { + + private final Config config; + private final Reporter reporter; + private final OverheadController overheadController; + private final StackWalker stackWalker; + + public Dependencies( + @Nonnull final Config config, + @Nonnull final Reporter reporter, + @Nonnull final OverheadController overheadController, + @Nonnull final StackWalker stackWalker) { + this.config = config; + this.reporter = reporter; + this.overheadController = overheadController; + this.stackWalker = stackWalker; + } + + public Config getConfig() { + return config; + } + + public Reporter getReporter() { + return reporter; + } + + public OverheadController getOverheadController() { + return overheadController; + } + + public StackWalker getStackWalker() { + return stackWalker; + } +} diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/HasDependencies.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/HasDependencies.java deleted file mode 100644 index 9e1d7cf758f..00000000000 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/HasDependencies.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.datadog.iast; - -import com.datadog.iast.overhead.OverheadController; -import datadog.trace.api.Config; -import datadog.trace.util.stacktrace.StackWalker; -import javax.annotation.Nonnull; - -public interface HasDependencies { - - void registerDependencies(@Nonnull Dependencies dependencies); - - class Dependencies { - private final Config config; - private final Reporter reporter; - private final OverheadController overheadController; - private final StackWalker stackWalker; - - public Dependencies( - @Nonnull final Config config, - @Nonnull final Reporter reporter, - @Nonnull final OverheadController overheadController, - @Nonnull final StackWalker stackWalker) { - this.config = config; - this.reporter = reporter; - this.overheadController = overheadController; - this.stackWalker = stackWalker; - } - - public Config getConfig() { - return config; - } - - public Reporter getReporter() { - return reporter; - } - - public OverheadController getOverheadController() { - return overheadController; - } - - public StackWalker getStackWalker() { - return stackWalker; - } - } -} diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastRequestContext.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastRequestContext.java index 733a4a97aa6..15817bde263 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastRequestContext.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastRequestContext.java @@ -18,11 +18,11 @@ public class IastRequestContext implements IastContext, HasMetricCollector { private final AtomicBoolean spanDataIsSet; private final TaintedObjects taintedObjects; private final OverheadContext overheadContext; - private final IastMetricCollector collector; - private volatile String strictTransportSecurity; - private volatile String xContentTypeOptions; - private volatile String xForwardedProto; - private volatile String contentType; + @Nullable private final IastMetricCollector collector; + @Nullable private volatile String strictTransportSecurity; + @Nullable private volatile String xContentTypeOptions; + @Nullable private volatile String xForwardedProto; + @Nullable private volatile String contentType; public IastRequestContext() { this(TaintedObjects.acquire(), null); @@ -33,7 +33,7 @@ public IastRequestContext(final TaintedObjects taintedObjects) { } public IastRequestContext( - final TaintedObjects taintedObjects, final IastMetricCollector collector) { + final TaintedObjects taintedObjects, @Nullable final IastMetricCollector collector) { this.vulnerabilityBatch = new VulnerabilityBatch(); this.spanDataIsSet = new AtomicBoolean(false); this.overheadContext = new OverheadContext(); @@ -45,6 +45,7 @@ public VulnerabilityBatch getVulnerabilityBatch() { return vulnerabilityBatch; } + @Nullable public String getStrictTransportSecurity() { return strictTransportSecurity; } @@ -53,6 +54,7 @@ public void setStrictTransportSecurity(final String strictTransportSecurity) { this.strictTransportSecurity = strictTransportSecurity; } + @Nullable public String getxContentTypeOptions() { return xContentTypeOptions; } @@ -61,6 +63,7 @@ public void setxContentTypeOptions(final String xContentTypeOptions) { this.xContentTypeOptions = xContentTypeOptions; } + @Nullable public String getxForwardedProto() { return xForwardedProto; } @@ -69,6 +72,7 @@ public void setxForwardedProto(final String xForwardedProto) { this.xForwardedProto = xForwardedProto; } + @Nullable public String getContentType() { return contentType; } @@ -111,6 +115,7 @@ public static IastRequestContext get(final RequestContext reqCtx) { return asRequestContext(IastContext.Provider.get(reqCtx)); } + @Nullable private static IastRequestContext asRequestContext(final IastContext ctx) { return ctx instanceof IastRequestContext ? (IastRequestContext) ctx : null; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastSystem.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastSystem.java index 23b6b0d00e8..589b2dfc80e 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastSystem.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastSystem.java @@ -1,6 +1,5 @@ package com.datadog.iast; -import com.datadog.iast.HasDependencies.Dependencies; import com.datadog.iast.overhead.OverheadController; import com.datadog.iast.propagation.FastCodecModule; import com.datadog.iast.propagation.PropagationModuleImpl; @@ -40,9 +39,9 @@ import datadog.trace.util.AgentTaskScheduler; import datadog.trace.util.stacktrace.StackWalkerFactory; import java.util.function.BiFunction; -import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Stream; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +54,8 @@ public static void start(final SubscriptionService ss) { start(ss, null); } - public static void start(final SubscriptionService ss, OverheadController overheadController) { + public static void start( + final SubscriptionService ss, @Nullable OverheadController overheadController) { final Config config = Config.get(); if (config.getIastActivation() != ProductActivation.FULLY_ENABLED) { LOGGER.debug("IAST is disabled"); @@ -70,7 +70,7 @@ public static void start(final SubscriptionService ss, OverheadController overhe final Dependencies dependencies = new Dependencies(config, reporter, overheadController, StackWalkerFactory.INSTANCE); final boolean addTelemetry = config.getIastTelemetryVerbosity() != Verbosity.OFF; - iastModules().forEach(registerModule(dependencies)); + iastModules(dependencies).forEach(InstrumentationBridge::registerIastModule); registerRequestStartedCallback(ss, addTelemetry, dependencies); registerRequestEndedCallback(ss, addTelemetry, dependencies); registerHeadersCallback(ss); @@ -78,38 +78,29 @@ public static void start(final SubscriptionService ss, OverheadController overhe LOGGER.debug("IAST started"); } - private static Consumer registerModule(final Dependencies dependencies) { - return module -> { - if (module instanceof HasDependencies) { - ((HasDependencies) module).registerDependencies(dependencies); - } - InstrumentationBridge.registerIastModule(module); - }; - } - - private static Stream iastModules() { + private static Stream iastModules(final Dependencies dependencies) { return Stream.of( new StringModuleImpl(), new FastCodecModule(), - new SqlInjectionModuleImpl(), - new PathTraversalModuleImpl(), - new CommandInjectionModuleImpl(), - new WeakCipherModuleImpl(), - new WeakHashModuleImpl(), - new LdapInjectionModuleImpl(), + new SqlInjectionModuleImpl(dependencies), + new PathTraversalModuleImpl(dependencies), + new CommandInjectionModuleImpl(dependencies), + new WeakCipherModuleImpl(dependencies), + new WeakHashModuleImpl(dependencies), + new LdapInjectionModuleImpl(dependencies), new PropagationModuleImpl(), - new HttpResponseHeaderModuleImpl(), - new HstsMissingHeaderModuleImpl(), + new HttpResponseHeaderModuleImpl(dependencies), + new HstsMissingHeaderModuleImpl(dependencies), new InsecureCookieModuleImpl(), new NoHttpOnlyCookieModuleImpl(), - new XContentTypeModuleImpl(), + new XContentTypeModuleImpl(dependencies), new NoSameSiteCookieModuleImpl(), - new SsrfModuleImpl(), - new UnvalidatedRedirectModuleImpl(), - new WeakRandomnessModuleImpl(), - new XPathInjectionModuleImpl(), - new TrustBoundaryViolationModuleImpl(), - new XssModuleImpl()); + new SsrfModuleImpl(dependencies), + new UnvalidatedRedirectModuleImpl(dependencies), + new WeakRandomnessModuleImpl(dependencies), + new XPathInjectionModuleImpl(dependencies), + new TrustBoundaryViolationModuleImpl(dependencies), + new XssModuleImpl(dependencies)); } private static void registerRequestStartedCallback( diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java index e51cf258b38..bb4f3436a27 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java @@ -30,7 +30,7 @@ public class Reporter { this(Config.get(), null); } - public Reporter(final Config config, final AgentTaskScheduler taskScheduler) { + public Reporter(final Config config, @Nullable final AgentTaskScheduler taskScheduler) { this( config.isIastDeduplicationEnabled() ? new HashBasedDeduplication(taskScheduler) @@ -108,11 +108,11 @@ protected static class HashBasedDeduplication implements Predicate hashes; - public HashBasedDeduplication(final AgentTaskScheduler taskScheduler) { + public HashBasedDeduplication(@Nullable final AgentTaskScheduler taskScheduler) { this(DEFAULT_MAX_SIZE, taskScheduler); } - HashBasedDeduplication(final int size, final AgentTaskScheduler taskScheduler) { + HashBasedDeduplication(final int size, @Nullable final AgentTaskScheduler taskScheduler) { maxSize = size; hashes = ConcurrentHashMap.newKeySet(size); if (taskScheduler != null) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestEndedHandler.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestEndedHandler.java index 25611c79643..fc2c9a18975 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestEndedHandler.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestEndedHandler.java @@ -3,7 +3,6 @@ import static com.datadog.iast.IastTag.ANALYZED; import static com.datadog.iast.IastTag.SKIPPED; -import com.datadog.iast.HasDependencies.Dependencies; import com.datadog.iast.overhead.OverheadController; import com.datadog.iast.taint.TaintedObjects; import datadog.trace.api.gateway.Flow; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestStartedHandler.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestStartedHandler.java index 9c680717743..4d5c851f52c 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestStartedHandler.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/RequestStartedHandler.java @@ -1,6 +1,5 @@ package com.datadog.iast; -import com.datadog.iast.HasDependencies.Dependencies; import com.datadog.iast.overhead.OverheadController; import datadog.trace.api.gateway.Flow; import java.util.function.Supplier; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Evidence.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Evidence.java index 65b2f78e374..c4dc17d27e5 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Evidence.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Evidence.java @@ -17,6 +17,8 @@ public final class Evidence { private final transient @Nonnull Context context = new Evidence.Context(4); /** For deserialization in tests via moshi */ + @Deprecated + @SuppressWarnings({"NullAway", "DataFlowIssue", "unused"}) private Evidence() { this(null, null); } @@ -25,15 +27,17 @@ public Evidence(final String value) { this(value, null); } - public Evidence(final String value, final Range[] ranges) { + public Evidence(@Nonnull final String value, @Nullable final Range[] ranges) { this.value = value; this.ranges = ranges; } + @Nonnull public String getValue() { return value; } + @Nullable public Range[] getRanges() { return ranges; } @@ -76,6 +80,7 @@ public boolean put(final String key, final Object value) { return true; } + @Nullable @SuppressWarnings("unchecked") public E get(@Nonnull final String key) { return (E) context.get(key); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Location.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Location.java index 2522699121b..1dbe22b545d 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Location.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Location.java @@ -1,25 +1,26 @@ package com.datadog.iast.model; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import javax.annotation.Nullable; public final class Location { - private final String path; + @Nullable private final String path; private final int line; - private final String method; + @Nullable private final String method; - private Long spanId; + @Nullable private Long spanId; - private transient String serviceName; + @Nullable private transient String serviceName; private Location( - final Long spanId, - final String path, + @Nullable final Long spanId, + @Nullable final String path, final int line, - final String method, - final String serviceName) { + @Nullable final String method, + @Nullable final String serviceName) { this.spanId = spanId; this.path = path; this.line = line; @@ -27,7 +28,8 @@ private Location( this.serviceName = serviceName; } - public static Location forSpanAndStack(final AgentSpan span, final StackTraceElement stack) { + public static Location forSpanAndStack( + @Nullable final AgentSpan span, final StackTraceElement stack) { return new Location( spanId(span), stack.getClassName(), @@ -54,6 +56,7 @@ public long getSpanId() { return spanId == null ? 0 : spanId; } + @Nullable public String getPath() { return path; } @@ -62,26 +65,30 @@ public int getLine() { return line; } + @Nullable public String getMethod() { return method; } + @Nullable public String getServiceName() { return serviceName; } - public void updateSpan(final AgentSpan span) { + public void updateSpan(@Nullable final AgentSpan span) { if (span != null) { this.spanId = span.getSpanId(); this.serviceName = span.getServiceName(); } } - private static Long spanId(AgentSpan span) { + @Nullable + private static Long spanId(@Nullable AgentSpan span) { return span != null ? span.getSpanId() : null; } - private static String serviceName(AgentSpan span) { + @Nullable + private static String serviceName(@Nullable AgentSpan span) { return span != null ? span.getServiceName() : null; } } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Source.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Source.java index f3f7d5d84e6..31acd483a7a 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Source.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Source.java @@ -5,17 +5,19 @@ import datadog.trace.api.iast.Taintable; import java.util.Objects; import java.util.StringJoiner; +import javax.annotation.Nullable; public final class Source implements Taintable.Source { private final @SourceTypeString byte origin; - private final String name; - private final String value; + @Nullable private final String name; + @Nullable private final String value; - public Source(final byte origin, final CharSequence name, final CharSequence value) { + public Source( + final byte origin, @Nullable final CharSequence name, @Nullable final CharSequence value) { this(origin, name == null ? null : name.toString(), value == null ? null : value.toString()); } - public Source(final byte origin, final String name, final String value) { + public Source(final byte origin, @Nullable final String name, @Nullable final String value) { this.origin = origin; this.name = name; this.value = value; @@ -27,11 +29,13 @@ public byte getOrigin() { } @Override + @Nullable public String getName() { return name; } @Override + @Nullable public String getValue() { return value; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Vulnerability.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Vulnerability.java index 1e119321ff1..97ecf815775 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Vulnerability.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/Vulnerability.java @@ -15,21 +15,26 @@ public final class Vulnerability { private long hash; public Vulnerability( - final VulnerabilityType type, final Location location, final Evidence evidence) { + @Nonnull final VulnerabilityType type, + @Nonnull final Location location, + @Nullable final Evidence evidence) { this.type = type; this.location = location; this.evidence = evidence; this.hash = type.calculateHash(this); } + @Nonnull public VulnerabilityType getType() { return type; } + @Nonnull public Location getLocation() { return location; } + @Nullable public Evidence getEvidence() { return evidence; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityBatch.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityBatch.java index 17f59fbdd7c..fa5193b0a00 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityBatch.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityBatch.java @@ -3,12 +3,13 @@ import com.datadog.iast.model.json.VulnerabilityEncoding; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; /** Collects vulnerabilities and serializes to JSON lazily on {@link #toString()}. */ public final class VulnerabilityBatch { - private List vulnerabilities; - private volatile String json; + @Nullable private List vulnerabilities; + @Nullable private volatile String json; public void add(final Vulnerability v) { synchronized (this) { @@ -21,6 +22,7 @@ public void add(final Vulnerability v) { } /** Internal list of vulnerabilities. Not thread-safe. */ + @Nullable public List getVulnerabilities() { return vulnerabilities; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityType.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityType.java index 12f3b276043..ae1d25ddfb3 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityType.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityType.java @@ -5,6 +5,7 @@ import datadog.trace.api.iast.VulnerabilityMarks; import datadog.trace.api.iast.VulnerabilityTypes; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.zip.CRC32; import javax.annotation.Nonnull; @@ -99,17 +100,24 @@ public int mark() { @Override public long calculateHash(@Nonnull final Vulnerability vulnerability) { CRC32 crc = new CRC32(); - crc.update(name().getBytes()); + update(crc, name()); final Location location = vulnerability.getLocation(); if (location != null) { crc.update(location.getLine()); - crc.update(location.getPath().getBytes()); + if (location.getPath() != null) { + update(crc, location.getPath()); + } if (location.getLine() <= -1 && location.getMethod() != null) { - crc.update(location.getMethod().getBytes()); + update(crc, location.getMethod()); } } return crc.getValue(); } + + protected void update(final CRC32 crc, final String value) { + final byte[] bytes = value.getBytes(StandardCharsets.UTF_8); + crc.update(bytes, 0, bytes.length); + } } class InjectionTypeImpl extends VulnerabilityTypeImpl implements InjectionType { @@ -135,10 +143,10 @@ public HeaderVulnerabilityType(@Nonnull String name, int vulnerabilityMark) { @Override public long calculateHash(@Nonnull final Vulnerability vulnerability) { CRC32 crc = new CRC32(); - crc.update(name().getBytes()); + update(crc, name()); String serviceName = vulnerability.getLocation().getServiceName(); if (serviceName != null) { - crc.update(serviceName.getBytes()); + update(crc, serviceName); } return crc.getValue(); } @@ -152,10 +160,10 @@ public CookieVulnerabilityType(@Nonnull String name, int vulnerabilityMark) { @Override public long calculateHash(@Nonnull final Vulnerability vulnerability) { CRC32 crc = new CRC32(); - crc.update(name().getBytes()); + update(crc, name()); final Evidence evidence = vulnerability.getEvidence(); if (evidence != null) { - crc.update(evidence.getValue().getBytes()); + update(crc, evidence.getValue()); } return crc.getValue(); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/AdapterFactory.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/AdapterFactory.java index 469c3b9227d..b62e74388ae 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/AdapterFactory.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/AdapterFactory.java @@ -37,7 +37,7 @@ static class Context { final List sources; final Map sourceIndexMap; final Map sourceContext; - Vulnerability vulnerability; + @Nullable Vulnerability vulnerability; public Context() { sources = new ArrayList<>(); @@ -183,7 +183,7 @@ public static class RedactionContext { private final Source source; private final boolean sensitive; private boolean sensitiveRanges; - private String redactedValue; + @Nullable private String redactedValue; public RedactionContext(final Source source) { this.source = source; @@ -206,6 +206,7 @@ public boolean shouldRedact() { return sensitive || sensitiveRanges; } + @Nullable public String getRedactedValue() { return redactedValue; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/EvidenceAdapter.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/EvidenceAdapter.java index d6da0e76561..9c78f11ed81 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/EvidenceAdapter.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/EvidenceAdapter.java @@ -74,8 +74,12 @@ private String substring(final String value, final Ranged range) { private class DefaultEvidenceAdapter extends FormattingAdapter { @Override - public void toJson(@Nonnull final JsonWriter writer, final @Nonnull Evidence evidence) + public void toJson(@Nonnull final JsonWriter writer, final @Nullable Evidence evidence) throws IOException { + if (evidence == null) { + writer.nullValue(); + return; + } writer.beginObject(); if (evidence.getRanges() == null || evidence.getRanges().length == 0) { writer.name("value"); @@ -132,8 +136,12 @@ private void writeValuePart( private class RedactedEvidenceAdapter extends FormattingAdapter { @Override - public void toJson(@Nonnull final JsonWriter writer, @Nonnull final Evidence evidence) + public void toJson(@Nonnull final JsonWriter writer, @Nullable final Evidence evidence) throws IOException { + if (evidence == null) { + writer.nullValue(); + return; + } final Context ctx = Context.get(); final Vulnerability vulnerability = ctx.vulnerability; if (vulnerability == null) { @@ -163,7 +171,10 @@ private void toRedactedJson( writer.beginArray(); for (final Iterator it = new ValuePartIterator(ctx, value, tainted, sensitive); it.hasNext(); ) { - it.next().write(ctx, writer); + final ValuePart next = it.next(); + if (next != null) { + next.write(ctx, writer); + } } writer.endArray(); } @@ -205,6 +216,7 @@ public boolean hasNext() { return !next.isEmpty() || index < value.length(); } + @Nullable @Override public ValuePart next() { if (!hasNext()) { @@ -237,6 +249,7 @@ public ValuePart next() { return next.poll(); } + @Nullable private Ranged handleTaintedValue( @Nonnull final Range nextTainted, @Nullable Ranged nextSensitive) { final RedactionContext redactionCtx = ctx.getRedaction(nextTainted.getSource()); @@ -290,6 +303,7 @@ private void handleSensitiveValue(@Nonnull Ranged nextSensitive) { * Removes the tainted range from the sensitive one and returns whatever is before and enqueues * the rest */ + @Nullable private Ranged removeTaintedRange(final Ranged sensitive, final Range tainted) { final List disjointRanges = sensitive.remove(tainted); Ranged result = null; @@ -303,6 +317,7 @@ private Ranged removeTaintedRange(final Ranged sensitive, final Range tainted) { return result; } + @Nullable private ValuePart nextStringValuePart(final int end) { if (index < end) { final String chunk = value.substring(index, end); @@ -325,9 +340,10 @@ interface ValuePart { } static class StringValuePart implements ValuePart { - private final String value; - private StringValuePart(final String value) { + @Nullable private final String value; + + private StringValuePart(@Nullable final String value) { this.value = value; } @@ -444,11 +460,12 @@ private void addValuePart( } else { final int length = chunk.length(); final String sourceValue = source.getValue(); + final String redactedValue = ctx.getRedactedValue(); final int matching = (sourceValue == null) ? -1 : sourceValue.indexOf(chunk); final String pattern; - if (matching >= 0) { + if (matching >= 0 && redactedValue != null) { // if matches append the matching part from the redacted value - pattern = ctx.getRedactedValue().substring(matching, matching + length); + pattern = redactedValue.substring(matching, matching + length); } else { // otherwise redact the string pattern = SensitiveHandler.get().redactString(chunk); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/SourceAdapter.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/SourceAdapter.java index 9da5177c6ef..7f5ab7edc1f 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/SourceAdapter.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/SourceAdapter.java @@ -66,7 +66,8 @@ public void toJson(@Nonnull final JsonWriter writer, final @Nonnull Source sourc } } - private void toRedactedJson(final JsonWriter writer, final Source source, final String value) + private void toRedactedJson( + final JsonWriter writer, final Source source, @Nullable final String value) throws IOException { writer.beginObject(); writer.name("origin"); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/TruncatedVulnerabilities.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/TruncatedVulnerabilities.java index 2212f1b9963..fe767384ef2 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/TruncatedVulnerabilities.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/json/TruncatedVulnerabilities.java @@ -2,15 +2,17 @@ import com.datadog.iast.model.Vulnerability; import java.util.List; +import javax.annotation.Nullable; public class TruncatedVulnerabilities { - private final List vulnerabilities; + @Nullable private final List vulnerabilities; - public TruncatedVulnerabilities(final List vulnerabilities) { + public TruncatedVulnerabilities(@Nullable final List vulnerabilities) { this.vulnerabilities = vulnerabilities; } + @Nullable public List getVulnerabilities() { return vulnerabilities; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operation.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operation.java index f0d75012887..c21cec9d9c7 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operation.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operation.java @@ -1,7 +1,9 @@ package com.datadog.iast.overhead; +import javax.annotation.Nullable; + public interface Operation { - boolean hasQuota(final OverheadContext context); + boolean hasQuota(@Nullable final OverheadContext context); - boolean consumeQuota(final OverheadContext context); + boolean consumeQuota(@Nullable final OverheadContext context); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operations.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operations.java index c9eab7b7237..e7bb35f1550 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operations.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/Operations.java @@ -1,5 +1,7 @@ package com.datadog.iast.overhead; +import javax.annotation.Nullable; + public class Operations { private Operations() {} @@ -7,7 +9,7 @@ private Operations() {} public static final Operation REPORT_VULNERABILITY = new Operation() { @Override - public boolean hasQuota(final OverheadContext context) { + public boolean hasQuota(@Nullable final OverheadContext context) { if (context == null) { return false; } @@ -15,7 +17,7 @@ public boolean hasQuota(final OverheadContext context) { } @Override - public boolean consumeQuota(final OverheadContext context) { + public boolean consumeQuota(@Nullable final OverheadContext context) { if (context == null) { return false; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/OverheadController.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/OverheadController.java index ee03973a11e..44f62063030 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/OverheadController.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/overhead/OverheadController.java @@ -13,6 +13,7 @@ import datadog.trace.util.AgentTaskScheduler; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,9 +25,9 @@ public interface OverheadController { int releaseRequest(); - boolean hasQuota(final Operation operation, final AgentSpan span); + boolean hasQuota(final Operation operation, @Nullable final AgentSpan span); - boolean consumeQuota(final Operation operation, final AgentSpan span); + boolean consumeQuota(final Operation operation, @Nullable final AgentSpan span); static OverheadController build(final Config config, final AgentTaskScheduler scheduler) { final OverheadControllerImpl result = new OverheadControllerImpl(config, scheduler); @@ -68,7 +69,7 @@ public int releaseRequest() { } @Override - public boolean hasQuota(final Operation operation, final AgentSpan span) { + public boolean hasQuota(final Operation operation, @Nullable final AgentSpan span) { final boolean result = delegate.hasQuota(operation, span); if (LOGGER.isDebugEnabled()) { LOGGER.debug( @@ -82,7 +83,7 @@ public boolean hasQuota(final Operation operation, final AgentSpan span) { } @Override - public boolean consumeQuota(final Operation operation, final AgentSpan span) { + public boolean consumeQuota(final Operation operation, @Nullable final AgentSpan span) { final boolean result = delegate.consumeQuota(operation, span); if (LOGGER.isDebugEnabled()) { LOGGER.debug( @@ -103,7 +104,7 @@ public void reset() { } } - private int getAvailableQuote(final AgentSpan span) { + private int getAvailableQuote(@Nullable final AgentSpan span) { final OverheadContext context = delegate.getContext(span); return context == null ? -1 : context.getAvailableQuota(); } @@ -149,16 +150,17 @@ public int releaseRequest() { } @Override - public boolean hasQuota(final Operation operation, final AgentSpan span) { + public boolean hasQuota(final Operation operation, @Nullable final AgentSpan span) { return operation.hasQuota(getContext(span)); } @Override - public boolean consumeQuota(final Operation operation, final AgentSpan span) { + public boolean consumeQuota(final Operation operation, @Nullable final AgentSpan span) { return operation.consumeQuota(getContext(span)); } - public OverheadContext getContext(final AgentSpan span) { + @Nullable + public OverheadContext getContext(@Nullable final AgentSpan span) { final RequestContext requestContext = span != null ? span.getRequestContext() : null; if (requestContext != null) { IastRequestContext iastRequestContext = requestContext.getData(RequestContextSlot.IAST); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/PropagationModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/PropagationModuleImpl.java index e9e9baa410e..ea0abe982b3 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/PropagationModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/PropagationModuleImpl.java @@ -19,6 +19,7 @@ import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.jetbrains.annotations.Contract; public class PropagationModuleImpl implements PropagationModule { @@ -322,6 +323,7 @@ private static CharSequence sourceValue(@Nullable final Object target) { return null; } + @Contract("null -> false") private static boolean canBeTainted(@Nullable final Object target) { if (target == null) { return false; @@ -332,6 +334,7 @@ private static boolean canBeTainted(@Nullable final Object target) { return true; } + @Contract("null -> false") private static boolean canBeTainted(@Nullable final Object[] target) { if (target == null || target.length == 0) { return false; @@ -462,8 +465,9 @@ private static Range[] markRanges(@Nonnull final Range[] ranges, final int mark) private static class LazyContext implements IastContext { private boolean fetched; - private IastRequestContext delegate; + @Nullable private IastRequestContext delegate; + @Nullable private IastRequestContext getDelegate() { if (!fetched) { fetched = true; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/StringModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/StringModuleImpl.java index 7a3f7720112..a93d3c53e8e 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/StringModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/propagation/StringModuleImpl.java @@ -39,6 +39,7 @@ public class StringModuleImpl implements StringModule { private static final int NULL_STR_LENGTH = "null".length(); + @SuppressWarnings("NullAway") // NullAway fails with taintedLeft and taintedRight checks @Override public void onStringConcat( @Nonnull final String left, @Nullable final String right, @Nonnull final String result) { @@ -170,7 +171,7 @@ public void onStringConcatFactory( int offset = 0, rangeIndex = 0; for (int item : recipeOffsets) { if (item < 0) { - offset += (-item); + offset += -item; } else { final String argument = args[item]; final Range[] ranges = sourceRanges.get(item); @@ -214,7 +215,7 @@ public void onStringSubSequence( @Override public void onStringJoin( - @Nullable String result, @Nonnull CharSequence delimiter, @Nonnull CharSequence... elements) { + @Nullable String result, @Nonnull CharSequence delimiter, @Nonnull CharSequence[] elements) { if (!canBeTainted(result)) { return; } @@ -262,7 +263,7 @@ public void onStringJoin( @Override @SuppressFBWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ") - public void onStringRepeat(String self, int count, String result) { + public void onStringRepeat(@Nonnull String self, int count, @Nonnull String result) { if (!canBeTainted(self) || !canBeTainted(result) || self == result) { return; } @@ -368,7 +369,7 @@ private static int insertRange( return rangeIndex + count; } - private static Range[] getRanges(final TaintedObject taintedObject) { + private static Range[] getRanges(@Nullable final TaintedObject taintedObject) { return taintedObject == null ? EMPTY : taintedObject.getRanges(); } @@ -572,11 +573,11 @@ public void onSplit(@Nonnull String self, @Nonnull String[] result) { * @param finalRanges result with all ranges */ private void addParameterTaintedRanges( - final Range placeholderRange, + @Nullable final Range placeholderRange, final Object param, final String formatted, final int offset, - final Range[] ranges, + @Nullable final Range[] ranges, /* out */ final RangeList finalRanges) { if (ranges != null && ranges.length > 0) { // only shift ranges if they are character sequences of the same length, otherwise taint the @@ -602,6 +603,7 @@ private void addParameterTaintedRanges( * @param finalRanges result with all ranges * @return tainted range of the placeholder or {@code null} if not tainted */ + @Nullable private Range addFormatTaintedRanges( final Ranged placeholderPos, final int offset, diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/AbstractRegexTokenizer.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/AbstractRegexTokenizer.java index 58a1e8aaec3..54c73669be3 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/AbstractRegexTokenizer.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/AbstractRegexTokenizer.java @@ -4,11 +4,12 @@ import java.util.NoSuchElementException; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nullable; public abstract class AbstractRegexTokenizer implements SensitiveHandler.Tokenizer { protected final Matcher matcher; - private Ranged current; + @Nullable private Ranged current; protected AbstractRegexTokenizer(final Pattern pattern, final String evidence) { matcher = pattern.matcher(evidence); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SensitiveHandlerImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SensitiveHandlerImpl.java index ffa8dbe3346..d62fdf8c95c 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SensitiveHandlerImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SensitiveHandlerImpl.java @@ -76,7 +76,7 @@ public Tokenizer tokenizeEvidence( return supplier.tokenizerFor(evidence); } - private int computeLength(final String value) { + private int computeLength(@Nullable final String value) { if (value == null || value.isEmpty()) { return 0; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SqlRegexpTokenizer.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SqlRegexpTokenizer.java index 9082979e890..6c87aaf7a87 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SqlRegexpTokenizer.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/SqlRegexpTokenizer.java @@ -120,10 +120,6 @@ public static Dialect fromEvidence(final Evidence evidence) { return ANSI; } - public static Dialect current() { - return ANSI; - } - public Pattern buildPattern() { return pattern.get(); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/TaintedRangeBasedTokenizer.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/TaintedRangeBasedTokenizer.java index b0f08bb9afb..b2cff3356b4 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/TaintedRangeBasedTokenizer.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sensitive/TaintedRangeBasedTokenizer.java @@ -2,22 +2,24 @@ import com.datadog.iast.model.Evidence; import com.datadog.iast.model.Range; +import com.datadog.iast.taint.Ranges; import com.datadog.iast.util.Ranged; import java.util.NoSuchElementException; +import javax.annotation.Nullable; public class TaintedRangeBasedTokenizer implements SensitiveHandler.Tokenizer { private final String value; private final Range[] ranges; - private Ranged current; + @Nullable private Ranged current; private int rangesIndex; private int pos; public TaintedRangeBasedTokenizer(final Evidence evidence) { - this.ranges = evidence.getRanges(); + this.ranges = evidence.getRanges() == null ? Ranges.EMPTY : evidence.getRanges(); this.value = evidence.getValue(); rangesIndex = 0; pos = 0; // current value position @@ -37,6 +39,7 @@ public Ranged current() { return current; } + @Nullable private Ranged buildNext() { for (; rangesIndex < ranges.length; rangesIndex++) { Range range = ranges[rangesIndex]; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/CommandInjectionModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/CommandInjectionModuleImpl.java index ea5fa289e6d..24fd88c99c4 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/CommandInjectionModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/CommandInjectionModuleImpl.java @@ -3,6 +3,7 @@ import static com.datadog.iast.taint.Ranges.rangesProviderFor; import static com.datadog.iast.taint.Tainteds.canBeTainted; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.taint.TaintedObjects; @@ -15,6 +16,10 @@ public class CommandInjectionModuleImpl extends SinkModuleBase implements CommandInjectionModule { + public CommandInjectionModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onRuntimeExec(@Nullable final String... cmdArray) { if (!canBeTainted(cmdArray)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HstsMissingHeaderModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HstsMissingHeaderModuleImpl.java index f096f5f46ce..801d7e51052 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HstsMissingHeaderModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HstsMissingHeaderModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Location; import com.datadog.iast.model.Vulnerability; @@ -23,6 +24,10 @@ public class HstsMissingHeaderModuleImpl extends SinkModuleBase implements HstsM private static final Logger LOGGER = LoggerFactory.getLogger(HstsMissingHeaderModuleImpl.class); + public HstsMissingHeaderModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onRequestEnd(final Object iastRequestContextObject, final IGSpanInfo igSpanInfo) { @@ -70,7 +75,7 @@ static boolean isHttps(@Nullable final String urlString, @Nullable final String if (urlString == null) { return false; } - if (urlString.toLowerCase().startsWith("https://")) { + if (urlString.toLowerCase(Locale.ROOT).startsWith("https://")) { return true; } if (forwardedFor == null) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HttpResponseHeaderModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HttpResponseHeaderModuleImpl.java index 3216bff3d60..9eea7be16c5 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HttpResponseHeaderModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/HttpResponseHeaderModuleImpl.java @@ -3,6 +3,7 @@ import static com.datadog.iast.util.HttpHeader.Values.SET_COOKIE; import static java.util.Collections.singletonList; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.Location; @@ -27,6 +28,10 @@ public class HttpResponseHeaderModuleImpl extends SinkModuleBase implements HttpResponseHeaderModule { + public HttpResponseHeaderModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onHeader(@Nonnull final String name, final String value) { final HttpHeader header = HttpHeader.from(name); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/LdapInjectionModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/LdapInjectionModuleImpl.java index 1b0fc2a3cd9..aaa0f999bfb 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/LdapInjectionModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/LdapInjectionModuleImpl.java @@ -3,6 +3,7 @@ import static com.datadog.iast.taint.Ranges.rangesProviderFor; import static com.datadog.iast.taint.Tainteds.canBeTainted; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.taint.TaintedObjects; @@ -14,6 +15,10 @@ public class LdapInjectionModuleImpl extends SinkModuleBase implements LdapInjectionModule { + public LdapInjectionModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @SuppressWarnings("unchecked") @Override public void onDirContextSearch( diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/PathTraversalModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/PathTraversalModuleImpl.java index 2cb6eb4d816..cd5a54862a7 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/PathTraversalModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/PathTraversalModuleImpl.java @@ -4,6 +4,7 @@ import static com.datadog.iast.taint.Tainteds.canBeTainted; import static java.util.Arrays.asList; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.taint.TaintedObjects; @@ -20,6 +21,10 @@ public class PathTraversalModuleImpl extends SinkModuleBase implements PathTraversalModule { + public PathTraversalModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onPathTraversal(final @Nullable String path) { if (!canBeTainted(path)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SinkModuleBase.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SinkModuleBase.java index 57a7de1b0dc..d1a24a5516f 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SinkModuleBase.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SinkModuleBase.java @@ -3,7 +3,7 @@ import static com.datadog.iast.util.ObjectVisitor.State.CONTINUE; import static com.datadog.iast.util.ObjectVisitor.State.EXIT; -import com.datadog.iast.HasDependencies; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.Reporter; import com.datadog.iast.model.Evidence; @@ -29,14 +29,13 @@ /** Base class with utility methods for with sinks */ @SuppressWarnings({"UnusedReturnValue", "SameParameterValue"}) -public abstract class SinkModuleBase implements HasDependencies { +public abstract class SinkModuleBase { - protected OverheadController overheadController; - protected Reporter reporter; - protected StackWalker stackWalker; + protected final OverheadController overheadController; + protected final Reporter reporter; + protected final StackWalker stackWalker; - @Override - public void registerDependencies(@Nonnull final Dependencies dependencies) { + protected SinkModuleBase(@Nonnull final Dependencies dependencies) { overheadController = dependencies.getOverheadController(); reporter = dependencies.getReporter(); stackWalker = dependencies.getStackWalker(); @@ -89,6 +88,9 @@ public void registerDependencies(@Nonnull final Dependencies dependencies) { if (rangeProvider.size() == 1) { // only one item and has ranges final E item = rangeProvider.value(0); + if (item == null) { + return null; // should never happen + } evidence = item.toString(); targetRanges = rangeProvider.ranges(item); } else { @@ -177,10 +179,6 @@ protected StackTraceElement getCurrentStackTrace() { return stackWalker.walk(SinkModuleBase::findValidPackageForVulnerability); } - protected String getServiceName(final AgentSpan span) { - return span != null ? span.getServiceName() : null; - } - static StackTraceElement findValidPackageForVulnerability( @Nonnull final Stream stream) { final StackTraceElement[] first = new StackTraceElement[1]; @@ -198,13 +196,13 @@ static StackTraceElement findValidPackageForVulnerability( private class InjectionVisitor implements Visitor { - private final AgentSpan span; + @Nullable private final AgentSpan span; private final IastRequestContext ctx; private final InjectionType type; - private Evidence evidence; + @Nullable private Evidence evidence; private InjectionVisitor( - final AgentSpan span, final IastRequestContext ctx, final InjectionType type) { + @Nullable final AgentSpan span, final IastRequestContext ctx, final InjectionType type) { this.span = span; this.ctx = ctx; this.type = type; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SqlInjectionModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SqlInjectionModuleImpl.java index 31d42394329..98ad3d757f4 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SqlInjectionModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SqlInjectionModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.VulnerabilityType; @@ -10,6 +11,10 @@ public class SqlInjectionModuleImpl extends SinkModuleBase implements SqlInjectionModule { + public SqlInjectionModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onJdbcQuery(@Nullable final String queryString) { onJdbcQuery(queryString, null); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SsrfModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SsrfModuleImpl.java index b4df8302c94..e397e649c6e 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SsrfModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/SsrfModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import datadog.trace.api.iast.sink.SsrfModule; @@ -9,6 +10,10 @@ public class SsrfModuleImpl extends SinkModuleBase implements SsrfModule { + public SsrfModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onURLConnection(@Nullable final Object url) { if (url == null) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/TrustBoundaryViolationModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/TrustBoundaryViolationModuleImpl.java index a584d078a0c..5f3ed0707b2 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/TrustBoundaryViolationModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/TrustBoundaryViolationModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import datadog.trace.api.iast.sink.TrustBoundaryViolationModule; @@ -9,6 +10,11 @@ public class TrustBoundaryViolationModuleImpl extends SinkModuleBase implements TrustBoundaryViolationModule { + + public TrustBoundaryViolationModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onSessionValue(@Nonnull String name, Object value) { final AgentSpan span = AgentTracer.activeSpan(); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/UnvalidatedRedirectModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/UnvalidatedRedirectModuleImpl.java index 45bd6ed2e47..deaf1977898 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/UnvalidatedRedirectModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/UnvalidatedRedirectModuleImpl.java @@ -2,6 +2,7 @@ import static com.datadog.iast.taint.Tainteds.canBeTainted; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.Location; @@ -25,6 +26,10 @@ public class UnvalidatedRedirectModuleImpl extends SinkModuleBase private static final String LOCATION_HEADER = "Location"; private static final String REFERER = "Referer"; + public UnvalidatedRedirectModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onRedirect(final @Nullable String value) { if (!canBeTainted(value)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakCipherModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakCipherModuleImpl.java index f06a52c4f02..0c61867614d 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakCipherModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakCipherModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.overhead.Operations; @@ -14,9 +15,8 @@ public class WeakCipherModuleImpl extends SinkModuleBase implements WeakCipherMo private Config config; - @Override - public void registerDependencies(@Nonnull Dependencies dependencies) { - super.registerDependencies(dependencies); + public WeakCipherModuleImpl(final Dependencies dependencies) { + super(dependencies); config = dependencies.getConfig(); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakHashModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakHashModuleImpl.java index 3d91d1d371b..88b9cb8b0a4 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakHashModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakHashModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.overhead.Operations; @@ -14,9 +15,8 @@ public class WeakHashModuleImpl extends SinkModuleBase implements WeakHashModule private Config config; - @Override - public void registerDependencies(@Nonnull Dependencies dependencies) { - super.registerDependencies(dependencies); + public WeakHashModuleImpl(final Dependencies dependencies) { + super(dependencies); config = dependencies.getConfig(); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakRandomnessModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakRandomnessModuleImpl.java index d374927173a..7c13313eb30 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakRandomnessModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/WeakRandomnessModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.VulnerabilityType; import com.datadog.iast.overhead.Operations; @@ -11,6 +12,10 @@ public class WeakRandomnessModuleImpl extends SinkModuleBase implements WeakRandomnessModule { + public WeakRandomnessModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onWeakRandom(@Nonnull final Class instance) { if (isSecuredInstance(instance)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XContentTypeModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XContentTypeModuleImpl.java index 3d610e75792..8cb864e443e 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XContentTypeModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XContentTypeModuleImpl.java @@ -1,5 +1,6 @@ package com.datadog.iast.sink; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Location; import com.datadog.iast.model.Vulnerability; @@ -18,6 +19,10 @@ public class XContentTypeModuleImpl extends SinkModuleBase implements XContentTypeModule { private static final Logger LOGGER = LoggerFactory.getLogger(XContentTypeModuleImpl.class); + public XContentTypeModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onRequestEnd(final Object iastRequestContextObject, final IGSpanInfo igSpanInfo) { try { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XPathInjectionModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XPathInjectionModuleImpl.java index 7e501b969a6..31633777c5e 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XPathInjectionModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XPathInjectionModuleImpl.java @@ -2,6 +2,7 @@ import static com.datadog.iast.taint.Tainteds.canBeTainted; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.VulnerabilityType; import datadog.trace.api.iast.sink.XPathInjectionModule; @@ -10,6 +11,11 @@ import javax.annotation.Nullable; public class XPathInjectionModuleImpl extends SinkModuleBase implements XPathInjectionModule { + + public XPathInjectionModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onExpression(@Nullable String expression) { if (!canBeTainted(expression)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XssModuleImpl.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XssModuleImpl.java index 0168b73924f..da3d1e18337 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XssModuleImpl.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/sink/XssModuleImpl.java @@ -3,6 +3,7 @@ import static com.datadog.iast.taint.Ranges.rangesProviderFor; import static com.datadog.iast.taint.Tainteds.canBeTainted; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.model.Evidence; import com.datadog.iast.model.Location; @@ -21,6 +22,10 @@ public class XssModuleImpl extends SinkModuleBase implements XssModule { + public XssModuleImpl(final Dependencies dependencies) { + super(dependencies); + } + @Override public void onXss(@Nonnull String s) { if (!canBeTainted(s)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Ranges.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Ranges.java index dd39adc8283..992655086c5 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Ranges.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Ranges.java @@ -85,7 +85,7 @@ public static void copyShift( public static Range[] mergeRanges( final int offset, @Nonnull final Range[] rangesLeft, @Nonnull final Range[] rangesRight) { - final long nRanges = rangesLeft.length + rangesRight.length; + final long nRanges = rangesLeft.length + (long) rangesRight.length; final Range[] ranges = newArray(nRanges); int remaining = ranges.length; if (rangesLeft.length > 0) { @@ -123,6 +123,7 @@ public static RangesProvider rangesProviderFor( return new ListProvider<>(items, to); } + @Nullable public static Range[] forSubstring(int offset, int length, final @Nonnull Range[] ranges) { int[] includedRangesInterval = getIncludedRangesInterval(offset, length, ranges); @@ -214,14 +215,16 @@ public interface RangesProvider { int size(); + @Nullable E value(final int index); + @Nullable Range[] ranges(final E value); } private abstract static class IterableProvider implements RangesProvider { private final LIST items; - private final Map ranges; + @Nullable private final Map ranges; private final int rangeCount; private IterableProvider(@Nonnull final LIST items, @Nonnull final TaintedObjects to) { @@ -252,11 +255,13 @@ public int rangeCount() { return rangeCount; } + @Nullable @Override public E value(final int index) { return item(items, index); } + @Nullable @Override public Range[] ranges(final E value) { return ranges == null ? null : ranges.get(value); @@ -269,12 +274,13 @@ public int size() { protected abstract int size(@Nonnull final LIST items); + @Nullable protected abstract E item(@Nonnull final LIST items, final int index); } private static class SingleProvider implements RangesProvider { private final E value; - private final TaintedObject tainted; + @Nullable private final TaintedObject tainted; private SingleProvider(@Nonnull final E value, @Nonnull final TaintedObjects to) { this.value = value; @@ -291,11 +297,13 @@ public int size() { return 1; } + @Nullable @Override public E value(int index) { return index == 0 ? value : null; } + @Nullable @Override public Range[] ranges(E value) { return value == this.value && tainted != null ? tainted.getRanges() : null; @@ -313,6 +321,7 @@ protected int size(@Nonnull final E[] items) { return items.length; } + @Nullable @Override protected E item(@Nonnull final E[] items, final int index) { return items[index]; @@ -330,13 +339,15 @@ protected int size(@Nonnull final List items) { return items.size(); } + @Nullable @Override protected E item(@Nonnull final List items, final int index) { return items.get(index); } } - public static Range[] getNotMarkedRanges(final Range[] ranges, final int mark) { + @Nullable + public static Range[] getNotMarkedRanges(@Nullable final Range[] ranges, final int mark) { if (ranges == null) { return null; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedMap.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedMap.java index fa690a22ded..79f91c18a6a 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedMap.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedMap.java @@ -223,7 +223,7 @@ private int remove(final TaintedObject entry) { if (cur == null) { return 0; } - for (TaintedObject prev = cur.next; cur != null; prev = cur, cur = cur.next) { + for (TaintedObject prev = cur.next; cur != null && prev != null; prev = cur, cur = cur.next) { if (cur == entry) { prev.next = cur.next; return 1; @@ -259,7 +259,7 @@ private int index(int h) { private Iterator iterator(final int start, final int stop) { return new Iterator() { int currentIndex = start; - TaintedObject currentSubPos; + @Nullable TaintedObject currentSubPos; @Override public boolean hasNext() { @@ -294,6 +294,8 @@ public TaintedObject next() { }; } + @Nonnull + @Override public Iterator iterator() { return iterator(0, table.length); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObject.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObject.java index d8b60f6b68e..84d3b9c6091 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObject.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObject.java @@ -14,7 +14,7 @@ public class TaintedObject extends WeakReference { public static final int MAX_RANGE_COUNT = Config.get().getIastMaxRangeCount(); final int positiveHashCode; - TaintedObject next; + @Nullable TaintedObject next; private Range[] ranges; public TaintedObject( diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObjects.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObjects.java index dc73bd3712b..ab3b20e0401 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObjects.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/TaintedObjects.java @@ -66,6 +66,7 @@ public TaintedObject taint(final @Nonnull Object obj, final @Nonnull Range[] ran return tainted; } + @Nullable @Override public TaintedObject get(final @Nonnull Object obj) { return map.get(obj); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Tainteds.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Tainteds.java index 142249ec1fe..422f677d553 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Tainteds.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/taint/Tainteds.java @@ -1,17 +1,21 @@ package com.datadog.iast.taint; import java.util.Collection; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.jetbrains.annotations.Contract; /** Utilitiles to work with {@link TaintedObject} */ public final class Tainteds { private Tainteds() {} + @Contract("null -> false") public static boolean canBeTainted(@Nullable final CharSequence s) { return s != null && s.length() > 0; } + @Contract("null -> false") public static boolean canBeTainted(@Nullable final E[] e) { if (e == null || e.length == 0) { return false; @@ -24,6 +28,7 @@ public static boolean canBeTainted(@Nullable final E[] return false; } + @Contract("null -> false") public static boolean canBeTainted(@Nullable final Collection e) { if (e == null || e.isEmpty()) { return false; @@ -36,7 +41,9 @@ public static boolean canBeTainted(@Nullable final Coll return false; } - public static TaintedObject getTainted(final TaintedObjects to, final Object value) { + @Nullable + public static TaintedObject getTainted( + @Nonnull final TaintedObjects to, @Nullable final Object value) { return value == null ? null : to.get(value); } } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/TelemetryRequestStartedHandler.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/TelemetryRequestStartedHandler.java index 1bf6033ca8a..5e647355b09 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/TelemetryRequestStartedHandler.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/TelemetryRequestStartedHandler.java @@ -1,6 +1,6 @@ package com.datadog.iast.telemetry; -import com.datadog.iast.HasDependencies.Dependencies; +import com.datadog.iast.Dependencies; import com.datadog.iast.IastRequestContext; import com.datadog.iast.RequestStartedHandler; import com.datadog.iast.taint.TaintedObjects; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/taint/TaintedObjectsWithTelemetry.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/taint/TaintedObjectsWithTelemetry.java index 475a9fd795e..1ac059b0b54 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/taint/TaintedObjectsWithTelemetry.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/telemetry/taint/TaintedObjectsWithTelemetry.java @@ -31,7 +31,7 @@ public static TaintedObjects build( private final TaintedObjects delegate; private final boolean debug; - private IastRequestContext ctx; + @Nullable private IastRequestContext ctx; protected TaintedObjectsWithTelemetry(final boolean debug, final TaintedObjects delegate) { this.delegate = delegate; @@ -46,6 +46,7 @@ public void initContext(final IastRequestContext ctx) { this.ctx = ctx; } + @Nullable @Override public TaintedObject taint(@Nonnull Object obj, @Nonnull Range[] ranges) { final TaintedObject result = delegate.taint(obj, ranges); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/CookieSecurityParser.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/CookieSecurityParser.java index 54dec1ec58a..bc238eac288 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/CookieSecurityParser.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/CookieSecurityParser.java @@ -5,8 +5,10 @@ import datadog.trace.api.iast.util.Cookie; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.NoSuchElementException; import java.util.StringTokenizer; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +46,7 @@ public static List parse(final String cookieString) { } } + @Nullable private static Cookie parseInternal(final String header) { String cookieName; boolean httpOnly = false; @@ -111,7 +114,7 @@ private static List splitMultiCookies(final String header) { } private static int guessCookieVersion(String header) { - header = header.toLowerCase(); + header = header.toLowerCase(Locale.ROOT); if (header.contains("expires=")) { // only netscape cookie using 'expires' return 0; diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/HttpHeader.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/HttpHeader.java index 36ee2b86501..5d58ea8a617 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/HttpHeader.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/HttpHeader.java @@ -6,6 +6,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.Nullable; public class HttpHeader { @@ -19,6 +20,7 @@ public boolean matches(final String name) { return this.name.equalsIgnoreCase(name); } + @Nullable public static HttpHeader from(final String name) { return Values.HEADERS.get(name.toLowerCase(Locale.ROOT)); } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/ObjectVisitor.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/ObjectVisitor.java index c9178b749c1..01f5e568061 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/ObjectVisitor.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/ObjectVisitor.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.function.Predicate; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +26,7 @@ public class ObjectVisitor { private static final int MAX_VISITED_OBJECTS = 1000; private static final int MAX_DEPTH = 10; - private static final Method TRY_SET_ACCESSIBLE; + @Nullable private static final Method TRY_SET_ACCESSIBLE; static { TRY_SET_ACCESSIBLE = fetchTrySetAccessibleMethod(); @@ -210,6 +211,7 @@ private static boolean inspectField(final Field field) { return true; } + @Nullable private static Method fetchTrySetAccessibleMethod() { Method method = null; if (Platform.isJavaVersionAtLeast(9)) { diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/Ranged.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/Ranged.java index 1cde27dc057..645fb58cfdc 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/Ranged.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/Ranged.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; public interface Ranged { @@ -62,6 +63,7 @@ default List remove(final Ranged range) { } /** Computes the intersection of the ranges or {@code null} if they do not intersect */ + @Nullable default Ranged intersection(final Ranged range) { if (this.getStart() == range.getStart() && this.getLength() == range.getLength()) { return this; @@ -84,7 +86,7 @@ default Ranged intersection(final Ranged range) { } } - default boolean isBefore(final Ranged range) { + default boolean isBefore(@Nullable final Ranged range) { if (range == null) { return true; } diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/RangedDeque.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/RangedDeque.java index faef93afde0..4e66a2bf5a1 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/RangedDeque.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/util/RangedDeque.java @@ -9,8 +9,10 @@ /** */ public interface RangedDeque { + @Nullable E poll(); + @Nullable E peek(); void addFirst(@Nonnull E item); @@ -31,8 +33,9 @@ abstract class BaseRangedDequeue implements RangedDeque { private final Deque head = new LinkedList<>(); - protected E next; + @Nullable protected E next; + @Nullable @Override public final E poll() { final E result = next; @@ -40,6 +43,7 @@ public final E poll() { return result; } + @Nullable @Override public final E peek() { return next; @@ -58,15 +62,18 @@ public final boolean isEmpty() { return next == null; } + @Nullable protected final E fetchNext() { return head.isEmpty() ? internalPoll() : head.poll(); } + @Nullable protected abstract E internalPoll(); } class EmptyRangedDequeue extends BaseRangedDequeue { + @Nullable @Override protected E internalPoll() { return null; @@ -82,6 +89,7 @@ class TokenizerQueue extends BaseRangedDequeue { next = fetchNext(); } + @Nullable @Override protected Ranged internalPoll() { return tokenizer.next() ? tokenizer.current() : null; @@ -99,6 +107,7 @@ class ArrayQueue extends BaseRangedDequeue { next = fetchNext(); } + @Nullable @Override protected E internalPoll() { return index >= array.length ? null : array[index++]; diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/IastModuleImplTestBase.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/IastModuleImplTestBase.groovy index d47ce8e0a14..9ad167ed6c6 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/IastModuleImplTestBase.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/IastModuleImplTestBase.groovy @@ -1,6 +1,5 @@ package com.datadog.iast -import com.datadog.iast.HasDependencies.Dependencies import com.datadog.iast.overhead.Operation import com.datadog.iast.overhead.OverheadController import datadog.trace.api.Config @@ -25,6 +24,8 @@ class IastModuleImplTestBase extends DDSpecification { // TODO replace by mock an fix all mock assertions (0 * _ will usually fail) protected StackWalker stackWalker = StackWalkerFactory.INSTANCE + protected Dependencies dependencies = new Dependencies(Config.get(), reporter, overheadController, stackWalker) + void setup() { AgentTracer.forceRegister(tracer) overheadController.acquireRequest() >> true @@ -34,9 +35,4 @@ class IastModuleImplTestBase extends DDSpecification { void cleanup() { AgentTracer.forceRegister(ORIGINAL_TRACER) } - - protected E registerDependencies(final E module) { - module.registerDependencies(new Dependencies(Config.get(), reporter, overheadController, stackWalker)) - return module - } } diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestEndedHandlerTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestEndedHandlerTest.groovy index b205d9d3eba..b325a373d90 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestEndedHandlerTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestEndedHandlerTest.groovy @@ -1,6 +1,5 @@ package com.datadog.iast -import com.datadog.iast.HasDependencies.Dependencies import com.datadog.iast.overhead.OverheadController import datadog.trace.api.Config import datadog.trace.api.gateway.Flow diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestStartedHandlerTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestStartedHandlerTest.groovy index f70e087b146..8a0ca4e2c4a 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestStartedHandlerTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/RequestStartedHandlerTest.groovy @@ -1,6 +1,5 @@ package com.datadog.iast -import com.datadog.iast.HasDependencies.Dependencies import com.datadog.iast.overhead.OverheadController import datadog.trace.api.Config import datadog.trace.api.gateway.Flow diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/model/VulnerabilityTypeTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/model/VulnerabilityTypeTest.groovy index 51568f75e64..408219c9000 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/model/VulnerabilityTypeTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/model/VulnerabilityTypeTest.groovy @@ -27,9 +27,6 @@ class VulnerabilityTypeTest extends DDSpecification { WEAK_CIPHER | getSpanAndClassAndMethodLocation(123) | new Evidence("MD5") | 3265519776 WEAK_CIPHER | getSpanAndClassAndMethodLocation(456) | new Evidence("MD4") | 3265519776 WEAK_CIPHER | getSpanAndClassAndMethodLocation(789) | null | 3265519776 - WEAK_CIPHER | null | new Evidence("MD5") | 1272119222 - WEAK_CIPHER | null | new Evidence("MD4") | 1272119222 - WEAK_CIPHER | null | null | 1272119222 INSECURE_COOKIE | getSpanAndStackLocation(123) | null | 3471934557 INSECURE_COOKIE | getSpanAndStackLocation(123) | new Evidence("cookieName1") | 360083726 INSECURE_COOKIE | getSpanAndStackLocation(123) | new Evidence("cookieName2") | 2357141684 @@ -47,19 +44,19 @@ class VulnerabilityTypeTest extends DDSpecification { HSTS_HEADER_MISSING | getSpanLocation(123, 'serviceName2') | null | 1268102093 } - private Location getSpanAndStackLocation(final long spanId){ + private Location getSpanAndStackLocation(final long spanId) { final span = Mock(AgentSpan) span.getSpanId() >> spanId return Location.forSpanAndStack(span, new StackTraceElement("foo", "foo", "foo", 1)) } - private Location getSpanAndClassAndMethodLocation(final long spanId){ + private Location getSpanAndClassAndMethodLocation(final long spanId) { final span = Mock(AgentSpan) span.getSpanId() >> spanId return Location.forSpanAndClassAndMethod(span, "foo", "foo") } - private Location getSpanLocation(final long spanId, final String serviceName){ + private Location getSpanLocation(final long spanId, final String serviceName) { final span = Mock(AgentSpan) span.getSpanId() >> spanId span.getServiceName() >> serviceName diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/CommandInjectionModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/CommandInjectionModuleTest.groovy index a4db2b305d2..30b8adf5166 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/CommandInjectionModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/CommandInjectionModuleTest.groovy @@ -27,7 +27,7 @@ class CommandInjectionModuleTest extends IastModuleImplTestBase { private AgentSpan span def setup() { - module = registerDependencies(new CommandInjectionModuleImpl()) + module = new CommandInjectionModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HstsMissingHeaderModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HstsMissingHeaderModuleTest.groovy index 58009e2d5c7..505776b3ea4 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HstsMissingHeaderModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HstsMissingHeaderModuleTest.groovy @@ -1,13 +1,10 @@ package com.datadog.iast.sink -import com.datadog.iast.HasDependencies import com.datadog.iast.IastModuleImplTestBase import com.datadog.iast.IastRequestContext import com.datadog.iast.RequestEndedHandler import com.datadog.iast.model.Vulnerability import com.datadog.iast.model.VulnerabilityType -import com.datadog.iast.overhead.OverheadController -import datadog.trace.api.Config import datadog.trace.api.gateway.Flow import datadog.trace.api.gateway.IGSpanInfo import datadog.trace.api.gateway.RequestContext @@ -15,9 +12,8 @@ import datadog.trace.api.gateway.RequestContextSlot import datadog.trace.api.iast.InstrumentationBridge import datadog.trace.api.internal.TraceSegment import datadog.trace.bootstrap.instrumentation.api.AgentSpan -import datadog.trace.util.stacktrace.StackWalker -public class HstsMissingHeaderModuleTest extends IastModuleImplTestBase { +class HstsMissingHeaderModuleTest extends IastModuleImplTestBase { private List objectHolder @@ -29,7 +25,7 @@ public class HstsMissingHeaderModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new HstsMissingHeaderModuleImpl()) + module = new HstsMissingHeaderModuleImpl(dependencies) InstrumentationBridge.registerIastModule(module) objectHolder = [] ctx = new IastRequestContext() @@ -46,14 +42,9 @@ public class HstsMissingHeaderModuleTest extends IastModuleImplTestBase { void 'hsts vulnerability'() { given: Vulnerability savedVul1 - final OverheadController overheadController = Mock(OverheadController) final iastCtx = Mock(IastRequestContext) iastCtx.getxForwardedProto() >> 'https' iastCtx.getContentType() >> "text/html" - final StackWalker stackWalker = Mock(StackWalker) - final dependencies = new HasDependencies.Dependencies( - Config.get(), reporter, overheadController, stackWalker - ) final handler = new RequestEndedHandler(dependencies) final TraceSegment traceSegment = Mock(TraceSegment) final reqCtx = Mock(RequestContext) @@ -96,15 +87,9 @@ public class HstsMissingHeaderModuleTest extends IastModuleImplTestBase { void 'no hsts vulnerability reported'() { given: - Vulnerability savedVul1 - final OverheadController overheadController = Mock(OverheadController) final iastCtx = Mock(IastRequestContext) iastCtx.getxForwardedProto() >> 'https' iastCtx.getContentType() >> "text/html" - final StackWalker stackWalker = Mock(StackWalker) - final dependencies = new HasDependencies.Dependencies( - Config.get(), reporter, overheadController, stackWalker - ) final handler = new RequestEndedHandler(dependencies) final TraceSegment traceSegment = Mock(TraceSegment) final reqCtx = Mock(RequestContext) diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HttpResponseHeaderModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HttpResponseHeaderModuleTest.groovy index f884b16f60d..f3e30e1e180 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HttpResponseHeaderModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HttpResponseHeaderModuleTest.groovy @@ -25,13 +25,13 @@ class HttpResponseHeaderModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new HttpResponseHeaderModuleImpl()) + module = new HttpResponseHeaderModuleImpl(dependencies) InstrumentationBridge.registerIastModule(module) InstrumentationBridge.registerIastModule(new InsecureCookieModuleImpl()) InstrumentationBridge.registerIastModule(new NoHttpOnlyCookieModuleImpl()) InstrumentationBridge.registerIastModule(new NoSameSiteCookieModuleImpl()) - InstrumentationBridge.registerIastModule(new HstsMissingHeaderModuleImpl()) - InstrumentationBridge.registerIastModule(new UnvalidatedRedirectModuleImpl()) + InstrumentationBridge.registerIastModule(new HstsMissingHeaderModuleImpl(dependencies)) + InstrumentationBridge.registerIastModule(new UnvalidatedRedirectModuleImpl(dependencies)) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/InsecureCookieModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/InsecureCookieModuleTest.groovy index bf74a709519..b160f37a28b 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/InsecureCookieModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/InsecureCookieModuleTest.groovy @@ -24,7 +24,7 @@ class InsecureCookieModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new HttpResponseHeaderModuleImpl()) + module = new HttpResponseHeaderModuleImpl(dependencies) InstrumentationBridge.registerIastModule(new InsecureCookieModuleImpl()) objectHolder = [] ctx = new IastRequestContext() diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/LdapInjectionModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/LdapInjectionModuleTest.groovy index 768bba078ff..682e8dfef39 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/LdapInjectionModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/LdapInjectionModuleTest.groovy @@ -27,7 +27,7 @@ class LdapInjectionModuleTest extends IastModuleImplTestBase { private AgentSpan span def setup() { - module = registerDependencies(new LdapInjectionModuleImpl()) + module = new LdapInjectionModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoHttpCookieModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoHttpCookieModuleTest.groovy index 28fda1aeecb..a246f30ee9f 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoHttpCookieModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoHttpCookieModuleTest.groovy @@ -24,7 +24,7 @@ class NoHttpCookieModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new HttpResponseHeaderModuleImpl()) + module = new HttpResponseHeaderModuleImpl(dependencies) InstrumentationBridge.registerIastModule(new NoHttpOnlyCookieModuleImpl()) objectHolder = [] ctx = new IastRequestContext() diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoSameSiteCookieModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoSameSiteCookieModuleTest.groovy index f4a97aaffa1..4e32a9b7722 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoSameSiteCookieModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/NoSameSiteCookieModuleTest.groovy @@ -24,7 +24,7 @@ class NoSameSiteCookieModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new HttpResponseHeaderModuleImpl()) + module = new HttpResponseHeaderModuleImpl(dependencies) InstrumentationBridge.registerIastModule(new NoSameSiteCookieModuleImpl()) objectHolder = [] ctx = new IastRequestContext() diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/PathTraversalModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/PathTraversalModuleTest.groovy index 01a4c1d1dd6..6c25122e393 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/PathTraversalModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/PathTraversalModuleTest.groovy @@ -27,7 +27,7 @@ class PathTraversalModuleTest extends IastModuleImplTestBase { private IastRequestContext ctx def setup() { - module = registerDependencies(new PathTraversalModuleImpl()) + module = new PathTraversalModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SqlInjectionModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SqlInjectionModuleTest.groovy index fe711a6a0c2..69b30fe5ef3 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SqlInjectionModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SqlInjectionModuleTest.groovy @@ -24,7 +24,7 @@ class SqlInjectionModuleTest extends IastModuleImplTestBase { private IastRequestContext ctx def setup() { - module = registerDependencies(new SqlInjectionModuleImpl()) + module = new SqlInjectionModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SsrfModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SsrfModuleTest.groovy index bb914d2dcd2..c379cea4b8f 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SsrfModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/SsrfModuleTest.groovy @@ -25,7 +25,7 @@ class SsrfModuleTest extends IastModuleImplTestBase { private AgentSpan span def setup() { - module = registerDependencies(new SsrfModuleImpl()) + module = new SsrfModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/TrustBoundaryViolationModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/TrustBoundaryViolationModuleTest.groovy index 7769e3e9262..a3fce16d195 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/TrustBoundaryViolationModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/TrustBoundaryViolationModuleTest.groovy @@ -25,7 +25,7 @@ class TrustBoundaryViolationModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new TrustBoundaryViolationModuleImpl()) + module = new TrustBoundaryViolationModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/UnvalidatedRedirectModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/UnvalidatedRedirectModuleTest.groovy index f773870eb5e..5dabb12cc52 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/UnvalidatedRedirectModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/UnvalidatedRedirectModuleTest.groovy @@ -28,7 +28,7 @@ class UnvalidatedRedirectModuleTest extends IastModuleImplTestBase { private IastRequestContext ctx def setup() { - module = registerDependencies(new UnvalidatedRedirectModuleImpl()) + module = new UnvalidatedRedirectModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { @@ -108,7 +108,7 @@ class UnvalidatedRedirectModuleTest extends IastModuleImplTestBase { void 'if onHeader receives a Location header call onRedirect'() { setup: - final urm = Spy(UnvalidatedRedirectModuleImpl) + final urm = Spy(new UnvalidatedRedirectModuleImpl(dependencies)) InstrumentationBridge.registerIastModule(urm) when: diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakCipherModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakCipherModuleTest.groovy index 5b71caa24d4..802df43ec28 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakCipherModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakCipherModuleTest.groovy @@ -12,7 +12,7 @@ class WeakCipherModuleTest extends IastModuleImplTestBase { private WeakCipherModule module def setup() { - module = registerDependencies(new WeakCipherModuleImpl()) + module = new WeakCipherModuleImpl(dependencies) } void 'iast module vulnerable cipher algorithm'(final String algorithm){ diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakHashModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakHashModuleTest.groovy index b3e83664558..2cfebb744e0 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakHashModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakHashModuleTest.groovy @@ -12,7 +12,7 @@ class WeakHashModuleTest extends IastModuleImplTestBase { private WeakHashModule module def setup() { - module = registerDependencies(new WeakHashModuleImpl()) + module = new WeakHashModuleImpl(dependencies) } void 'iast module vulnerable hash algorithm'(final String algorithm){ diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakRandomnessModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakRandomnessModuleTest.groovy index a7401b01a5f..fa3db3c8f19 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakRandomnessModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/WeakRandomnessModuleTest.groovy @@ -14,7 +14,7 @@ class WeakRandomnessModuleTest extends IastModuleImplTestBase { private AgentSpan span def setup() { - module = registerDependencies(new WeakRandomnessModuleImpl()) + module = new WeakRandomnessModuleImpl(dependencies) span = Mock(AgentSpan) { getSpanId() >> 123456 } diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XContentTypeOptionsModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XContentTypeOptionsModuleTest.groovy index dfda4e18cdb..a8d377e968b 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XContentTypeOptionsModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XContentTypeOptionsModuleTest.groovy @@ -1,13 +1,10 @@ package com.datadog.iast.sink -import com.datadog.iast.HasDependencies import com.datadog.iast.IastModuleImplTestBase import com.datadog.iast.IastRequestContext import com.datadog.iast.RequestEndedHandler import com.datadog.iast.model.Vulnerability import com.datadog.iast.model.VulnerabilityType -import com.datadog.iast.overhead.OverheadController -import datadog.trace.api.Config import datadog.trace.api.gateway.Flow import datadog.trace.api.gateway.IGSpanInfo import datadog.trace.api.gateway.RequestContext @@ -15,7 +12,6 @@ import datadog.trace.api.gateway.RequestContextSlot import datadog.trace.api.iast.InstrumentationBridge import datadog.trace.api.internal.TraceSegment import datadog.trace.bootstrap.instrumentation.api.AgentSpan -import datadog.trace.util.stacktrace.StackWalker public class XContentTypeOptionsModuleTest extends IastModuleImplTestBase { @@ -29,7 +25,7 @@ public class XContentTypeOptionsModuleTest extends IastModuleImplTestBase { def setup() { InstrumentationBridge.clearIastModules() - module = registerDependencies(new XContentTypeModuleImpl()) + module = new XContentTypeModuleImpl(dependencies) InstrumentationBridge.registerIastModule(module) objectHolder = [] ctx = new IastRequestContext() @@ -46,13 +42,8 @@ public class XContentTypeOptionsModuleTest extends IastModuleImplTestBase { void 'x content options sniffing vulnerability'() { given: Vulnerability savedVul1 - final OverheadController overheadController = Mock(OverheadController) final iastCtx = Mock(IastRequestContext) iastCtx.getContentType() >> "text/html" - final StackWalker stackWalker = Mock(StackWalker) - final dependencies = new HasDependencies.Dependencies( - Config.get(), reporter, overheadController, stackWalker - ) final handler = new RequestEndedHandler(dependencies) final TraceSegment traceSegment = Mock(TraceSegment) final reqCtx = Mock(RequestContext) @@ -93,15 +84,9 @@ public class XContentTypeOptionsModuleTest extends IastModuleImplTestBase { void 'no x content options sniffing reported'() { given: - Vulnerability savedVul1 - final OverheadController overheadController = Mock(OverheadController) final iastCtx = Mock(IastRequestContext) iastCtx.getxForwardedProto() >> 'https' iastCtx.getContentType() >> "text/html" - final StackWalker stackWalker = Mock(StackWalker) - final dependencies = new HasDependencies.Dependencies( - Config.get(), reporter, overheadController, stackWalker - ) final handler = new RequestEndedHandler(dependencies) final TraceSegment traceSegment = Mock(TraceSegment) final reqCtx = Mock(RequestContext) diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XPathInjectionModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XPathInjectionModuleTest.groovy index 819980331ae..3638b6f431b 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XPathInjectionModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XPathInjectionModuleTest.groovy @@ -23,7 +23,7 @@ class XPathInjectionModuleTest extends IastModuleImplTestBase { private IastRequestContext ctx def setup() { - module = registerDependencies(new XPathInjectionModuleImpl()) + module = new XPathInjectionModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XssModuleTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XssModuleTest.groovy index 6722b3faf3c..bbebbceae97 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XssModuleTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XssModuleTest.groovy @@ -26,7 +26,7 @@ class XssModuleTest extends IastModuleImplTestBase { private IastRequestContext ctx def setup() { - module = registerDependencies(new XssModuleImpl()) + module = new XssModuleImpl(dependencies) objectHolder = [] ctx = new IastRequestContext() final reqCtx = Mock(RequestContext) { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/telemetry/AbstractTelemetryCallbackTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/telemetry/AbstractTelemetryCallbackTest.groovy index aefaf6c46a1..92f03e910d2 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/telemetry/AbstractTelemetryCallbackTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/telemetry/AbstractTelemetryCallbackTest.groovy @@ -1,7 +1,7 @@ package com.datadog.iast.telemetry -import com.datadog.iast.HasDependencies.Dependencies +import com.datadog.iast.Dependencies import com.datadog.iast.IastModuleImplTestBase import datadog.trace.api.Config import datadog.trace.api.gateway.RequestContext diff --git a/dd-java-agent/agent-iast/src/testFixtures/groovy/com/datadog/iast/test/NoopOverheadController.groovy b/dd-java-agent/agent-iast/src/testFixtures/groovy/com/datadog/iast/test/NoopOverheadController.groovy index 74964a13634..32152663dc1 100644 --- a/dd-java-agent/agent-iast/src/testFixtures/groovy/com/datadog/iast/test/NoopOverheadController.groovy +++ b/dd-java-agent/agent-iast/src/testFixtures/groovy/com/datadog/iast/test/NoopOverheadController.groovy @@ -2,6 +2,7 @@ package com.datadog.iast.test import com.datadog.iast.overhead.Operation import com.datadog.iast.overhead.OverheadController +import com.github.javaparser.quality.Nullable import datadog.trace.bootstrap.instrumentation.api.AgentSpan import groovy.transform.CompileStatic @@ -18,12 +19,12 @@ class NoopOverheadController implements OverheadController { } @Override - boolean hasQuota(Operation operation, AgentSpan span) { + boolean hasQuota(Operation operation, @Nullable AgentSpan span) { true } @Override - boolean consumeQuota(Operation operation, AgentSpan span) { + boolean consumeQuota(Operation operation, @Nullable AgentSpan span) { true } diff --git a/internal-api/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java b/internal-api/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java index d5a7e535e2b..255c54ef9b2 100644 --- a/internal-api/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java +++ b/internal-api/src/main/java/datadog/trace/api/iast/telemetry/IastMetricCollector.java @@ -79,7 +79,7 @@ public static void add(@Nonnull final IastMetric metric, final int value) { public static void add( @Nonnull final IastMetric metric, final int value, @Nullable final Object ctx) { - add(metric, (byte) -1, value, null); + add(metric, (byte) -1, value, ctx); } /** Prefer using {@link #add(IastMetric, byte, int, Object)} if possible */