Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fs from "fs";
import * as os from "os";

import { expect } from "chai";
import * as sinon from "sinon";

import { Config } from "./config";
import { FIREBASE_JSON_PATH as VALID_CONFIG_PATH } from "./test/fixtures/valid-config";
Expand Down Expand Up @@ -33,6 +34,10 @@ describe("Config", () => {
});

describe("#path", () => {
afterEach(() => {
sinon.restore();
});

it("should skip an absolute path", () => {
const config = new Config({}, { cwd: SIMPLE_CONFIG_DIR });
const absPath = "/Users/something";
Expand All @@ -43,6 +48,23 @@ describe("Config", () => {
const relativePath = "something";
expect(config.path(relativePath)).to.eq(path.join(SIMPLE_CONFIG_DIR, relativePath));
});
it("should allow path segments containing two dots", () => {
const publicDir = "foo..bar";
const config = new Config({ hosting: { public: publicDir } }, { cwd: SIMPLE_CONFIG_DIR });
const configuredPublicDir = config.get("hosting.public") as string;
expect(config.path(configuredPublicDir)).to.eq(path.join(SIMPLE_CONFIG_DIR, publicDir));
});
it("should reject parent directory traversal", () => {
const config = new Config({}, { cwd: SIMPLE_CONFIG_DIR });
for (const relativePath of ["..", path.join("..", "outside")]) {
expect(() => config.path(relativePath)).to.throw("is outside of project directory");
}
});
it("should reject an absolute result from path.relative", () => {
const config = new Config({}, { cwd: SIMPLE_CONFIG_DIR });
sinon.stub(path, "relative").returns(path.resolve("outside"));
expect(() => config.path("inside")).to.throw("is outside of project directory");
});
});

describe("#parseFile", () => {
Expand Down
7 changes: 6 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,12 @@ export class Config {
return pathName;
}
const outPath = path.normalize(path.join(this.projectDir, pathName));
if (path.relative(this.projectDir, outPath).includes("..")) {
const relativePath = path.relative(this.projectDir, outPath);
if (
path.isAbsolute(relativePath) ||
relativePath === ".." ||
relativePath.startsWith(`..${path.sep}`)
) {
throw new FirebaseError(clc.bold(pathName) + " is outside of project directory", { exit: 1 });
}
return outPath;
Expand Down