@itentialopensource/adapter-utils 5.10.24 → 5.10.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,7 @@ const { HttpsProxyAgent } = require('https-proxy-agent');
32
32
  const { SocksProxyAgent } = require('socks-proxy-agent');
33
33
  const AsyncLockCl = require('async-lock');
34
34
  const FormData = require('form-data');
35
+ const validator = require('validator');
35
36
 
36
37
  const ThrottleCl = require(path.join(__dirname, '/throttle.js'));
37
38
 
@@ -134,6 +135,45 @@ let sslCertFilePath = null;
134
135
 
135
136
  const mfaStepsResults = []; // keeps requested result for each step
136
137
 
138
+ // SSRF Protection: Validate requests to prevent malicious requests
139
+ function validateRequestSecurity(requestHeader, options) {
140
+ const { hostname, port: requestPort, path: requestPath } = requestHeader;
141
+ if (!hostname) {
142
+ throw new Error('Hostname is required');
143
+ }
144
+ if (!requestPort) {
145
+ throw new Error('Port is required');
146
+ }
147
+
148
+ const isValidIP = validator.isIP(hostname);
149
+ let isValidDomain = false;
150
+ if (!isValidIP) {
151
+ // Only validate as FQDN if it's NOT an IP address
152
+ const fqdnOptions = {
153
+ require_tld: false,
154
+ allow_underscores: true,
155
+ ignore_max_length: true
156
+ };
157
+
158
+ isValidDomain = validator.isFQDN(hostname, fqdnOptions);
159
+ }
160
+
161
+ if (!isValidIP && !isValidDomain) {
162
+ throw new Error('Hostname must be a valid IP address or domain name');
163
+ }
164
+
165
+ if (!validator.isPort(String(requestPort))) {
166
+ throw new Error('Invalid port number');
167
+ }
168
+
169
+ if (requestPath && options.maxPathLength && options.maxPathLength > 0) {
170
+ if (requestPath.length > options.maxPathLength) {
171
+ throw new Error(`Path too long (${requestPath.length} > ${options.maxPathLength})`);
172
+ }
173
+ }
174
+ return requestHeader;
175
+ }
176
+
137
177
  /* CONNECTOR ENGINE INTERNAL FUNCTIONS */
138
178
  /** Wait for adapter-mongo to be available.
139
179
  * @summary adapter may load before adapter-mongo but it requires UPDATE: test if dbUtil object can connect.
@@ -644,7 +684,8 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
644
684
  }
645
685
 
646
686
  // make the call to System
647
- const httpRequest = useProt.request(request.header, (res) => {
687
+ const validatedHeader = validateRequestSecurity(request.header, {});
688
+ const httpRequest = useProt.request(validatedHeader, (res) => {
648
689
  let respStr = '';
649
690
  if (res.headers['content-encoding'] !== 'gzip') {
650
691
  res.setEncoding('utf8');
@@ -869,7 +910,18 @@ function makeRequest(request, entitySchema, callProperties, startTrip, attempt,
869
910
  // handle any exception
870
911
  const tripDiff = process.hrtime(roundTTime);
871
912
  const tripEnd = `${Math.round(((tripDiff[0] * NS_PER_SEC) + tripDiff[1]) / 1000000)}ms`;
872
- const errorObj = transUtilInst.checkAndReturn(e, origin, 'Issue during make request');
913
+
914
+ // Check if this is a validation error from validateRequestSecurity
915
+ const isValidationError = e.message && (
916
+ e.message.includes('Hostname is required')
917
+ || e.message.includes('Port is required')
918
+ || e.message.includes('Hostname must be a valid IP address or domain name')
919
+ || e.message.includes('Invalid port number')
920
+ || e.message.includes('Path length exceeds maximum allowed')
921
+ );
922
+
923
+ const errorMessage = isValidationError ? 'Request security validation failed' : 'Issue during make request';
924
+ const errorObj = transUtilInst.checkAndReturn(e, origin, errorMessage);
873
925
  errorObj.metrics = {
874
926
  code: 'translate_error',
875
927
  redirects: attempt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-utils",
3
- "version": "5.10.24",
3
+ "version": "5.10.26",
4
4
  "description": "Itential Adapter Utility Libraries",
5
5
  "scripts": {
6
6
  "postinstall": "node utils/setup.js",
@@ -37,11 +37,12 @@
37
37
  "json-query": "^2.2.2",
38
38
  "jsontoxml": "^1.0.1",
39
39
  "jsonwebtoken": "^9.0.1",
40
- "mongodb": "^3.7.4",
41
40
  "mocha": "^10.7.3",
41
+ "mongodb": "^3.7.4",
42
42
  "readline-sync": "^1.4.10",
43
43
  "socks-proxy-agent": "^8.0.1",
44
44
  "uuid": "^9.0.0",
45
+ "validator": "^13.15.15",
45
46
  "xml2js": "^0.6.0"
46
47
  },
47
48
  "devDependencies": {