fix(deno): default permissions so env/inputFiles/outputFiles work on Script - #415
Conversation
…/outputFiles work deno.Script ran `deno run <file>` with no permission flags. Deno denies env, filesystem read and write by default, so the env, inputFiles and outputFiles properties that every other script task supports failed at runtime with NotCapable errors. Add a `permissions` property defaulting to --allow-env, --allow-read and --allow-write, giving Script parity with the rest of the module while still letting users scope permissions up (e.g. --allow-net) or down to an empty list for Deno's secure-by-default sandbox.
📦 Artifacts
🧪 Java Unit Tests
🔁 Unreleased Commits8 commits since
|
Tests report quick summary:success ✅ > tests: 247, success: 247, skipped: 0, failed: 0 unfold for details
|
Browser QA —
|
| # | Flow | Expected | Result |
|---|---|---|---|
| 1 | deno_env_repro_410 (exact repro from #410) |
ENV=hello instead of NotCapable |
✅ SUCCESS |
| 2 | deno_input_output_files |
inputFiles readable, outputFiles captured | ✅ SUCCESS |
| 3 | deno_custom_permissions |
user-supplied --allow-net honored |
✅ SUCCESS |
| 4 | deno_empty_permissions |
permissions: [] restores Deno's deny-all sandbox |
✅ FAILED as designed |
| 5 | deno_commands_non_regression |
deno.Commands unchanged |
✅ SUCCESS |
The generated command line was verified in the logs: deno run --allow-env --allow-read --allow-write <script>.ts — the defaults are applied, and are overridden verbatim when permissions is set.
Flow 1: deno_env_repro_410 (✅ SUCCESS)
Flow YAML
id: deno_env_repro_410
namespace: qa.deno
tasks:
- id: deno_env
type: io.kestra.plugin.scripts.deno.Script
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
containerImage: denoland/deno:alpine
env:
MY_VAR: hello
script: |
console.log("ENV=" + Deno.env.get("MY_VAR"));Gantt (screenshot)
| Task | Status | Duration |
|---|---|---|
deno_env |
SUCCESS | ~0.5s |
| Total | SUCCESS | ~0.5s |
Logs synthesis — the exact scenario from the issue now passes. Command: deno run --allow-env --allow-read --allow-write /tmp/.../8032887033266725774.ts; output INFO ENV=hello; Command succeed with exit code 0. Before the fix this failed with NotCapable: Requires env access to "MY_VAR".
Outputs — none (task produces no output files).
Flow 2: deno_input_output_files (✅ SUCCESS)
Flow YAML
id: deno_input_output_files
namespace: qa.deno
tasks:
- id: deno_files
type: io.kestra.plugin.scripts.deno.Script
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
containerImage: denoland/deno:alpine
inputFiles:
in.txt: "hello from input file"
outputFiles:
- out.txt
script: |
const content = Deno.readTextFileSync("in.txt");
console.log("READ=" + content);
Deno.writeTextFileSync("out.txt", content.toUpperCase());
console.log("WROTE out.txt");Gantt (screenshot)
| Task | Status | Duration |
|---|---|---|
deno_files |
SUCCESS | 0.60s |
| Total | SUCCESS | 0.60s |
Logs synthesis — INFO READ=hello from input file, INFO WROTE out.txt, then Captured 1 output file(s). Both the read and the write permissions that previously blocked this now apply.
Outputs synthesis (screenshot) — deno_files exposes { vars, exitCode, outputFiles, taskRunner } with outputFiles."out.txt" = kestra:///qa/deno/deno-input-output-files/executions/.../out.txt.
Flow 3: deno_custom_permissions (✅ SUCCESS)
Flow YAML
id: deno_custom_permissions
namespace: qa.deno
tasks:
- id: deno_net
type: io.kestra.plugin.scripts.deno.Script
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
containerImage: denoland/deno:alpine
permissions:
- --allow-env
- --allow-read
- --allow-write
- --allow-net
env:
MY_VAR: custom
script: |
console.log("ENV=" + Deno.env.get("MY_VAR"));
console.log("NET=" + Deno.permissions.querySync({ name: "net" }).state);
console.log("READ=" + Deno.permissions.querySync({ name: "read" }).state);Gantt (screenshot)
| Task | Status | Duration |
|---|---|---|
deno_net |
SUCCESS | 0.55s |
| Total | SUCCESS | 0.55s |
Logs synthesis — ENV=custom, NET=granted, READ=granted. Deno itself confirms the user-supplied flag list reached the runtime, so the property is not cosmetic.
Flow 4: deno_empty_permissions (✅ FAILED — expected)
Flow YAML
id: deno_empty_permissions
namespace: qa.deno
tasks:
- id: deno_sandboxed
type: io.kestra.plugin.scripts.deno.Script
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
containerImage: denoland/deno:alpine
permissions: []
env:
MY_VAR: denied
script: |
console.log("ENV=" + Deno.env.get("MY_VAR"));Gantt (screenshot)
| Task | Status | Duration |
|---|---|---|
deno_sandboxed |
FAILED | 0.52s |
| Total | FAILED (expected) | 0.52s |
Logs synthesis — error: Uncaught (in promise) NotCapable: Requires env access to "MY_VAR", run again with the --allow-env flag, then TaskException: Command failed with exit code 1. This is the desired outcome: an empty list is respected rather than silently replaced by the defaults, so users who want Deno's secure-by-default sandbox can still have it.
Flow 5: deno_commands_non_regression (✅ SUCCESS)
Flow YAML
id: deno_commands_non_regression
namespace: qa.deno
tasks:
- id: deno_cmd
type: io.kestra.plugin.scripts.deno.Commands
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
containerImage: denoland/deno:alpine
env:
MY_VAR: cmdhello
inputFiles:
main.ts: |
console.log("ENV=" + Deno.env.get("MY_VAR"));
commands:
- deno run --allow-all main.tsGantt (screenshot)
| Task | Status | Duration |
|---|---|---|
deno_cmd |
SUCCESS | 0.50s |
| Total | SUCCESS | 0.50s |
Logs synthesis — ENV=cmdhello. deno.Commands is untouched by this change, as intended.
Notes
- No timeouts — every execution completed in well under a second once the
denoland/deno:alpineimage was pulled. - Topology/artifact scenarios were out of scope: this PR does not add or change a plugin artifact or custom UI.
- Behavior change worth a reviewer's attention: the new default grants
--allow-env --allow-read --allow-writeto everydeno.Scriptthat does not setpermissions. That is what makes the inherited task properties work (and matches every other scripts task), but it does widen the default sandbox compared to 1.9.8.
Summary
deno.Scriptbuiltdeno run <file>with no permission flags. Deno denies env, filesystem read and write by default, soenv,inputFilesandoutputFilesall failed at runtime withNotCapableerrors — the three features every other script task supports were unusable.permissionsproperty ondeno.Scriptdefaulting to--allow-env,--allow-read,--allow-write, giving parity with the rest of the module by default. Users can widen it (e.g.--allow-net) or set it to an empty list to run under Deno's secure-by-default sandbox.deno.Commandsis unaffected — users already control the full command there.@Schema, added a runnable example, and updated the plugin how-to doc.closes: #410
Test plan
rtk test ./gradlew :plugin-script-deno:testpasses (includes a new test reproducing the issue — first confirmed it failed withNotCapable: Requires env access to "MY_VAR"against the old code, then verified it passes with the fix; also exercises inputFiles/outputFiles)rtk err ./gradlew :plugin-script-deno:compileJava :plugin-script-deno:compileTestJava— no errors./gradlew shadowJar