Bun and Deno load .env for a Sume script: Deno needs --allow-env

One submit script, three runtimes. Bun reads .env on its own; Deno needs --env-file plus --allow-env for each variable. Tested on Bun 1.4.0 and Deno 2.9.7.

4 min readSume
All posts

The same ten-line submit.mjs that uses process.env.SUME_API_KEY runs unchanged on Node, Bun and Deno. What differs is how the variables get in. Bun auto-loads a .env from the working directory. Deno does not, and it also guards every read: a variable that is not on the --allow-env list throws a permission error, even when --env-file loaded it.

Results below are from Node 22.14.0, Bun 1.4.0 and Deno 2.9.7 running the script against a local stand-in server that answers 202, with a .env holding SUME_API_KEY and SUME_BASE.

Same script, three runtimes (read 2026-10-07)
RuntimeCommandResult
Node 22.14node --env-file=.env submit.mjs202
Bun 1.4.0bun submit.mjs202 (reads .env automatically)
Deno 2.9.7deno run --env-file=.env --allow-env=SUME_API_KEY,SUME_BASE --allow-net=127.0.0.1:8791 submit.mjs202
Deno 2.9.7same, without --allow-envpermission error at the first env read
Deno 2.9.7--allow-env=SUME_API_KEY onlypermission error when SUME_BASE is read

The script they all ran

It stops early when the key is missing, then posts a 5-second Wan 3.0 clip at 480p with an Idempotency-Key, using the single x-api-key header Sume expects.

const key = process.env.SUME_API_KEY;
if (!key) throw new Error("SUME_API_KEY is empty: start with --env-file=.env or export it");

const res = await fetch(`${process.env.SUME_BASE ?? "https://api.sume.com"}/v1/videos`, {
  method: "POST",
  headers: { "x-api-key": key, "content-type": "application/json", "Idempotency-Key": "kite-env-1" },
  body: JSON.stringify({ model: "wan-3.0", prompt: "a red kite", duration: 5, resolution: "480p" }),
});
console.log(res.status, (await res.json()).id);

Which flags to give Deno in production

List exactly the variables the script reads, and pin the network permission to the host: --allow-net=api.sume.com. Downloading a finished clip is a separate story, because the content redirect can land on another host; the related Deno post covers that. A tight permission list is a cheap way to make sure a dependency cannot read your other secrets or call a host you did not name.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume