Skip to content

Commit

Permalink
fix(core): Do not send credentials to browser console (#5031)
Browse files Browse the repository at this point in the history
  • Loading branch information
janober authored Dec 23, 2022
1 parent a229788 commit afc5297
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 30 deletions.
38 changes: 37 additions & 1 deletion packages/nodes-base/nodes/HttpRequest/GenericFunctions.ts
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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: {
Expand Down
18 changes: 8 additions & 10 deletions packages/nodes-base/nodes/HttpRequest/V1/HttpRequestV1.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -914,28 +914,34 @@ 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 = {
user: httpDigestAuth.user as string,
pass: httpDigestAuth.password as string,
sendImmediately: false,
};
authDataKeys.auth = ['pass'];
}

if (requestOptions.headers!.accept === undefined) {
Expand All @@ -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) {
Expand Down
23 changes: 13 additions & 10 deletions packages/nodes-base/nodes/HttpRequest/V2/HttpRequestV2.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -948,28 +953,34 @@ 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 = {
user: httpDigestAuth.user as string,
pass: httpDigestAuth.password as string,
sendImmediately: false,
};
authDataKeys.auth = ['pass'];
}

if (requestOptions.headers!.accept === undefined) {
Expand All @@ -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') {
Expand Down
18 changes: 9 additions & 9 deletions packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1208,28 +1210,34 @@ 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 = {
user: httpDigestAuth.user as string,
pass: httpDigestAuth.password as string,
sendImmediately: false,
};
authDataKeys.auth = ['pass'];
}

if (requestOptions.headers!.accept === undefined) {
Expand All @@ -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') {
Expand Down

0 comments on commit afc5297

Please sign in to comment.