Skip to content

Commit 9864f27

Browse files
authored
fix: prevent hosting deploy to site in wrong project (#10380)
* fix: prevent hosting deploy to site in wrong project ### Description Prevent accidental deployments to a hosting site that does not belong to the active project. The CLI now verifies that the site belongs to the project before creating a version. Fixes #10376 ### Scenarios Tested - Verified that error is thrown when site does not belong to project. - Verified that deploy passes when site belongs to project. - Verified that check is skipped for demo projects. ### Sample Commands `firebase deploy --project project-b` (where site in firebase.json belongs to project-a) -> should fail. * chore: remove excessive site validation check and update tests * Comment * chore: remove demo project check and corresponding test * chore: remove unused Constants import in prepare.ts
1 parent 792502a commit 9864f27

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
- Fixed an issue where hosting deploy allowed publishing to a site in a different project. (#10376)
12
- Added 'firebase_deploy' and 'firebase_deploy_status' MCP tools.
23
- Added SSE mode support to `firebase mcp`. To use it, run `firebase mcp --mode=sse --port=3000`, and connect your client on `http://localhost:3000`.

src/deploy/hosting/prepare.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ describe("hosting prepare", () => {
2929
trackingStub = sinon.stub(tracking);
3030
backendStub = sinon.stub(backend);
3131
loggerStub = sinon.stub(utils, "logLabeledBullet");
32+
hostingStub.getSite.resolves({
33+
name: "projects/project/sites/site",
34+
defaultUrl: "https://site.web.app",
35+
appId: "app-id",
36+
labels: {},
37+
});
3238

3339
// We're intentionally using pointer references so that editing site
3440
// edits the results of hostingConfig() and changes firebase.json
@@ -147,6 +153,34 @@ describe("hosting prepare", () => {
147153
});
148154
});
149155

156+
it("throws error if site does not exist in project", async () => {
157+
hostingStub.getSite.rejects(new Error(`could not find site "site" for project "project"`));
158+
159+
const context: Context = {
160+
projectId: "project",
161+
};
162+
163+
await expect(prepare(context, options)).to.eventually.be.rejectedWith(
164+
`could not find site "site" for project "project"`,
165+
);
166+
});
167+
168+
it("passes if site belongs to project", async () => {
169+
hostingStub.getSite.resolves({
170+
name: "projects/project/sites/site",
171+
defaultUrl: "https://site.web.app",
172+
appId: "app-id",
173+
labels: {},
174+
});
175+
hostingStub.createVersion.resolves("version");
176+
177+
const context: Context = {
178+
projectId: "project",
179+
};
180+
181+
await expect(prepare(context, options)).to.eventually.be.fulfilled;
182+
});
183+
150184
describe("unsafePins", () => {
151185
const apiRewriteWithoutPin: hostingApi.Rewrite = {
152186
glob: "**",

src/deploy/hosting/prepare.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ export async function prepare(
116116

117117
const versions = await Promise.all(
118118
configs.map(async (config) => {
119+
// Get the site to confirm that it exists on this project
120+
await api.getSite(context.projectId, config.site);
119121
const labels: Record<string, string> = {
120122
...deploymentTool.labels(),
121123
};

0 commit comments

Comments
 (0)