Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@newrelic/security-agent

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@newrelic/security-agent - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

lib/instrumentation-security/core/grpc-utils.js

12

CHANGELOG.md

@@ -0,1 +1,13 @@

### v1.3.0 (2024-05-31)
#### Features
* Added route field in security event for API endpoint mapping
#### Bug fixes
* Fix for control commands acknowledgement in security agent
* Added assert for typeof response data in Reflected XSS validation
* Updated @grpc/grpc-js instrumentation to instrument submodules
* Handling to convert header values into string
#### Miscellaneous chores
* Updated log level for critical messages
* Readme update
* (deps-dev): bump axios from 0.21.4 to 1.7.2

@@ -2,0 +14,0 @@ ### v1.2.0 (2024-04-12)

14

lib/instrumentation-security/core/security-metadata.js

@@ -18,4 +18,14 @@ /*

const securityMetadata = {};
const httpRequest = Object.assign({},request);
if(httpRequest.tempFiles){
const rHeaders = request.headers;
try {
Object.keys(rHeaders).forEach(key => {
if (rHeaders[key]) {
rHeaders[key] = String(rHeaders[key]);
}
});
} catch (error) {
}
request.headers = rHeaders;
const httpRequest = Object.assign({}, request);
if (httpRequest.tempFiles) {
delete httpRequest.tempFiles;

@@ -22,0 +32,0 @@ }

8

lib/instrumentation-security/hooks/fs/nr-fs.js

@@ -141,5 +141,5 @@ /*

if (parameters[0].startsWith(DOTDOTSLASH)) {
parameters[0] = agentModule.applicationInfo.serverInfo.deployedApplications[0].deployedPath + SLASH + parameters[0];
parameters[0] = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath + SLASH + parameters[0];
} else if (parameters[0].startsWith(SLASHDOTDOT)) {
parameters[0] = agentModule.applicationInfo.serverInfo.deployedApplications[0].deployedPath + parameters[0];
parameters[0] = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath + parameters[0];
} else {

@@ -351,3 +351,3 @@ parameters[0] = path.resolve(parameters[0]);

filePath = path.resolve(filePath);
const appPath = agentModule.applicationInfo.serverInfo.deployedApplications[0].deployedPath;
const appPath = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath;
const isInPath = isPathInside(filePath, appPath);

@@ -369,3 +369,3 @@ if (typeof filePath === STRING && isInPath) {

filePath = path.resolve(filePath);
const appPath = agentModule.applicationInfo.serverInfo.deployedApplications[0].deployedPath;
const appPath = API.getSecAgent().applicationInfo.serverInfo.deployedApplications[0].deployedPath;
const isInPath = isPathInside(filePath, appPath);

@@ -372,0 +372,0 @@ if (typeof filePath === STRING && isInPath) {

@@ -202,8 +202,37 @@ /*

newrelic.instrument({
moduleName: '@grpc/grpc-js/build/src/server',
isEsm: true,
onRequire: require('./hooks/grpc-js/nr-grpc').wrapServer,
onError: function intrumentErrorHandler(err) {
logger.error(err.message, err.stack)
}
})
newrelic.instrument({
moduleName: '@grpc/grpc-js/build/src/make-client',
isEsm: true,
onRequire: require('./hooks/grpc-js/nr-grpc').wrapMakeClient,
onError: function intrumentErrorHandler(err) {
logger.error(err.message, err.stack)
}
})
newrelic.instrument({
moduleName: '@grpc/grpc-js/build/src/resolving-call',
isEsm: true,
onRequire: require('./hooks/grpc-js/nr-grpc').wrapStartResolve,
onError: function intrumentErrorHandler(err) {
logger.error(err.message, err.stack)
}
})
newrelic.instrument({
moduleName: '@grpc/grpc-js/build/src/call-stream',
isEsm: true,
onRequire: require('./hooks/grpc-js/nr-grpc').wrapStartCall,
onError: function intrumentErrorHandler(err) {
logger.error(err.message, err.stack)
}
})

@@ -19,2 +19,9 @@ /*

NRLogger.info("Starting New Relic Node.js Security Agent ");
try {
if (NRAgent.config.security.enabled){
require('../instrumentation-security');
}
} catch (error) {
logger.error("Error while applying security instrumentation")
}

@@ -173,5 +180,4 @@ const {

if (initialize()) {
require('../instrumentation-security');
initLogger.info("[STEP-6] => Application instrumentation applied successfully");
}
})();

@@ -110,3 +110,3 @@ /*

const LogMessage = require('./LogMessage');
const logMessage = new LogMessage.logMessage("SEVERE", 'Error in creating directory', __filename, error);
const logMessage = new LogMessage.logMessage("DEBUG", 'Error in creating directory', __filename, error);
addLogEventtoBuffer(logMessage);

@@ -292,3 +292,3 @@ }

const LogMessage = require('./LogMessage');
const logMessage = new LogMessage.logMessage("SEVERE", 'Error in processing snapshot files', __filename, error);
const logMessage = new LogMessage.logMessage("DEBUG", 'Error in processing snapshot files', __filename, error);
addLogEventtoBuffer(logMessage);

@@ -295,0 +295,0 @@ }

@@ -10,2 +10,3 @@ /*

const restClient = require('../../restclient');
const grpcClient = require('../../grpcClient');
const { Agent } = require('../../../agent');

@@ -24,5 +25,2 @@ const { FuzzFailEvent } = require('../../../FuzzFailEvent');

const {
IS_LAMBDA_ENV,
AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER } = require('../../../sec-agent-constants');
const statusUtils = require('../../../statusUtils');

@@ -58,3 +56,3 @@

}
iastIntervalConst = setInterval(() => {

@@ -131,10 +129,13 @@ let data = IASTUtil.generateIASTDataRequest();

try {
if (IS_LAMBDA_ENV) {
const qualifiedARN = Agent.getAgent().applicationInfo.applicationUUID;
const splitArn = String.prototype.split.call(qualifiedARN, ':');
const arn = splitArn.slice(0, splitArn.length - 1).join(':');
const ver = process.env[AWS_LAMBDA_FUNCTION_VERSION_ENV_IDENTIFIER];
logger.info('Invoking Lambda:: ARN: ' + arn);
logger.info('Invoking Lambda:: Version: ' + ver);
if (fuzzRequest.protocol == 'grpc') {
const config = parseGRPCRequestToFuzz(fuzzRequest);
config.headers['nr-csec-parent-id'] = fuzzRequest.id;
IASTUtil.completedRequestsMapInit(fuzzRequest.id);
grpcClient.fireRequest(config);
if (fuzzRequest.headers && fuzzRequest.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
logScannedApiId(fuzzRequest.headers[NR_CSEC_FUZZ_REQUEST_ID], fuzzRequest.requestURI)
}
IASTUtil.removePendingRequestId(fuzzRequest.id);
} else {

@@ -160,3 +161,2 @@ const config = parseAxiosHttpRequestToFuzz(fuzzRequest);

logger.info('Firing http request:: URL: ' + config.url);
const response = restClient.fireRequest(config);

@@ -218,2 +218,22 @@ handleFuzzResponse(response, fuzzDetails);

/**
* Parses the passed fuzz request object to
* Axios config.
*
* @param {JSON} requestObject
*/
function parseGRPCRequestToFuzz(requestObject) {
let serverName = requestObject.serverName ? requestObject.serverName : LOCALHOST;
let host = serverName + COLON + requestObject.serverPort
return {
url: requestObject.protocol + COLON_SLASH_SLASH + host + requestObject.url,
requestURI: requestObject.requestURI,
protocol: requestObject.protocol,
serverPort: requestObject.serverPort,
method: requestObject.method,
data: requestObject.body,
headers: requestObject.headers,
timeout: 5000,
};
}

