fix(studio): forbid ext:: remotes; type the per-dialect test table

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-30 03:27:30 +01:00
co-authored by Claude Opus 5.5
parent 2849d3c911
commit 667f3e814b
3 changed files with 11 additions and 1 deletions
@@ -11,6 +11,7 @@ const BASE = [
"-c", "merge.conflictstyle=merge",
"-c", "pull.rebase=false",
"-c", "init.defaultBranch=main",
"-c", "protocol.ext.allow=never", // author-supplied remote URLs must never run commands
];
function env(who?: Identity): Record<string, string> {
+1 -1
View File
@@ -11,7 +11,7 @@ test("anonymous gets 401, learners 403", async () => {
expect((await env.call("lea", "POST", "/api/studio/courses", { id: "x", title: "X" })).status).toBe(403);
});
const DBS = [["sqlite", "sqlite://:memory:"], ...(process.env.STC_TEST_PG_URL ? [["postgres", process.env.STC_TEST_PG_URL]] : [])] as const;
const DBS: [string, string][] = [["sqlite", "sqlite://:memory:"], ...(process.env.STC_TEST_PG_URL ? [["postgres", process.env.STC_TEST_PG_URL] as [string, string]] : [])];
test.each(DBS)("creating a course records the creator in course_authors; a per-course author without the role can edit it [%s]", async (_name, url) => {
env = await setupApp([], url);
@@ -144,3 +144,12 @@ describe("sync", () => {
void bob;
});
});
test("ext:: remotes cannot run commands", async () => {
const { store } = await courseWithEdit();
const marker = join(tempDir(), "pwned");
await store.setRemote("c1", `ext::touch%s${marker}`);
const r = await store.sync("c1", ada);
expect(r.ok).toBe(false);
expect(await Bun.file(marker).exists()).toBe(false);
});