Skip to content

Commit c10350f

Browse files
authored
Merge pull request #404 from newrelic/release/v1.7.0
CSEC Java Agent Version 1.7.0
2 parents 52239d3 + 404a672 commit c10350f

File tree

13 files changed

+38
-15
lines changed

13 files changed

+38
-15
lines changed

Changelog.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Noteworthy changes to the agent are documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [1.7.0] - TBD
7+
## [1.7.0] - 2025-4-25
88
### Adds
99
- [PR-395](https://github.com/newrelic/csec-java-agent/pull/395) **Support for Deserialization Vulnerability Detection**: Implemented mechanisms to detect vulnerabilities arising from unsafe deserialization processes.
1010
- [PR-395](https://github.com/newrelic/csec-java-agent/pull/395) **Support for Vulnerability Detection of Remote Code Invocation via Reflection**: Enhanced capability to identify security risks associated with remote code execution through reflection.
@@ -16,8 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- [PR-403](https://github.com/newrelic/csec-java-agent/pull/403) GraphQL Supported Version Range: Restricted the supported version range for GraphQL due to the release of a new version on April 7th, 2025
1717

1818
### Fixes
19-
- [PR-372](https://github.com/newrelic/csec-java-agent/pull/372) **Repeat IAST Request Relay Commands**: Reconfigured logic to repeat IAST control commands until the endpoint is confirmed.
19+
- [PR-372](https://github.com/newrelic/csec-java-agent/pull/372) **Repeat IAST Request Replay Commands**: Reconfigured logic to repeat IAST control commands until the endpoint is confirmed.
2020

21+
### Note
22+
- The instrumentation for the module `com.newrelic.instrumentation.security.java-reflection` is disabled by default. This is due to its impact on CPU utilization, which can significantly increase when the module is active.
23+
- **Action Required**: To detect unsafe reflection vulnerabilities effectively, enable the `com.newrelic.instrumentation.security.java-reflection` module.
2124

2225
## [1.6.1] - 2025-3-1
2326
### Adds

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# The agent version.
2-
agentVersion=1.6.1
2+
agentVersion=1.7.0
33
jsonVersion=1.2.11
44
# Updated exposed NR APM API version.
55
nrAPIVersion=8.12.0

instrumentation-security/java-reflection/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ dependencies {
88

99

1010
jar {
11-
manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.java-reflection' }
11+
manifest { attributes 'Implementation-Title': 'com.newrelic.instrumentation.security.java-reflection', 'Enabled': 'false' }
1212
}
1313

1414
verifyInstrumentation {

instrumentation-security/jersey-2.16/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public abstract class ContainerResponse_Instrumentation {
4444
public void close() {
4545
boolean isLockAcquired = false;
4646
try {
47-
isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK);
47+
isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK);
4848
if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) {
4949
HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext());
5050
}

instrumentation-security/jersey-2/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation {
4343
public void close() {
4444
boolean isLockAcquired = false;
4545
try {
46-
isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK);
46+
isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK);
4747
if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) {
4848
HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext());
4949
}

instrumentation-security/jersey-3/src/main/java/com/newrelic/agent/security/instrumentation/jersey2/ContainerResponse_Instrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public abstract class ContainerResponse_Instrumentation {
4343
public void close() {
4444
boolean isLockAcquired = false;
4545
try {
46-
isLockAcquired = GenericHelper.acquireLockIfPossible(VulnerabilityCaseType.REFLECTED_XSS, SERVLET_GET_IS_OPERATION_LOCK);
46+
isLockAcquired = GenericHelper.acquireLockIfPossible(SERVLET_GET_IS_OPERATION_LOCK);
4747
if(isLockAcquired && GenericHelper.isLockAcquired(HttpRequestHelper.getNrSecCustomAttribForPostProcessing())) {
4848
HttpRequestHelper.postProcessSecurityHook(this.getClass().getName(), getWrappedMessageContext());
4949
}

instrumentation-security/mule-3.6/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
@Weave(type = MatchType.ExactClass, originalName = "org.mule.module.http.internal.domain.response.HttpResponseBuilder")
2020
public class HttpResponseBuilder_Instrumentation {
2121

22-
private final ResponseStatus responseStatus = Weaver.callOriginal();
23-
private final HttpEntity body = Weaver.callOriginal();
22+
private ResponseStatus responseStatus = Weaver.callOriginal();
23+
private HttpEntity body = Weaver.callOriginal();
2424

2525
public HttpResponse build() {
2626
HttpResponse response = Weaver.callOriginal();

instrumentation-security/mule-3.7/src/main/java/org/mule/module/http/internal/domain/response/HttpResponseBuilder_Instrumentation.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
@Weave(type = MatchType.ExactClass, originalName = "org.mule.module.http.internal.domain.response.HttpResponseBuilder")
2020
public class HttpResponseBuilder_Instrumentation {
2121

22-
private final ResponseStatus responseStatus = Weaver.callOriginal();
23-
private final HttpEntity body = Weaver.callOriginal();
22+
private ResponseStatus responseStatus = Weaver.callOriginal();
23+
private HttpEntity body = Weaver.callOriginal();
2424

2525
public HttpResponse build() {
2626
HttpResponse response = Weaver.callOriginal();

instrumentation-security/servlet-2.4/src/main/java/javax/servlet/http/HttpServletResponse_Instrumentation.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public void addCookie(Cookie cookie){
3737
releaseLock(cookie.hashCode());
3838
}
3939
}
40+
if (isOwaspHookEnabled) {
41+
registerExitOperation(isLockAcquired, operation);
42+
}
4043
}
4144

4245
private AbstractOperation preprocessSecurityHook(Cookie cookie, String className, String methodName) {
@@ -78,6 +81,17 @@ private AbstractOperation preprocessSecurityHook(Cookie cookie, String className
7881
return null;
7982
}
8083

84+
private static void registerExitOperation(boolean isProcessingAllowed, AbstractOperation operation) {
85+
try {
86+
if (operation == null || !isProcessingAllowed || !NewRelicSecurity.isHookProcessingActive() || NewRelicSecurity.getAgent().getSecurityMetaData().getRequest().isEmpty()) {
87+
return;
88+
}
89+
NewRelicSecurity.getAgent().registerExitEvent(operation);
90+
} catch (Throwable e) {
91+
NewRelicSecurity.getAgent().log(LogLevel.FINEST, String.format(GenericHelper.EXIT_OPERATION_EXCEPTION_MESSAGE, HttpServletHelper.SERVLET_2_4, e.getMessage()), e, HttpServletResponse_Instrumentation.class.getName());
92+
}
93+
}
94+
8195
private void releaseLock(int hashCode) {
8296
GenericHelper.releaseLock(ServletHelper.NR_SEC_HTTP_SERVLET_RESPONSE_ATTRIB_NAME, hashCode);
8397
}

instrumentation-security/servlet-2.4/src/test/java/com/nr/agent/security/instrumentation/servlet24/HttpSessionTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public void testSessionSetAttribute() throws IOException, URISyntaxException {
3535
SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector();
3636
List<AbstractOperation> operations = introspector.getOperations();
3737
Assert.assertTrue("No operations detected", operations.size() > 0);
38-
Assert.assertTrue("Unexpected operation count detected", operations.size() == 2 || operations.size() == 3);
3938
TrustBoundaryOperation targetOperation = null;
4039
int i=0;
4140
for (AbstractOperation operation : operations) {
@@ -65,7 +64,6 @@ public void testSessionPutValue() throws IOException, URISyntaxException {
6564
SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector();
6665
List<AbstractOperation> operations = introspector.getOperations();
6766
Assert.assertFalse(operations.isEmpty());
68-
Assert.assertTrue("Unexpected operation count detected", operations.size() == 2 || operations.size() == 3);
6967
TrustBoundaryOperation targetOperation = null;
7068
for (AbstractOperation operation : operations) {
7169
if (operation instanceof TrustBoundaryOperation)
@@ -86,7 +84,6 @@ public void testAddCookie() throws IOException, URISyntaxException {
8684
SecurityIntrospector introspector = SecurityInstrumentationTestRunner.getIntrospector();
8785
List<AbstractOperation> operations = introspector.getOperations();
8886
Assert.assertTrue("No operations detected", operations.size() > 0);
89-
Assert.assertTrue("Unexpected operation count detected", operations.size() == 1 || operations.size() == 2);
9087
SecureCookieOperationSet targetOperation = null;
9188
targetOperation = verifySecureCookieOp(operations);
9289

newrelic-security-agent/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ tasks.register('generate-sbom') {
203203
def parsedJson = new JsonSlurper().parseText(req.getInputStream().getText())
204204

205205
try {
206+
if (!project.buildDir.exists()) {
207+
mkdir project.buildDir;
208+
}
206209
def reportsDir = Paths.get("$buildDir", "reports")
207210
def sbomFile = new File("$buildDir/reports", "SBOM.json")
208211
if (Files.exists(reportsDir) || Files.createDirectory(reportsDir)) {

newrelic-security-agent/src/main/java/com/newrelic/agent/security/AgentConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ private String applyRequiredLogLevel() {
318318
if(value instanceof Boolean) {
319319
logLevel = IUtilConstants.OFF;
320320
} else {
321-
logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, LogLevel.FINEST.name());
321+
logLevel = NewRelic.getAgent().getConfig().getValue(IUtilConstants.NR_LOG_LEVEL, IUtilConstants.INFO);
322322
}
323323

324324
try {

newrelic-security-api-test-impl/src/main/java/com/newrelic/api/agent/security/Agent.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.newrelic.api.agent.security.schema.ServerConnectionConfiguration;
99
import com.newrelic.api.agent.security.schema.operation.FileIntegrityOperation;
1010
import com.newrelic.api.agent.security.schema.operation.FileOperation;
11+
import com.newrelic.api.agent.security.schema.operation.SecureCookieOperationSet;
1112
import com.newrelic.api.agent.security.schema.policy.AgentPolicy;
1213
import com.newrelic.api.agent.security.schema.policy.IastDetectionCategory;
1314
import com.newrelic.api.agent.security.utils.logging.LogLevel;
@@ -85,6 +86,8 @@ public void registerOperation(AbstractOperation operation) {
8586
return;
8687
}
8788
operation.setApiID(apiId);
89+
String executionId = "dummy-exec-id";
90+
operation.setExecutionId(executionId);
8891
operation.setStartTime(Instant.now().toEpochMilli());
8992
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
9093
operation.setStackTrace(Arrays.copyOfRange(trace, 1, trace.length));
@@ -93,6 +96,9 @@ public void registerOperation(AbstractOperation operation) {
9396

9497
@Override
9598
public void registerExitEvent(AbstractOperation operation) {
99+
if (operation instanceof SecureCookieOperationSet) {
100+
this.getSecurityMetaData().getCustomAttribute(OPERATIONS, List.class).add(operation);
101+
}
96102
this.getSecurityMetaData().getCustomAttribute(EXIT_OPERATIONS, List.class).add(operation);
97103
}
98104

0 commit comments

Comments
 (0)