Skip to content

Commit

Permalink
Replace node-fetch dependency with undici (#7705)
Browse files Browse the repository at this point in the history
Update our dependency on aging `node-fetch` `v2.6.7` to `undici` `v5.26.5`.

This should fix some vulnerabilities within node-fetch as well as fix user issue #7660.
  • Loading branch information
DellaBitta committed Nov 12, 2023
1 parent a89e05b commit bebecda
Show file tree
Hide file tree
Showing 27 changed files with 147,757 additions and 195 deletions.
11 changes: 11 additions & 0 deletions .changeset/real-dolls-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@firebase/auth-compat': minor
'@firebase/firestore': minor
'@firebase/functions': minor
'@firebase/storage': minor
'@firebase/auth': minor
'firebase': minor
---

Replaced node-fetch v2.6.7 dependency with the latest version of undici (v5.26.5) in Node.js SDK
builds for auth, firestore, functions and storage.
147,406 changes: 147,406 additions & 0 deletions .yarn/releases/yarn-1.22.11.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion integration/messaging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"express": "4.18.2",
"geckodriver": "2.0.4",
"mocha": "9.2.2",
"node-fetch": "2.6.7",
"undici": "5.26.5",
"selenium-assistant": "6.1.1"
}
}
4 changes: 2 additions & 2 deletions integration/messaging/test/utils/sendMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

const fetch = require('node-fetch');
const undici = require('undici');
const FCM_SEND_ENDPOINT = 'https://fcm.googleapis.com/fcm/send';
// Rotatable fcm server key. It's generally a bad idea to expose server keys. The reason is to
// simplify testing process (no need to implement server side decryption of git secret). The
Expand All @@ -28,7 +28,7 @@ module.exports = async payload => {
'Requesting to send an FCM message with payload: ' + JSON.stringify(payload)
);

const response = await fetch(FCM_SEND_ENDPOINT, {
const response = await undici.fetch(FCM_SEND_ENDPOINT, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
"tslint": "6.1.3",
"typedoc": "0.16.11",
"typescript": "4.7.4",
"undici": "5.26.5",
"watch": "1.0.2",
"webpack": "5.76.0",
"yargs": "17.7.2"
Expand Down
12 changes: 8 additions & 4 deletions packages/auth-compat/index.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@
*/
export * from './index';
import { FetchProvider } from '@firebase/auth/internal';
import * as fetchImpl from 'node-fetch';
import {
fetch as undiciFetch,
Headers as undiciHeaders,
Response as undiciResponse
} from 'undici';
import './index';

FetchProvider.initialize(
fetchImpl.default as unknown as typeof fetch,
fetchImpl.Headers as unknown as typeof Headers,
fetchImpl.Response as unknown as typeof Response
undiciFetch as unknown as typeof fetch,
undiciHeaders as unknown as typeof Headers,
undiciResponse as unknown as typeof Response
);
12 changes: 12 additions & 0 deletions packages/auth-compat/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

const karmaBase = require('../../config/karma.base');
const webpackBase = require('../../config/webpack.test');
const { argv } = require('yargs');

const files = ['src/**/*.test.ts'];
Expand All @@ -29,6 +30,17 @@ module.exports = function (config) {
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
// undici is a fetch polyfill that test helpers call for Node tests, and browser tests should
// ingore its import to avoid compilation errors in those test helpers.
webpack: {
...webpackBase,
resolve: {
...webpackBase.resolve,
alias: {
'undici': false
}
}
},

client: Object.assign({}, karmaBase.client, getClientConfig())
});
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-compat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@firebase/auth-types": "0.12.0",
"@firebase/component": "0.6.4",
"@firebase/util": "1.9.3",
"node-fetch": "2.6.7",
"undici": "5.26.5",
"tslib": "^2.1.0"
},
"license": "Apache-2.0",
Expand Down
13 changes: 12 additions & 1 deletion packages/auth/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

const karmaBase = require('../../config/karma.base');
const webpackBase = require('../../config/webpack.test');
const { argv } = require('yargs');

module.exports = function (config) {
Expand All @@ -26,7 +27,17 @@ module.exports = function (config) {
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],

// undici is a fetch polyfill that test helpers call for Node tests, and browser tests should
// ingore its import to avoid compilation errors in those test helpers.
webpack: {
...webpackBase,
resolve: {
...webpackBase.resolve,
alias: {
'undici': false
}
}
},
client: Object.assign({}, karmaBase.client, getClientConfig(argv))
});

Expand Down
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"@firebase/component": "0.6.4",
"@firebase/logger": "0.4.0",
"@firebase/util": "1.9.3",
"node-fetch": "2.6.7",
"undici": "5.26.5",
"tslib": "^2.1.0"
},
"license": "Apache-2.0",
Expand Down
12 changes: 8 additions & 4 deletions packages/auth/src/platform_node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ import { ClientPlatform } from '../core/util/version';
import { AuthImpl } from '../core/auth/auth_impl';

