Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions crates/bashkit-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ bun add @everruns/bashkit # Bun
deno add npm:@everruns/bashkit # Deno
```

Use a patched, supported Node.js release. The October 2026 security minimums
are **22.23.4**, **24.22.1**, and **26.12.1** in their respective release lines;
keep taking subsequent upstream security updates. The package's `engines >=18`
is an ABI compatibility floor, not security support for EOL Node 18/20. The
Node 20 CI lane checks legacy compatibility only. Bashkit does not bundle Node.

## Quick Start

### Sync Execution
Expand Down
4 changes: 2 additions & 2 deletions examples/hyperlight/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/hyperlight/build-and-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ component="target/bashkit-sandbox.component.wasm"

echo "==> building guest (wasm32-unknown-unknown, no JS, no WASI)"
RUSTFLAGS='--cfg getrandom_backend="custom"' \
cargo build --release --target wasm32-unknown-unknown
cargo build --locked --release --target wasm32-unknown-unknown

echo "==> wrapping core module as a component"
wasm-tools component new "$core" -o "$component"
Expand All @@ -26,7 +26,7 @@ if grep -qv '"bashkit:sandbox/host"' <<<"$imports"; then
fi

echo "==> running under wasmtime"
actual=$(cd host && cargo run --release --quiet -- "../$component" "$(cat "$here/smoke.sh")")
actual=$(cd host && cargo run --locked --release --quiet -- "../$component" "$(cat "$here/smoke.sh")")
expected=$'beta gamma alpha \n6\nslept 1s'

echo "$actual"
Expand Down
6 changes: 6 additions & 0 deletions knowledge/log.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Bashkit Knowledge Update Log

## 2026-10-24

* **Runtime security completion**: Pin CI/release Node lanes to patched 22.23.4/24.22.1; document legacy Node20 as compatibility-only. Align standalone Hyperlight Tokio with patched root/fuzz 1.53.3 for RUSTSEC-2026-0386. Cargo lockfile audits now fail on unsound warnings, with a regression preserving coverage of other ecosystems.
* **Windows dependency**: Replace yanked clipboard-win5.4.1 with 5.4.3 via Rustyline; reviewed the HTML range/copy safety delta and recorded a precise cargo-vet delta audit without new exemptions or publisher trust. Rustyline calls Unicode reads, so exploitation through the changed HTML API is not established.
* **Advisory retirement**: Remove the npm braces suppression after GitHub withdrew GHSA-vfj7-8cjw-p6xm on 2026-10-23; braces3.0.3 remains in AVA's dev-only graph, not patched code. RSA Marvin remains accepted only for opt-in SSH: the latest published RSA prerelease still warns of exposure, and russh pins rc.18. See [Threat Model](security/threat-model.md).

## 2026-10-16

* **Browser live runtime callbacks**: Integrated the runtime dispatcher with live byte sinks, bounded capture and command pipelines after the streaming API landed. Both execution paths retain request-local leases; tests cover async sink completion/deadlines, abort/reuse, reset and caller context. See [Browser Package](runtimes/browser-package.md).
Expand Down
9 changes: 9 additions & 0 deletions knowledge/runtimes/node-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ queued calls, worker threads, adapters, reentry, bad values and snapshot/reset.
`runtime-compat/runtime-functions.test.mjs` runs in Node, Bun and Deno. Dedicated
macOS and Windows CI runs the callback suite as well as Linux's runtime matrix.

## Host runtime security

Build/release jobs use Node 24.22.1 and general CI uses 22.23.4, the patched
October 2026 releases. The runtime matrix explicitly tests both versions.
Node 20 remains an EOL compatibility-only lane; its green result does not imply
security support. The npm `engines >=18` field is the native ABI compatibility
floor, not a security-supported runtime list. Consumers supply Node themselves
and must use a currently patched supported runtime. No Node executable is bundled.

## See also

- [Python Package](python-package.md)
Expand Down
2 changes: 2 additions & 0 deletions knowledge/runtimes/non-js-wasm.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ tags:

Experiment, proven end-to-end under wasmtime. See `examples/hyperlight/`.
Not published as a package; no micro-VM boot test yet (needs KVM/WHP hardware).
The end-to-end smoke builds both standalone guest and host with `--locked`, so
their audited dependency graphs cannot silently change during verification.

## Abstract

Expand Down
15 changes: 12 additions & 3 deletions knowledge/security/threat-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -1853,16 +1853,25 @@ checks.
|----------|-------|----------------|-------------|
| RUSTSEC-2023-0071 | `rsa` | Marvin timing sidechannel (TM-CRY-002). No patched version exists; reachable only via the opt-in `ssh` feature | `rsa` ships a constant-time release |
| RUSTSEC-2023-0089 | `atomic-polyfill` | Unmaintained, no known vulnerability; transitive via `monty` → `postcard` → `heapless` (pinned at 0.7, which still requires it) | Upstream drops the dependency |
| GHSA-vfj7-8cjw-p6xm | `braces` (npm) | Stack-exhaustion DoS through deeply nested patterns. No patched version exists — 3.0.3 is both the latest release and the last affected one. Reached only as `ava` → `globby` → `fast-glob` → `micromatch` → `braces`, a devDependency of `crates/bashkit-js`, globbing test-file patterns committed to this repo; it is not in the published package's `files` list, so no consumer installs it | `braces` ships a release above 3.0.3 |

A suppression that stops matching is not evidence that it can be dropped.
`cargo deny check advisories` currently warns `advisory-not-detected` for
RUSTSEC-2023-0071, because `ssh-key` resolves `rsa` to a pre-release
(0.10.0-rc.18) and RustSec version ranges do not match pre-release versions.
The advisory still carries `patched = []`, so the exposure is unchanged and
matching resumes as soon as `rsa` ships a stable release. Before removing any
entry above, check the advisory's own `patched` list rather than the scanner's
silence.
entry above, verify the advisory's own patched release, dependency removal, or
explicit upstream withdrawal rather than the scanner's silence.

Retired: [GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm)
(`braces`, npm), withdrawn by GitHub on 2026-10-23 at 12:53:02 UTC because it
was not a practically exploitable vulnerability. The AVA dev-only chain still
resolves braces 3.0.3; withdrawal is not evidence of patched parser code. The
npm suppression list is now empty, so future findings fail without that exception.

Cargo scans use `--deny unsound` across every discovered lockfile. Informational
soundness findings such as RUSTSEC-2026-0386 must fail the required audit gate,
not merely print a warning. Other documented risk decisions remain unchanged.

Retired: RUSTSEC-2026-0173 (`proc-macro-error2`, unmaintained). Its recorded
removal condition — "`tabled` releases a version without it" — was met by
Expand Down
32 changes: 6 additions & 26 deletions scripts/audit-lockfiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,11 @@ IGNORED_ADVISORIES=(
RUSTSEC-2023-0071
)

# npm advisories, by GHSA (or CVE) id. A patched release is almost always
# reachable by a bump, because the npm dependencies are all dev- or
# example-only; the entry below is the exception the mechanism exists for. It
# landed on 2026-10-02 against the newest published version of the package,
# with no fixed release to move to, so the choice is an explicit, documented
# acceptance or a red scan that stays red — not a pinned floor nobody records.
#
# It is a `last_affected` advisory in OSV, not a `fixed` one: there is no
# patched version, so re-check the advisory's own fixed-range before dropping
# the entry. A sibling entry for GHSA-ch52-4w7c-c8xp
# (`http-cache-semantics`) was dropped this way once 4.3.0 published above its
# `last_affected` 4.2.0; `site/package.json` now pins that floor as an
# override. The package below reaches no consumer of a published artifact.
#
# GHSA-vfj7-8cjw-p6xm — stack-exhaustion DoS in `braces` from deeply nested
# patterns. Reached only as ava → globby → fast-glob → micromatch → braces, a
# devDependency of crates/bashkit-js: the test runner globbing test-file
# patterns that live in this repo. `braces` 3.0.3 is both the latest release
# and the last affected one. The published package ships the files listed in
# its package.json `files` array, so no consumer installs this chain. Drop
# once `braces` ships a release above 3.0.3.
#
IGNORED_NPM_ADVISORIES=(
GHSA-vfj7-8cjw-p6xm
)
# npm advisories, by GHSA/CVE id. No active exceptions. The previous
# GHSA-vfj7-8cjw-p6xm (braces) exception was retired after GitHub withdrew
# the advisory on 2026-10-23 as not practically exploitable. This is not a
# patched-code claim; a newly published finding must fail normally.
IGNORED_NPM_ADVISORIES=()

# PyPI advisories, by OSV (or GHSA) id. Empty: nothing has yet needed
# suppressing here. Same bar as the npm list above — an entry needs a rationale
Expand Down Expand Up @@ -125,7 +105,7 @@ found=0
while IFS= read -r lock; do
found=$((found + 1))
echo "::group::cargo audit $lock"
cargo audit ${cargo_ignore_flags[@]+"${cargo_ignore_flags[@]}"} -f "$lock" || status=1
cargo audit --deny unsound ${cargo_ignore_flags[@]+"${cargo_ignore_flags[@]}"} -f "$lock" || status=1
echo "::endgroup::"
done < <(discover Cargo.lock)
require_found "$found" Cargo.lock
Expand Down
23 changes: 21 additions & 2 deletions scripts/tests/test_audit_lockfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def suppressions(name):


class AuditLockfilesTests(unittest.TestCase):
def run_script(self, locks):
def run_script(self, locks, cargo_stub=None):
"""Run the script against a temp tree containing `locks`, return (result, calls)."""
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
Expand All @@ -77,7 +77,7 @@ def run_script(self, locks):
(root / 'scripts/lib/npm_audit.py', 'npm'),
(root / 'scripts/lib/pypi_audit.py', 'pypi'),
):
target.write_text(STUB.format(label=label))
target.write_text(cargo_stub if label == "cargo" and cargo_stub else STUB.format(label=label))
target.chmod(target.stat().st_mode | stat.S_IEXEC)

calls_file = root / 'calls.txt'
Expand Down Expand Up @@ -157,6 +157,25 @@ def test_one_failing_lockfile_fails_the_scan(self):
self.assertEqual(result.returncode, 1)
self.assertEqual(len(self.by_label(calls, 'cargo')), 3, calls)

def test_unsound_warning_fails_scan_without_hiding_other_ecosystems(self):
# cargo-audit normally returns success for informational unsoundness.
# Simulate a finding in a standalone workspace, honoring its deny flag.
cargo_stub = """#!/bin/sh
echo "cargo $@" >> "$AUDIT_CALLS"
case "$*" in
*hyperlight*)
case "$*" in *"--deny unsound"*) exit 1 ;; esac ;;
esac
exit 0
"""
result, calls = self.run_script(
ALL_LOCKS + ['examples/hyperlight/Cargo.lock'], cargo_stub=cargo_stub
)
self.assertEqual(result.returncode, 1)
self.assertEqual(len(self.by_label(calls, 'cargo')), 3, calls)
self.assertEqual(len(self.by_label(calls, 'npm')), 2, calls)
self.assertEqual(len(self.by_label(calls, 'pypi')), 1, calls)

def test_a_failure_in_one_ecosystem_still_audits_the_others(self):
# An npm advisory must not stop the cargo or PyPI scan: each ecosystem
# is reported separately so one never masks another.
Expand Down
6 changes: 6 additions & 0 deletions supply-chain/audits.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ criteria = "safe-to-deploy"
delta = "4.6.4 -> 4.6.7"
notes = "Reviewed defer attribute codegen (Defer magic attr, bool-lit helper, initial/final method ordering); proc-macro output only, no new unsafe or ambient access."

[[audits.clipboard-win]]
who = "Mykhailo Chalyi <mike@chaliy.name>"
criteria = "safe-to-deploy"
delta = "5.4.1 -> 5.4.3"
notes = "Reviewed the complete source delta against the existing exempted baseline. HTML fragment offsets use checked subtraction followed by str::get and Vec::extend_from_slice, replacing unchecked pointer copying/set_len; malformed ranges or UTF-8 boundaries return invalid_data. The sum equals the parsed end offset after checked subtraction. Clipboard-open retries now sleep 5ms per bounded attempt. No dependency, feature, license, build-script or external-capability changes. Existing Windows FFI baseline was not re-audited. Rustyline uses Unicode clipboard reads, not the changed HTML API."

[[audits.combine]]
who = "Mykhailo Chalyi <mike@chaliy.name>"
criteria = "safe-to-deploy"
Expand Down
Loading