Skip to content

Commit 325a854

Browse files
authored
Merge branch 'master' into munir/otlp-trace-metrics-fixes
2 parents 43eb7e9 + f543555 commit 325a854

36 files changed

Lines changed: 1958 additions & 1277 deletions

File tree

‎.github/CODEOWNERS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
/dd-java-agent/instrumentation/snakeyaml-1.33/ @DataDog/asm-java
7979
/dd-java-agent/instrumentation/velocity-1.5/ @DataDog/asm-java
8080
/dd-java-agent/instrumentation/freemarker/ @DataDog/asm-java
81+
/dd-java-agent/instrumentation/beanshell-2.0/ @DataDog/asm-java
8182
/dd-java-agent/instrumentation/datadog/asm/ @DataDog/asm-java
8283
/dd-smoke-tests/apm-tracing-disabled/ @DataDog/asm-java
8384
/dd-smoke-tests/appsec/ @DataDog/asm-java

‎.github/workflows/analyze-changes.yaml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
${{ runner.os }}-gradle-
3131
3232
- name: Initialize CodeQL
33-
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
33+
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
3434
with:
3535
languages: 'java'
3636
build-mode: 'manual'
@@ -43,7 +43,7 @@ jobs:
4343
./gradlew clean :dd-java-agent:shadowJar --build-cache --parallel --stacktrace --no-daemon --max-workers=4
4444
4545
- name: Perform CodeQL Analysis and upload results to GitHub Security tab
46-
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
46+
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
4747

4848
trivy:
4949
name: Analyze changes with Trivy
@@ -104,7 +104,7 @@ jobs:
104104
TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db
105105

106106
- name: Upload Trivy scan results to GitHub Security tab
107-
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
107+
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
108108
if: always()
109109
with:
110110
sarif_file: 'trivy-results.sarif'

‎.github/workflows/prune-old-pull-requests.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
pull-requests: write
1414
steps:
1515
- name: Prune old pull requests
16-
uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
16+
uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
1717
with:
1818
days-before-stale: -1 # Disable general stale bot
1919
days-before-pr-stale: 90 # Only enable stale bot for PRs with no activity for 90 days

‎.github/workflows/update-gradle-dependencies.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
with:
2626
submodules: "recursive"
2727

28-
- uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
28+
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
2929
with:
3030
distribution: 'temurin'
3131
java-version: '21'

‎.gitlab/exploration-tests.yml‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,19 @@ build-exploration-tests-image:
77
needs: []
88
tags: [ "arch:amd64" ]
99
image: $REGISTRY/docker:27.3.1
10+
id_tokens:
11+
DDSIGN_ID_TOKEN:
12+
aud: image-integrity
1013
script:
11-
- docker buildx build --tag $EXPLORATION_TESTS_IMAGE -f dd-java-agent/agent-debugger/exploration-tests/Dockerfile.exploration-tests --push dd-java-agent/agent-debugger/exploration-tests
14+
- METADATA_FILE=$(mktemp)
15+
- >
16+
docker buildx build
17+
--tag $EXPLORATION_TESTS_IMAGE
18+
--file dd-java-agent/agent-debugger/exploration-tests/Dockerfile.exploration-tests
19+
--push
20+
--metadata-file ${METADATA_FILE}
21+
dd-java-agent/agent-debugger/exploration-tests
22+
- ddsign sign $EXPLORATION_TESTS_IMAGE --docker-metadata-file ${METADATA_FILE}
1223

1324
.common-exploration-tests: &common-exploration-tests
1425
rules:

‎dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/symbol/SymbolAggregator.java‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.datadog.debugger.sink.SymbolSink;
66
import datadog.instrument.utils.ClassNameTrie;
7+
import datadog.trace.api.internal.VisibleForTesting;
78
import datadog.trace.bootstrap.debugger.DebuggerContext;
89
import datadog.trace.util.AgentTaskScheduler;
910
import datadog.trace.util.Strings;
@@ -28,6 +29,7 @@
2829
import java.util.concurrent.TimeUnit;
2930
import java.util.jar.JarEntry;
3031
import java.util.jar.JarFile;
32+
import java.util.stream.Stream;
3133
import org.slf4j.Logger;
3234
import org.slf4j.LoggerFactory;
3335

