Skip to content

Commit 57ca58a

Browse files
authored
RemoteConfig can be loaded in windows CMD.exe (#913)
Favors using process.cwd over process.env.PWD as the latter is POSIX only (I might need to go check some of my code in firebase-tools!). While I was at it, I fixed a probably useless but nasty vulnerability where a malformed .runtimeconfig.json file would allow arbitrary code execution.
1 parent 33a68ea commit 57ca58a

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
- Adds support for setting user labels on functions via `runWith()`.
22
- Adds support for FIREBASE_CONFIG env as the name of a JSON file
33
- Formalize module exports. Loggers can now be accessed at 'firebase-functions/logger' and 'firebase-functions/logger/compat'
4+
- Fixes an issue where Remote Config coiuld not be emulated in Windows machines on the classic Command Prompt.

spec/v1/config.spec.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,47 +22,55 @@
2222

2323
import { expect } from 'chai';
2424
import * as fs from 'fs';
25-
import * as mockRequire from 'mock-require';
25+
import * as process from 'process';
2626
import Sinon = require('sinon');
2727

2828
import * as config from '../../src/v1/config';
2929

3030
describe('config()', () => {
3131
let readFileSync: Sinon.SinonStub;
32+
let cwdStub: Sinon.SinonStub;
3233

3334
before(() => {
3435
readFileSync = Sinon.stub(fs, 'readFileSync');
3536
readFileSync.throws('Unexpected call');
36-
process.env.PWD = '/srv';
37+
cwdStub = Sinon.stub(process, 'cwd');
38+
cwdStub.returns('/srv');
3739
});
3840

3941
after(() => {
40-
delete process.env.PWD;
4142
Sinon.verifyAndRestore();
4243
});
4344

4445
afterEach(() => {
45-
mockRequire.stopAll();
4646
delete config.config.singleton;
4747
(config as any).firebaseConfigCache = null;
4848
delete process.env.FIREBASE_CONFIG;
4949
delete process.env.CLOUD_RUNTIME_CONFIG;
5050
});
5151

5252
it('loads config values from .runtimeconfig.json', () => {
53-
mockRequire('/srv/.runtimeconfig.json', { foo: 'bar', firebase: {} });
53+
const json = JSON.stringify({
54+
foo: 'bar',
55+
firebase: {},
56+
});
57+
readFileSync
58+
.withArgs('/srv/.runtimeconfig.json')
59+
.returns(Buffer.from(json));
5460
const loaded = config.config();
5561
expect(loaded).to.not.have.property('firebase');
5662
expect(loaded).to.have.property('foo', 'bar');
5763
});
5864

5965
it('does not provide firebase config if .runtimeconfig.json not invalid', () => {
60-
mockRequire('/srv/.runtimeconfig.json', 'does-not-exist');
66+
readFileSync.withArgs('/srv/.runtimeconfig.json').returns('invalid JSON');
6167
expect(config.firebaseConfig()).to.be.null;
6268
});
6369

6470
it('does not provide firebase config if .ruuntimeconfig.json has no firebase property', () => {
65-
mockRequire('/srv/.runtimeconfig.json', {});
71+
readFileSync
72+
.withArgs('/srv/.runtimeconfig.json')
73+
.returns(Buffer.from('{}'));
6674
expect(config.firebaseConfig()).to.be.null;
6775
});
6876

@@ -78,7 +86,7 @@ describe('config()', () => {
7886

7987
it('loads Firebase configs from FIREBASE_CONFIG env variable pointing to a file', () => {
8088
const oldEnv = process.env;
81-
process.env = {
89+
(process as any).env = {
8290
...oldEnv,
8391
FIREBASE_CONFIG: '.firebaseconfig.json',
8492
};
@@ -91,13 +99,14 @@ describe('config()', () => {
9199
'foo@firebaseio.com'
92100
);
93101
} finally {
94-
process.env = oldEnv;
102+
(process as any).env = oldEnv;
95103
}
96104
});
97105

98106
it('accepts alternative locations for config file', () => {
99107
process.env.CLOUD_RUNTIME_CONFIG = 'another.json';
100-
mockRequire('another.json', { foo: 'bar', firebase: {} });
108+
const json = JSON.stringify({ foo: 'bar', firebase: {} });
109+
readFileSync.withArgs('another.json').returns(Buffer.from(json));
101110
expect(config.firebaseConfig()).to.not.be.null;
102111
expect(config.config()).to.have.property('foo', 'bar');
103112
});

src/v1/config.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ export function firebaseConfig(): firebase.AppOptions | null {
8989
try {
9090
const configPath =
9191
process.env.CLOUD_RUNTIME_CONFIG ||
92-
path.join(process.env.PWD, '.runtimeconfig.json');
93-
const config = require(configPath);
92+
path.join(process.cwd(), '.runtimeconfig.json');
93+
const contents = fs.readFileSync(configPath);
94+
const config = JSON.parse(contents.toString('utf8'));
9495
if (config.firebase) {
9596
firebaseConfigCache = config.firebase;
9697
return firebaseConfigCache;
@@ -115,8 +116,9 @@ function init() {
115116
try {
116117
const configPath =
117118
process.env.CLOUD_RUNTIME_CONFIG ||
118-
path.join(process.env.PWD, '.runtimeconfig.json');
119-
const parsed = require(configPath);
119+
path.join(process.cwd(), '.runtimeconfig.json');
120+
const contents = fs.readFileSync(configPath);
121+
const parsed = JSON.parse(contents.toString('utf8'));
120122
delete parsed.firebase;
121123
config.singleton = parsed;
122124
return;

0 commit comments

Comments
 (0)