import { FetchProvider } from '../core/util/fetch_provider';
import * as fetchImpl from 'node-fetch';
import { getDefaultEmulatorHost } from '@firebase/util';
import {
fetch as undiciFetch,
Headers as undiciHeaders,
Response as undiciResponse
} from 'undici';

// Initialize the fetch polyfill, the types are slightly off so just cast and hope for the best
FetchProvider.initialize(
fetchImpl.default as unknown as typeof fetch,
fetchImpl.Headers as unknown as typeof Headers,
fetchImpl.Response as unknown as typeof Response
undiciFetch as unknown as typeof fetch,
undiciHeaders as unknown as typeof Headers,
undiciResponse as unknown as typeof Response
);

// First, we set up the various platform-specific features for Node (register
Expand Down
12 changes: 6 additions & 6 deletions packages/auth/test/helpers/integration/emulator_rest_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

import * as fetchImpl from 'node-fetch';
import { fetch as undiciFetch, RequestInit as undiciRequestInit } from 'undici';
import { getAppConfig, getEmulatorUrl } from './settings';

export interface VerificationSession {
Expand Down Expand Up @@ -87,10 +87,10 @@ function buildEmulatorUrlForPath(endpoint: string): string {
function doFetch(url: string, request?: RequestInit): ReturnType<typeof fetch> {
if (typeof document !== 'undefined') {
return fetch(url, request);
} else {
return undiciFetch(
url,
request as undiciRequestInit
) as unknown as ReturnType<typeof fetch>;
}

return fetchImpl.default(
url,
request as fetchImpl.RequestInit
) as unknown as ReturnType<typeof fetch>;
}
2 changes: 1 addition & 1 deletion packages/firestore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"@firebase/webchannel-wrapper": "0.10.3",
"@grpc/grpc-js": "~1.9.0",
"@grpc/proto-loader": "^0.7.8",
"node-fetch": "2.6.7",
"undici": "5.26.5",
"tslib": "^2.1.0"
},
"peerDependencies": {
Expand Down
6 changes: 3 additions & 3 deletions packages/firestore/src/platform/node_lite/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

import nodeFetch from 'node-fetch';
import { fetch as undiciFetch } from 'undici';

import { DatabaseInfo } from '../../core/database_info';
import { Connection } from '../../remote/connection';
Expand All @@ -25,8 +25,8 @@ export { newConnectivityMonitor } from '../browser/connection';

/** Initializes the HTTP connection for the REST API. */
export function newConnection(databaseInfo: DatabaseInfo): Connection {
// node-fetch is meant to be API compatible with `fetch`, but its type doesn't
// undici is meant to be API compatible with `fetch`, but its type doesn't
// match 100%.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return new FetchConnection(databaseInfo, nodeFetch as any);
return new FetchConnection(databaseInfo, undiciFetch as any);
}
14 changes: 13 additions & 1 deletion packages/functions/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

const karmaBase = require('../../config/karma.base');
const webpackBase = require('../../config/webpack.test');

const files = [`src/**/*.test.ts`];

Expand All @@ -25,7 +26,18 @@ module.exports = function (config) {
files,
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha']
frameworks: ['mocha'],
// undici is a fetch polyfill that test helpers call for Node tests, and browser tests should
// ingore its import to avoid compilation errors in those test helpers.
webpack: {
...webpackBase,
resolve: {
...webpackBase.resolve,
alias: {
'undici': false
}
}
}
});

config.set(karmaConfig);
Expand Down
2 changes: 1 addition & 1 deletion packages/functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@firebase/auth-interop-types": "0.2.1",
"@firebase/app-check-interop-types": "0.3.0",
"@firebase/util": "1.9.3",
"node-fetch": "2.6.7",
"undici": "5.26.5",
"tslib": "^2.1.0"
},
"nyc": {
Expand Down
4 changes: 2 additions & 2 deletions packages/functions/src/index.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* limitations under the License.
*/
import { registerFunctions } from './config';
import nodeFetch from 'node-fetch';
import { fetch as undiciFetch } from 'undici';

export * from './api';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
registerFunctions(nodeFetch as any, 'node');
registerFunctions(undiciFetch as any, 'node');
4 changes: 2 additions & 2 deletions packages/functions/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { FirebaseAuthInternalName } from '@firebase/auth-interop-types';
import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types';
import { FunctionsService } from '../src/service';
import { connectFunctionsEmulator } from '../src/api';
import nodeFetch from 'node-fetch';
import { fetch as undiciFetch } from 'undici';
import { MessagingInternalComponentName } from '../../../packages/messaging-interop-types';

export function makeFakeApp(options: FirebaseOptions = {}): FirebaseApp {
Expand Down Expand Up @@ -59,7 +59,7 @@ export function createTestService(
)
): FunctionsService {
const fetchImpl: typeof fetch =
typeof window !== 'undefined' ? fetch.bind(window) : (nodeFetch as any);
typeof window !== 'undefined' ? fetch.bind(window) : (undiciFetch as any);
const functions = new FunctionsService(
app,
authProvider,
Expand Down

0 comments on commit bebecda

Please sign in to comment.