diff options
| author | David Sherret <dsherret@users.noreply.github.com> | 2024-09-16 21:39:37 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-16 21:39:37 +0100 |
| commit | 62e952559f600e72d7498c9b12f906cb0b1ba150 (patch) | |
| tree | 6dbcce6592973358ef4bf6341888b0bbbdb98cc5 /tests | |
| parent | e0b9c745c15720914f14996bf357d5b375e2dbd8 (diff) | |
refactor(permissions): split up Descriptor into Allow, Deny, and Query (#25508)
This makes the permission system more versatile.
Diffstat (limited to 'tests')
17 files changed, 188 insertions, 45 deletions
diff --git a/tests/integration/run_tests.rs b/tests/integration/run_tests.rs index 95b6e5a01..10a266fcc 100644 --- a/tests/integration/run_tests.rs +++ b/tests/integration/run_tests.rs @@ -255,12 +255,6 @@ itest!(_052_no_remote_flag { http_server: true, }); -itest!(_056_make_temp_file_write_perm { - args: - "run --quiet --allow-read --allow-write=./subdir/ run/056_make_temp_file_write_perm.ts", - output: "run/056_make_temp_file_write_perm.out", -}); - itest!(_058_tasks_microtasks_close { args: "run --quiet run/058_tasks_microtasks_close.ts", output: "run/058_tasks_microtasks_close.ts.out", diff --git a/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc b/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc new file mode 100644 index 000000000..fac0d928a --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/__test__.jsonc @@ -0,0 +1,8 @@ +{ + "envs": { + "DYLD_FALLBACK_LIBRARY_PATH": "", + "LD_LIBRARY_PATH": "" + }, + "args": "run --allow-run --deny-run=deno --allow-read main.ts", + "output": "main.out" +} diff --git a/tests/specs/permission/deny_run_binary_absolute_path/main.out b/tests/specs/permission/deny_run_binary_absolute_path/main.out new file mode 100644 index 000000000..45b228387 --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/main.out @@ -0,0 +1,8 @@ +NotCapable: Requires run access to "deno", run again with the --allow-run flag + at [WILDCARD] { + name: "NotCapable" +} +NotCapable: Requires run access to "[WILDLINE]", run again with the --allow-run flag + at [WILDCARD] { + name: "NotCapable" +} diff --git a/tests/specs/permission/deny_run_binary_absolute_path/main.ts b/tests/specs/permission/deny_run_binary_absolute_path/main.ts new file mode 100644 index 000000000..eca5e5a33 --- /dev/null +++ b/tests/specs/permission/deny_run_binary_absolute_path/main.ts @@ -0,0 +1,15 @@ +try { + new Deno.Command("deno", { + args: ["--version"], + }).outputSync(); +} catch (err) { + console.error(err); +} + +try { + new Deno.Command(Deno.execPath(), { + args: ["--version"], + }).outputSync(); +} catch (err) { + console.error(err); +} diff --git a/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out new file mode 100644 index 000000000..7144e088c --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.out @@ -0,0 +1,4 @@ +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] +good [WILDCARD]subdir[WILDCARD] diff --git a/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts new file mode 100644 index 000000000..28661973c --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/056_make_temp_file_write_perm.ts @@ -0,0 +1,52 @@ +Deno.mkdirSync("subdir"); + +// async file +{ + const path = await Deno.makeTempFile({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} +// sync file +{ + const path = Deno.makeTempFileSync({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} + +// async dir +{ + const path = await Deno.makeTempDir({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} + +// sync dir +{ + const path = Deno.makeTempDirSync({ dir: `subdir` }); + try { + if (!path.match(/^subdir[/\\][^/\\]+/)) { + throw Error("bad " + path); + } + console.log("good", path); + } finally { + await Deno.remove(path); + } +} diff --git a/tests/specs/permission/make_temp_write_perm/__test__.jsonc b/tests/specs/permission/make_temp_write_perm/__test__.jsonc new file mode 100644 index 000000000..80a503215 --- /dev/null +++ b/tests/specs/permission/make_temp_write_perm/__test__.jsonc @@ -0,0 +1,15 @@ +{ + "tempDir": true, + "tests": { + "reduced_perms": { + // this should not expose the full directory + "args": "run --quiet --allow-read --allow-write=./subdir/ 056_make_temp_file_write_perm.ts", + "output": "056_make_temp_file_write_perm.out" + }, + "all_perms": { + // this will work the same as above + "args": "run --quiet -A 056_make_temp_file_write_perm.ts", + "output": "056_make_temp_file_write_perm.out" + } + } +} diff --git a/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc b/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc index 173e13027..3e5d86adf 100644 --- a/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc +++ b/tests/specs/run/allow_run_allowlist_resolution/__test__.jsonc @@ -1,8 +1,9 @@ { - "args": "run --quiet -A main.ts", - "output": "main.out", + "tempDir": true, "envs": { "DYLD_FALLBACK_LIBRARY_PATH": "", "LD_LIBRARY_PATH": "" - } + }, + "args": "run --quiet -A main.ts", + "output": "main.out" } diff --git a/tests/specs/run/allow_run_allowlist_resolution/main.out b/tests/specs/run/allow_run_allowlist_resolution/main.out index f61f9b550..b494bb52f 100644 --- a/tests/specs/run/allow_run_allowlist_resolution/main.out +++ b/tests/specs/run/allow_run_allowlist_resolution/main.out @@ -3,7 +3,7 @@ PermissionStatus { state: "granted", onchange: null } PermissionStatus { state: "prompt", onchange: null } PermissionStatus { state: "granted", onchange: null } --- -Info Failed to resolve 'deno' for allow-run: cannot find binary path +Info Failed to resolve 'binary' for allow-run: cannot find binary path PermissionStatus { state: "prompt", onchange: null } PermissionStatus { state: "prompt", onchange: null } PermissionStatus { state: "prompt", onchange: null } diff --git a/tests/specs/run/allow_run_allowlist_resolution/main.ts b/tests/specs/run/allow_run_allowlist_resolution/main.ts index bf33d8cbe..e43e0b5da 100644 --- a/tests/specs/run/allow_run_allowlist_resolution/main.ts +++ b/tests/specs/run/allow_run_allowlist_resolution/main.ts @@ -1,36 +1,41 @@ -// Testing the following (but with `deno` instead of `echo`): -// | `deno run --allow-run=echo` | `which path == "/usr/bin/echo"` at startup | `which path != "/usr/bin/echo"` at startup | -// |-------------------------------------|--------------------------------------------|--------------------------------------------| -// | **`Deno.Command("echo")`** | ✅ | ✅ | -// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ❌ | +// Testing the following: +// | `deno run --allow-run=binary` | `which path == "/usr/bin/binary"` at startup | `which path != "/usr/bin/binary"` at startup | +// |---------------------------------------|----------------------------------------------|--------------------------------------------| +// | **`Deno.Command("binary")`** | :white_check_mark: | :white_check_mark: | +// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :x: | +// | `deno run --allow-run=/usr/bin/binary | `which path == "/usr/bin/binary"` at runtime | `which path != "/usr/bin/binary"` at runtime | +// |---------------------------------------|----------------------------------------------|--------------------------------------------| +// | **`Deno.Command("binary")`** | :white_check_mark: | :x: | +// | **`Deno.Command("/usr/bin/binary")`** | :white_check_mark: | :white_check_mark: | -// | `deno run --allow-run=/usr/bin/echo | `which path == "/usr/bin/echo"` at runtime | `which path != "/usr/bin/echo"` at runtime | -// |-------------------------------------|--------------------------------------------|--------------------------------------------| -// | **`Deno.Command("echo")`** | ✅ | ❌ | -// | **`Deno.Command("/usr/bin/echo")`** | ✅ | ✅ | +const binaryName = Deno.build.os === "windows" ? "binary.exe" : "binary"; +const pathSep = Deno.build.os === "windows" ? "\\" : "/"; +const cwd = Deno.cwd(); +const execPathParent = `${Deno.cwd()}${pathSep}sub`; +const execPath = `${execPathParent}${pathSep}${binaryName}`; -const execPath = Deno.execPath(); -const execPathParent = execPath.replace(/[/\\][^/\\]+$/, ""); +Deno.mkdirSync(execPathParent); +Deno.copyFileSync(Deno.execPath(), execPath); const testUrl = `data:application/typescript;base64,${ btoa(` - console.error(await Deno.permissions.query({ name: "run", command: "deno" })); + console.error(await Deno.permissions.query({ name: "run", command: "binary" })); console.error(await Deno.permissions.query({ name: "run", command: "${ execPath.replaceAll("\\", "\\\\") }" })); Deno.env.set("PATH", ""); - console.error(await Deno.permissions.query({ name: "run", command: "deno" })); + console.error(await Deno.permissions.query({ name: "run", command: "binary" })); console.error(await Deno.permissions.query({ name: "run", command: "${ execPath.replaceAll("\\", "\\\\") }" })); `) }`; -const process1 = await new Deno.Command(Deno.execPath(), { +await new Deno.Command(Deno.execPath(), { args: [ "run", "--allow-env", - "--allow-run=deno", + "--allow-run=binary", testUrl, ], stdout: "inherit", @@ -44,7 +49,7 @@ await new Deno.Command(Deno.execPath(), { args: [ "run", "--allow-env", - "--allow-run=deno", + "--allow-run=binary", testUrl, ], stderr: "inherit", diff --git a/tests/specs/run/ld_preload/__test__.jsonc b/tests/specs/run/ld_preload/__test__.jsonc index 882f157e9..16ae697a7 100644 --- a/tests/specs/run/ld_preload/__test__.jsonc +++ b/tests/specs/run/ld_preload/__test__.jsonc @@ -6,11 +6,11 @@ }, "tests": { "env_arg": { - "args": "run --allow-run=echo env_arg.ts", + "args": "run --allow-run=curl env_arg.ts", "output": "env_arg.out" }, "set_with_allow_env": { - "args": "run --allow-run=echo --allow-env set_with_allow_env.ts", + "args": "run --allow-run=curl --allow-env set_with_allow_env.ts", "output": "set_with_allow_env.out" } } diff --git a/tests/specs/run/ld_preload/set_with_allow_env.ts b/tests/specs/run/ld_preload/set_with_allow_env.ts index 79004aa16..a3e8dd397 100644 --- a/tests/specs/run/ld_preload/set_with_allow_env.ts +++ b/tests/specs/run/ld_preload/set_with_allow_env.ts @@ -1,7 +1,7 @@ Deno.env.set("LD_PRELOAD", "./libpreload.so"); try { - new Deno.Command("echo").spawn(); + new Deno.Command("curl").spawn(); } catch (err) { console.log(err); } @@ -9,7 +9,7 @@ try { Deno.env.set("DYLD_FALLBACK_LIBRARY_PATH", "./libpreload.so"); try { - Deno.run({ cmd: ["echo"] }).spawnSync(); + Deno.run({ cmd: ["curl"] }).spawnSync(); } catch (err) { console.log(err); } diff --git a/tests/testdata/run/056_make_temp_file_write_perm.out b/tests/testdata/run/056_make_temp_file_write_perm.out deleted file mode 100644 index c56aae43f..000000000 --- a/tests/testdata/run/056_make_temp_file_write_perm.out +++ /dev/null @@ -1 +0,0 @@ -good [WILDCARD]subdir[WILDCARD] diff --git a/tests/testdata/run/056_make_temp_file_write_perm.ts b/tests/testdata/run/056_make_temp_file_write_perm.ts deleted file mode 100644 index c0deda8a2..000000000 --- a/tests/testdata/run/056_make_temp_file_write_perm.ts +++ /dev/null @@ -1,9 +0,0 @@ -const path = await Deno.makeTempFile({ dir: `subdir` }); -try { - if (!path.match(/^subdir[/\\][^/\\]+/)) { - throw Error("bad " + path); - } - console.log("good", path); -} finally { - await Deno.remove(path); -} diff --git a/tests/testdata/workers/read_check_granular_worker.js b/tests/testdata/workers/read_check_granular_worker.js index 7f2d0f717..01df8ca97 100644 --- a/tests/testdata/workers/read_check_granular_worker.js +++ b/tests/testdata/workers/read_check_granular_worker.js @@ -1,4 +1,16 @@ // deno-fmt-ignore-file +import { toFileUrl } from "@std/path/to-file-url"; + +function tryGetCwd() { + // will throw in one test but not the other + try { + return Deno.cwd() + } catch { + return import.meta.dirname; + } +} + +const fooExePath = tryGetCwd() + "/foo" + (Deno.build.os === "windows" ? ".exe" : ""); postMessage({ envGlobal: (await Deno.permissions.query({ name: "env" })).state, envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state, @@ -15,11 +27,13 @@ postMessage({ readGlobal: (await Deno.permissions.query({ name: "read" })).state, readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state, readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state, - readAbsent: (await Deno.permissions.query({ name: "read", path: "absent" })).state, + readAbsent: (await Deno.permissions.query({ name: "read", path: "../absent" })).state, runGlobal: (await Deno.permissions.query({ name: "run" })).state, - runFoo: (await Deno.permissions.query({ name: "run", command: new URL("foo", import.meta.url) })).state, + runFoo: (await Deno.permissions.query({ name: "run", command: toFileUrl(fooExePath) })).state, + runFooPath: (await Deno.permissions.query({ name: "run", command: fooExePath })).state, runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state, runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state, + runUnresolved: (await Deno.permissions.query({ name: "run", command: "unresolved-exec" })).state, runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state, writeGlobal: (await Deno.permissions.query({ name: "write" })).state, writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state, diff --git a/tests/unit/os_test.ts b/tests/unit/os_test.ts index 4f760ecf8..a70796505 100644 --- a/tests/unit/os_test.ts +++ b/tests/unit/os_test.ts @@ -79,7 +79,9 @@ Deno.test( ) => { const src = ` console.log( - ${JSON.stringify(Object.keys(expectedEnv))}.map(k => Deno.env.get(k)) + ${ + JSON.stringify(Object.keys(expectedEnv)) + }.map(k => Deno.env.get(k) ?? null) )`; const { success, stdout } = await new Deno.Command(Deno.execPath(), { args: ["eval", src], diff --git a/tests/unit/worker_test.ts b/tests/unit/worker_test.ts index 88c6ca4c6..42c257282 100644 --- a/tests/unit/worker_test.ts +++ b/tests/unit/worker_test.ts @@ -5,6 +5,7 @@ // Requires to be run with `--allow-net` flag import { assert, assertEquals, assertMatch, assertThrows } from "@std/assert"; +import { toFileUrl } from "@std/path/to-file-url"; function resolveWorker(worker: string): string { return import.meta.resolve(`../testdata/workers/${worker}`); @@ -442,7 +443,31 @@ Deno.test("Worker limit children permissions", async function () { worker.terminate(); }); +function setupReadCheckGranularWorkerTest() { + const tempDir = Deno.realPathSync(Deno.makeTempDirSync()); + const initialPath = Deno.env.get("PATH")!; + const initialCwd = Deno.cwd(); + Deno.chdir(tempDir); + const envSep = Deno.build.os === "windows" ? ";" : ":"; + Deno.env.set("PATH", initialPath + envSep + tempDir); + + // create executables that will be resolved when doing `which` + const ext = Deno.build.os === "windows" ? ".exe" : ""; + Deno.copyFileSync(Deno.execPath(), tempDir + "/bar" + ext); + + return { + tempDir, + runFooFilePath: tempDir + "/foo" + ext, + [Symbol.dispose]() { + Deno.removeSync(tempDir, { recursive: true }); + Deno.env.set("PATH", initialPath); + Deno.chdir(initialCwd); + }, + }; +} + Deno.test("Worker limit children permissions granularly", async function () { + const ctx = setupReadCheckGranularWorkerTest(); const workerUrl = resolveWorker("read_check_granular_worker.js"); const worker = new Worker( workerUrl, @@ -453,8 +478,13 @@ Deno.test("Worker limit children permissions granularly", async function () { env: ["foo"], net: ["foo", "bar:8000"], ffi: [new URL("foo", workerUrl), "bar"], - read: [new URL("foo", workerUrl), "bar"], - run: [new URL("foo", workerUrl), "bar", "./baz"], + read: [new URL("foo", workerUrl), "bar", ctx.tempDir], + run: [ + toFileUrl(ctx.runFooFilePath), + "bar", + "./baz", + "unresolved-exec", + ], write: [new URL("foo", workerUrl), "bar"], }, }, @@ -482,8 +512,10 @@ Deno.test("Worker limit children permissions granularly", async function () { readAbsent: "prompt", runGlobal: "prompt", runFoo: "granted", + runFooPath: "granted", runBar: "granted", runBaz: "granted", + runUnresolved: "prompt", // unresolved binaries remain as "prompt" runAbsent: "prompt", writeGlobal: "prompt", writeFoo: "granted", @@ -494,6 +526,7 @@ Deno.test("Worker limit children permissions granularly", async function () { }); Deno.test("Nested worker limit children permissions", async function () { + const _cleanup = setupReadCheckGranularWorkerTest(); /** This worker has permissions but doesn't grant them to its children */ const worker = new Worker( resolveWorker("parent_read_check_worker.js"), @@ -521,8 +554,10 @@ Deno.test("Nested worker limit children permissions", async function () { readAbsent: "prompt", runGlobal: "prompt", runFoo: "prompt", + runFooPath: "prompt", runBar: "prompt", runBaz: "prompt", + runUnresolved: "prompt", runAbsent: "prompt", writeGlobal: "prompt", writeFoo: "prompt", |
