|
1 | 1 | # just-bash |
2 | 2 |
|
| 3 | +## 3.0.3 |
| 4 | + |
| 5 | +### Patch Changes |
| 6 | + |
| 7 | +- [#277](https://github.com/vercel-labs/just-bash/pull/277) [`aec5643`](https://github.com/vercel-labs/just-bash/commit/aec56431d7d9b6fcb141bbfe25d26f4931f54f80) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: avoid lazy import in variable assignment path that trips defense-in-depth (fixes [#273](https://github.com/vercel-labs/just-bash/issues/273)) |
| 8 | + |
| 9 | + Any non-`export` variable assignment (bare `SECRET=s`, prefixed `SECRET=s cmd`, |
| 10 | + or before a custom command) failed with a defense-in-depth security violation |
| 11 | + (`dynamic import of Node.js builtin 'node:module' is blocked during script |
| 12 | +execution`), while plain commands and `export`-ed assignments passed. |
| 13 | + |
| 14 | + `processScalarAssignment()` resolved `isArray` via `await import("./expansion.js")` |
| 15 | + in two spots. In the bundled `dist`, that dynamic `import()` marks `expansion.js` |
| 16 | + as a lazily-linked chunk whose `createRequire` banner imports `node:module`; the |
| 17 | + defense layer's ESM `resolve` hook blocks that builtin import when the sandbox is |
| 18 | + active and untrusted, so it blocked just-bash's own chunk load. The file already |
| 19 | + statically imports from `./expansion.js`, so `isArray` is now pulled from that |
| 20 | + static import and the two lazy imports are removed — no lazy `node:module`-bearing |
| 21 | + chunk is linked at runtime. No public API change. |
| 22 | + |
| 23 | +- [#276](https://github.com/vercel-labs/just-bash/pull/276) [`1ec5eec`](https://github.com/vercel-labs/just-bash/commit/1ec5eec0aefd099d23ac9f056df1e6612c81d49b) Thanks [@mutewinter](https://github.com/mutewinter)! - interpreter: preserve leading whitespace in multi-line quoted strings (fixes [#259](https://github.com/vercel-labs/just-bash/issues/259)) |
| 24 | + |
| 25 | + `exec()` runs each script through `normalizeScript()`, which `trimStart()`s |
| 26 | + leading indentation from lines so indented template-literal scripts parse. It |
| 27 | + was applied line-by-line and stripped the leading whitespace inside multi-line |
| 28 | + single- and double-quoted strings too. The visible symptom was `python3 -c |
| 29 | +'...'` (and `node -e`, `awk`, etc.) with an indented body failing with |
| 30 | + `IndentationError`, while the same code via heredoc or pipe worked. |
| 31 | + |
| 32 | + `normalizeScript()` is now quote-aware (mirroring the earlier heredoc-aware |
| 33 | + fix): it only strips indentation from lines that begin outside any quote, and |
| 34 | + preserves lines that begin inside an unterminated single- or double-quoted |
| 35 | + string verbatim. This also un-skips four sed spec tests whose indented stdin |
| 36 | + was previously being corrupted. |
| 37 | + |
| 38 | +- [#286](https://github.com/vercel-labs/just-bash/pull/286) [`cb2b583`](https://github.com/vercel-labs/just-bash/commit/cb2b583b3f46e6bb4e6982c4bfe19903ec811a87) Thanks [@privatenumber](https://github.com/privatenumber)! - interpreter: deliver redirected output to each fd's final target (fixes `cmd > file 2>&1` leaking stderr to stdout) |
| 39 | + |
| 40 | + `applyRedirections()` processed a command's redirection list sequentially over |
| 41 | + the result's stdout/stderr strings, moving content at each step. The |
| 42 | + duplication operators (`2>&1`, `1>&2`) merged into the live stream regardless |
| 43 | + of where the source fd pointed, so the canonical `cmd > file 2>&1` wrote |
| 44 | + stdout to the file but leaked stderr onto the caller's stdout — including |
| 45 | + "command not found" errors and custom-command stderr. Any wrapper protocol |
| 46 | + that parses the enclosing script's stdout (e.g. a runner emitting a JSON |
| 47 | + payload after `eval "$CMD" > "$OUT" 2>&1`) saw the leaked stderr corrupt its |
| 48 | + stream. Ordering variants were wrong in other ways: `cmd 2>&1 > file` put |
| 49 | + stderr in the file instead of on stdout, and `cmd > a > b` wrote content to |
| 50 | + `a` instead of `b`. |
| 51 | + |
| 52 | + The pass now mirrors how bash sets up fds before running the command: each |
| 53 | + output redirection only opens/truncates its target and re-points the fd's |
| 54 | + sink (file, /dev/null, or a snapshot of the caller-visible stream), and |
| 55 | + duplication operators copy the source fd's current sink. Stream content is |
| 56 | + delivered once, after the whole list is processed, to each fd's final sink. |
| 57 | + This makes `cmd > file 2>&1` send stderr to the file, `cmd 2>&1 > file` keep |
| 58 | + stderr on the caller's stdout, `cmd > all 2>&1 2> err` let the later `2> err` |
| 59 | + reclaim stderr, and `cmd > a > b` truncate `a` while writing content to `b`. |
| 60 | + The `/dev/null`-as-regular-VFS-file behavior for stdout redirects is |
| 61 | + preserved. |
| 62 | + |
3 | 63 | ## 3.0.2 |
4 | 64 |
|
5 | 65 | ### Patch Changes |
|
0 commit comments