@@ -206,7 +208,7 @@ public void scanJar(
206208
scanDirectory(jarPath, alreadyScannedJars, baos, buffer, symDBReport);
207209
} else {
208210
try {
209-
try (JarFile jarFile = new JarFile(jarPathFile)) {
211+
try (JarFile jarFile = openJarFile(jarPathFile)) {
210212
jarFile.stream()
211213
.filter(jarEntry -> jarEntry.getName().endsWith(".class"))
212214
.filter(
@@ -225,14 +227,19 @@ public void scanJar(
225227
alreadyScannedJars.add(jarPath.toString());
226228
}
227229

230+
@VisibleForTesting
231+
JarFile openJarFile(File file) throws IOException {
232+
return new JarFile(file);
233+
}
234+
228235
private void scanDirectory(
229236
Path jarPath,
230237
Set<String> alreadyScannedJars,
231238
ByteArrayOutputStream baos,
232239
byte[] buffer,
233240
SymDBReport symDBReport) {
234-
try {
235-
Files.walk(jarPath)
241+
try (Stream<Path> paths = Files.walk(jarPath)) {
242+
paths
236243
// explicitly no follow links walking the directory to avoid cycles
237244
.filter(path -> Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS))
238245
.filter(path -> path.toString().endsWith(".class"))
@@ -276,11 +283,14 @@ private void parseJarEntry(
276283
byte[] buffer) {
277284
LOGGER.debug("parsing jarEntry class: {}", jarEntry.getName());
278285
try {
279-
InputStream inputStream = jarFile.getInputStream(jarEntry);
280-
int readBytes;
281-
baos.reset();
282-
while ((readBytes = inputStream.read(buffer)) != -1) {
283-
baos.write(buffer, 0, readBytes);
286+
// must be closed so the JarFile returns its Inflater to the cache instead of allocating a
287+
// new native zlib context per entry
288+
try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
289+
int readBytes;
290+
baos.reset();
291+
while ((readBytes = inputStream.read(buffer)) != -1) {
292+
baos.write(buffer, 0, readBytes);
293+
}
284294
}
285295
parseClass(symDBReport, jarEntry.getName(), baos.toByteArray(), jarPath.toString());
286296
} catch (IOException ex) {

‎dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/symbol/SymbolAggregatorTest.java‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@
1515

1616
import com.datadog.debugger.sink.SymbolSink;
1717
import com.datadog.debugger.util.ClassNameFiltering;
18+
import java.io.ByteArrayOutputStream;
19+
import java.io.File;
20+
import java.io.FilterInputStream;
21+
import java.io.IOException;
22+
import java.io.InputStream;
1823
import java.net.URL;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
1926
import java.security.CodeSource;
2027
import java.security.ProtectionDomain;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
import java.util.jar.JarFile;
30+
import java.util.zip.ZipEntry;
2131
import org.junit.jupiter.api.Test;
2232
import org.junit.jupiter.api.condition.DisabledIf;
2333
import org.mockito.ArgumentCaptor;
@@ -76,6 +86,45 @@ void testScanQueuedCorruptedJars() {
7686
captor.getAllValues().get(2));
7787
}
7888

89+
@Test
90+
void testScanJarClosesEntryStreams() throws Exception {
91+
SymbolSink symbolSink = mock(SymbolSink.class);
92+
CountingJarFile[] holder = new CountingJarFile[1];
93+
SymbolAggregator symbolAggregator =
94+
new SymbolAggregator(ClassNameFiltering.allowAll(), emptyList(), symbolSink, 1) {
95+
@Override
96+
JarFile openJarFile(File file) throws IOException {
97+
return holder[0] = new CountingJarFile(file);
98+
}
99+
};
100+
Path jarPath = Paths.get(getClass().getResource("/debugger-symbol.jar").toURI());
101+
symbolAggregator.scanJar(
102+
SymDBReport.NO_OP, jarPath, new ByteArrayOutputStream(8192), new byte[4096]);
103+
assertTrue(holder[0].opened.get() > 0);
104+
assertEquals(holder[0].opened.get(), holder[0].closed.get());
105+
}
106+
107+
private static class CountingJarFile extends JarFile {
108+
final AtomicInteger opened = new AtomicInteger();
109+
final AtomicInteger closed = new AtomicInteger();
110+
111+
CountingJarFile(File file) throws IOException {
112+
super(file);
113+
}
114+
115+
@Override
116+
public synchronized InputStream getInputStream(ZipEntry ze) throws IOException {
117+
opened.incrementAndGet();
118+
return new FilterInputStream(super.getInputStream(ze)) {
119+
@Override
120+
public void close() throws IOException {
121+
closed.incrementAndGet();
122+
super.close();
123+
}
124+
};
125+
}
126+
}
127+
79128
@Test
80129
@DisabledIf(
81130
value = "datadog.environment.JavaVirtualMachine#isJ9",

‎dd-java-agent/agent-iast/build.gradle‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ dependencies {
5151
testImplementation project(':dd-java-agent:agent-bootstrap')
5252
testImplementation('org.skyscreamer:jsonassert:1.5.1')
5353
testImplementation(libs.bytebuddy)
54+
testImplementation libs.bundles.mockito
5455

5556
testImplementation(libs.groovy.yaml)
5657

‎dd-java-agent/agent-iast/src/main/java/com/datadog/iast/IastSystem.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.datadog.iast.propagation.StringModuleImpl;
1111
import com.datadog.iast.securitycontrol.IastSecurityControlTransformer;
1212
import com.datadog.iast.sink.ApplicationModuleImpl;
13+
import com.datadog.iast.sink.CodeInjectionModuleImpl;
1314
import com.datadog.iast.sink.CommandInjectionModuleImpl;
1415
import com.datadog.iast.sink.EmailInjectionModuleImpl;
1516
import com.datadog.iast.sink.HardcodedSecretModuleImpl;
@@ -187,7 +188,8 @@ private static Stream<IastModule> iastModules(
187188
InsecureAuthProtocolModuleImpl.class,
188189
ReflectionInjectionModuleImpl.class,
189190
UntrustedDeserializationModuleImpl.class,
190-
EmailInjectionModuleImpl.class);
191+
EmailInjectionModuleImpl.class,
192+
CodeInjectionModuleImpl.class);
191193
if (iast != FULLY_ENABLED) {
192194
modules = modules.filter(IastSystem::isOptOut);
193195
}

‎dd-java-agent/agent-iast/src/main/java/com/datadog/iast/model/VulnerabilityType.java‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.datadog.iast.model;
22

33
import static com.datadog.iast.util.CRCUtils.update;
4+
import static datadog.trace.api.iast.VulnerabilityMarks.CODE_INJECTION_MARK;
45
import static datadog.trace.api.iast.VulnerabilityMarks.COMMAND_INJECTION_MARK;
56
import static datadog.trace.api.iast.VulnerabilityMarks.EMAIL_HTML_INJECTION_MARK;
67
import static datadog.trace.api.iast.VulnerabilityMarks.HEADER_INJECTION_MARK;
@@ -171,6 +172,9 @@ public interface VulnerabilityType {
171172
.excludedSources(Builder.DB_EXCLUDED)
172173
.build();
173174

175+
VulnerabilityType CODE_INJECTION =
176+
type(VulnerabilityTypes.CODE_INJECTION).mark(CODE_INJECTION_MARK).build();
177+
174178
/* All vulnerability types that have a mark. Should be updated if new vulnerabilityType with mark is added */
175179
VulnerabilityType[] MARKED_VULNERABILITIES = {
176180
SQL_INJECTION,
@@ -185,7 +189,8 @@ public interface VulnerabilityType {
185189
HEADER_INJECTION,
186190
REFLECTION_INJECTION,
187191
UNTRUSTED_DESERIALIZATION,
188-
EMAIL_HTML_INJECTION
192+
EMAIL_HTML_INJECTION,
193+
CODE_INJECTION
189194
};
190195

191196
String name();

0 commit comments

Comments
 (0)