diff --git a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts index d055f7284..adc8af829 100644 --- a/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts +++ b/packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts @@ -1,4 +1,9 @@ -import { INodeExecutionData, IOAuth2Options } from 'n8n-workflow'; +import { IDataObject, INodeExecutionData, IOAuth2Options } from 'n8n-workflow'; +import { OptionsWithUri } from 'request-promise-native'; + +export type IAuthDataSanitizeKeys = { + [key: string]: string[]; +}; export const replaceNullValues = (item: INodeExecutionData) => { if (item.json === null) { @@ -7,6 +12,37 @@ export const replaceNullValues = (item: INodeExecutionData) => { return item; }; +export function sanitizeUiMessage(request: OptionsWithUri, authDataKeys: IAuthDataSanitizeKeys) { + let sendRequest = request as unknown as IDataObject; + + // Protect browser from sending large binary data + if (Buffer.isBuffer(sendRequest.body) && sendRequest.body.length > 250000) { + sendRequest = { + ...request, + body: `Binary data got replaced with this text. Original was a Buffer with a size of ${request.body.length} byte.`, + }; + } + + // Remove credential information + for (const requestProperty of Object.keys(authDataKeys)) { + sendRequest = { + ...sendRequest, + [requestProperty]: Object.keys(sendRequest[requestProperty] as object).reduce( + // eslint-disable-next-line @typescript-eslint/no-loop-func + (acc: IDataObject, curr) => { + acc[curr] = authDataKeys[requestProperty].includes(curr) + ? '** hidden **' + : (sendRequest[requestProperty] as IDataObject)[curr]; + return acc; + }, + {}, + ), + }; + } + + return sendRequest; +} + export const getOAuth2AdditionalParameters = (nodeCredentialType: string) => { const oAuth2Options: { [credentialType: string]: IOAuth2Options } = { bitlyOAuth2Api: { diff --git a/packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts b/packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts index 2849d0931..7965e5493 100644 --- a/packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts @@ -13,7 +13,7 @@ import { } from 'n8n-workflow'; import { OptionsWithUri } from 'request'; -import { replaceNullValues } from '../GenericFunctions'; +import { IAuthDataSanitizeKeys, replaceNullValues, sanitizeUiMessage } from '../GenericFunctions'; interface OptionData { name: string; @@ -914,21 +914,26 @@ export class HttpRequestV1 implements INodeType { requestOptions.headers['Content-Type'] = options.bodyContentCustomMimeType; } + const authDataKeys: IAuthDataSanitizeKeys = {}; + // Add credentials if any are set if (httpBasicAuth !== undefined) { requestOptions.auth = { user: httpBasicAuth.user as string, pass: httpBasicAuth.password as string, }; + authDataKeys.auth = ['pass']; } if (httpHeaderAuth !== undefined) { requestOptions.headers![httpHeaderAuth.name as string] = httpHeaderAuth.value; + authDataKeys.headers = [httpHeaderAuth.name as string]; } if (httpQueryAuth !== undefined) { if (!requestOptions.qs) { requestOptions.qs = {}; } requestOptions.qs[httpQueryAuth.name as string] = httpQueryAuth.value; + authDataKeys.qs = [httpQueryAuth.name as string]; } if (httpDigestAuth !== undefined) { requestOptions.auth = { @@ -936,6 +941,7 @@ export class HttpRequestV1 implements INodeType { pass: httpDigestAuth.password as string, sendImmediately: false, }; + authDataKeys.auth = ['pass']; } if (requestOptions.headers!.accept === undefined) { @@ -951,15 +957,7 @@ export class HttpRequestV1 implements INodeType { } try { - let sendRequest: any = requestOptions; - // Protect browser from sending large binary data - if (Buffer.isBuffer(sendRequest.body) && sendRequest.body.length > 250000) { - sendRequest = { - ...requestOptions, - body: `Binary data got replaced with this text. Original was a Buffer with a size of ${requestOptions.body.length} byte.`, - }; - } - this.sendMessageToUI(sendRequest); + this.sendMessageToUI(sanitizeUiMessage(requestOptions, authDataKeys)); } catch (e) {} if (oAuth1Api) { diff --git a/packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts b/packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts index ab118f8af..60fc469b5 100644 --- a/packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts @@ -11,7 +11,12 @@ import { } from 'n8n-workflow'; import { OptionsWithUri } from 'request'; -import { getOAuth2AdditionalParameters, replaceNullValues } from '../GenericFunctions'; +import { + getOAuth2AdditionalParameters, + IAuthDataSanitizeKeys, + replaceNullValues, + sanitizeUiMessage, +} from '../GenericFunctions'; interface OptionData { name: string; @@ -948,21 +953,26 @@ export class HttpRequestV2 implements INodeType { requestOptions.headers['Content-Type'] = options.bodyContentCustomMimeType; } + const authDataKeys: IAuthDataSanitizeKeys = {}; + // Add credentials if any are set if (httpBasicAuth !== undefined) { requestOptions.auth = { user: httpBasicAuth.user as string, pass: httpBasicAuth.password as string, }; + authDataKeys.auth = ['pass']; } if (httpHeaderAuth !== undefined) { requestOptions.headers![httpHeaderAuth.name as string] = httpHeaderAuth.value; + authDataKeys.headers = [httpHeaderAuth.name as string]; } if (httpQueryAuth !== undefined) { if (!requestOptions.qs) { requestOptions.qs = {}; } requestOptions.qs[httpQueryAuth.name as string] = httpQueryAuth.value; + authDataKeys.qs = [httpQueryAuth.name as string]; } if (httpDigestAuth !== undefined) { requestOptions.auth = { @@ -970,6 +980,7 @@ export class HttpRequestV2 implements INodeType { pass: httpDigestAuth.password as string, sendImmediately: false, }; + authDataKeys.auth = ['pass']; } if (requestOptions.headers!.accept === undefined) { @@ -985,15 +996,7 @@ export class HttpRequestV2 implements INodeType { } try { - let sendRequest: any = requestOptions; - // Protect browser from sending large binary data - if (Buffer.isBuffer(sendRequest.body) && sendRequest.body.length > 250000) { - sendRequest = { - ...requestOptions, - body: `Binary data got replaced with this text. Original was a Buffer with a size of ${requestOptions.body.length} byte.`, - }; - } - this.sendMessageToUI(sendRequest); + this.sendMessageToUI(sanitizeUiMessage(requestOptions, authDataKeys)); } catch (e) {} if (authentication === 'genericCredentialType' || authentication === 'none') { diff --git a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts index 437f96bb4..24fd8533d 100644 --- a/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts +++ b/packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts @@ -17,7 +17,9 @@ import { OptionsWithUri } from 'request-promise-native'; import { binaryContentTypes, getOAuth2AdditionalParameters, + IAuthDataSanitizeKeys, replaceNullValues, + sanitizeUiMessage, } from '../GenericFunctions'; export class HttpRequestV3 implements INodeType { description: INodeTypeDescription; @@ -1208,21 +1210,26 @@ export class HttpRequestV3 implements INodeType { requestOptions.headers['Content-Type'] = rawContentType; } + const authDataKeys: IAuthDataSanitizeKeys = {}; + // Add credentials if any are set if (httpBasicAuth !== undefined) { requestOptions.auth = { user: httpBasicAuth.user as string, pass: httpBasicAuth.password as string, }; + authDataKeys.auth = ['pass']; } if (httpHeaderAuth !== undefined) { requestOptions.headers![httpHeaderAuth.name as string] = httpHeaderAuth.value; + authDataKeys.headers = [httpHeaderAuth.name as string]; } if (httpQueryAuth !== undefined) { if (!requestOptions.qs) { requestOptions.qs = {}; } requestOptions.qs[httpQueryAuth.name as string] = httpQueryAuth.value; + authDataKeys.qs = [httpQueryAuth.name as string]; } if (httpDigestAuth !== undefined) { requestOptions.auth = { @@ -1230,6 +1237,7 @@ export class HttpRequestV3 implements INodeType { pass: httpDigestAuth.password as string, sendImmediately: false, }; + authDataKeys.auth = ['pass']; } if (requestOptions.headers!.accept === undefined) { @@ -1245,15 +1253,7 @@ export class HttpRequestV3 implements INodeType { } try { - let sendRequest: any = requestOptions; - // Protect browser from sending large binary data - if (Buffer.isBuffer(sendRequest.body) && sendRequest.body.length > 250000) { - sendRequest = { - ...requestOptions, - body: `Binary data got replaced with this text. Original was a Buffer with a size of ${requestOptions.body.length} byte.`, - }; - } - this.sendMessageToUI(sendRequest); + this.sendMessageToUI(sanitizeUiMessage(requestOptions, authDataKeys)); } catch (e) {} if (authentication === 'genericCredentialType' || authentication === 'none') {