@@ -220,0 +240,0 @@

@@ -34,2 +34,5 @@ /*

let data = completedRequestsMap.get(id);
if(!data){
return;
}
data.push(eventId);

@@ -36,0 +39,0 @@ completedRequestsMap.set(id, data);

@@ -21,3 +21,3 @@ /*

initLogger.info('Security Agent is now ACTIVE for', applicationInfoModule.getInstance().applicationUUID);
const logMessage = new LogMessage.logMessage("SEVERE", `Security Agent is ACTIVE for ${ applicationInfoModule.getInstance().applicationUUID}`, __filename, null);
const logMessage = new LogMessage.logMessage("INFO", `Security Agent is ACTIVE for ${ applicationInfoModule.getInstance().applicationUUID}`, __filename, null);
require('../../../commonUtils').addLogEventtoBuffer(logMessage);

@@ -24,0 +24,0 @@

@@ -107,2 +107,3 @@ /*

initLogger.info(`Connecting to Validator at ${validatorService}`);
IASTUtil.IASTCleanup();
let cert = ''

@@ -142,2 +143,3 @@ try {

logger.warn("WS connection closed");
this.obeyReconnect();
})

@@ -177,3 +179,3 @@ this.instance = webSocket;

initTimeOut = setTimeout(() => {
IASTUtil.IASTCleanup();
logger.debug("Terminating ws instance and reconnecting");

@@ -195,3 +197,5 @@ try {

let timeDiffInPing = (currentTime - lastPongtime) / 1000;
if (timeDiffInPing > 40 && lastPongtime != 0) {
logger.debug("Websocket ready state is:",self.instance.readyState)
if (timeDiffInPing > 40 && lastPongtime != 0 && self.instance.readyState > 1) {
self.obeyReconnect();

@@ -201,2 +205,3 @@ lastPongtime = 0;

}
try {

@@ -208,3 +213,3 @@ await promisify(self.instance, self.instance.ping)(ACK, true, function (err) {

statusUtils.addErrortoBuffer(err);
self.obeyReconnect();
}

@@ -267,3 +272,3 @@ });

});
})
} catch (error) {

@@ -270,0 +275,0 @@ logger.debug(LOG_MESSAGES.ERROR_WHILE_SEND_EVENT, eventStr, error);

@@ -104,2 +104,3 @@ /*

event.metaData.isClientDetectedFromXFF = isClientDetectedFromXFF;
event.httpRequest.route = uri;
return event;

@@ -106,0 +107,0 @@ } catch (e) {

@@ -101,3 +101,3 @@ /*

const LogMessage = require('./LogMessage');
const logMessage = new LogMessage.logMessage("SEVERE", 'Error in creating snapshot file', __filename, err);
const logMessage = new LogMessage.logMessage("DEBUG", 'Error in creating snapshot file', __filename, err);
commonUtils.addLogEventtoBuffer(logMessage);

@@ -104,0 +104,0 @@ } else {

@@ -85,3 +85,3 @@ /*

const dispatcher = NRAgent.environment.get('Dispatcher')[0];
const logMessage = new LogMessage.logMessage("SEVERE", `Detected framework: ${framework} and dispatcher: ${dispatcher}`, __filename, null);
const logMessage = new LogMessage.logMessage("INFO", `Detected framework: ${framework} and dispatcher: ${dispatcher}`, __filename, null);
commonUtils.addLogEventtoBuffer(logMessage);

@@ -88,0 +88,0 @@ } catch (error) {

@@ -13,2 +13,3 @@ /*

const htmlEntities = require('html-entities');
const { STRING } = require('./sec-agent-constants');

@@ -140,6 +141,11 @@ const tagNameRegex = /<([a-zA-Z_-]+[0-9]*|!--)/gmi;

const attackConstructs = new Set();
for (const data of combinedData) {
const constructs = getXSSConstructs(data);
constructs.forEach(attackConstructs.add, attackConstructs);
try {
for (const data of combinedData) {
const constructs = getXSSConstructs(data);
constructs.forEach(attackConstructs.add, attackConstructs);
}
} catch (error) {
logger.debug("Error while getting rxss constucts:", error);
}
return attackConstructs;

@@ -157,3 +163,3 @@ }

let attribMatcher;
while (currPos < data.length) {
while (currPos < data.length && typeof data == STRING ) {
let tagName;

@@ -239,3 +245,3 @@

if (data.charAt(currPos) !== ANGLE_END_CHAR) {
if (typeof data == STRING && data.charAt(currPos) !== ANGLE_END_CHAR) {
const tmp = data.indexOf(ANGLE_END, currPos);

@@ -242,0 +248,0 @@ if (tmp !== -1) {

{
"name": "@newrelic/security-agent",
"version": "1.2.0",
"version": "1.3.0",
"description": "New Relic Security Agent for Node.js",

@@ -61,2 +61,3 @@ "main": "index.js",

"devDependencies": {
"@grpc/proto-loader": "^0.7.10",
"@hapi/hapi": "^21.3.0",

@@ -63,0 +64,0 @@ "@koa/router": "^12.0.0",

@@ -102,3 +102,3 @@ # New Relic Node.js security agent

Any feedback provided to New Relic about the New Relic security agent, including feedback provided as source code, comments, or other copyrightable or patentable material, is provided to New Relic under the terms of the Apache Software License, version 2. If you do not provide attribution information or a copy of the license with your feedback, you waive the performance of those requirements of the Apache License with respect to New Relic. The license grant regarding any feedback is irrevocable and persists past the termination of the preview license.
Any feedback provided to New Relic about the New Relic security agent, including feedback provided as source code, comments, or other copyrightable or patentable material, is provided to New Relic under the terms of the New Relic Software License v1.0. If you do not provide attribution information or a copy of the license with your feedback, you waive the performance of those requirements of the New Relic Software License v1.0 with respect to New Relic. The license grant regarding any feedback is irrevocable.
Keep in mind that when you submit a pull request or other feedback, you’ll need to sign the CLA via the click-through using CLA-Assistant. You only have to sign the CLA one time per project.

@@ -105,0 +105,0 @@ If you have any questions drop us an email at opensource@newrelic.com.

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc