Skip to content

fix(js): bound async execute queue#2042

Closed
chaliy wants to merge 1 commit into
mainfrom
2026-06-12-fix-unbounded-queuing-in-async-execute-api
Closed

fix(js): bound async execute queue#2042
chaliy wants to merge 1 commit into
mainfrom
2026-06-12-fix-unbounded-queuing-in-async-execute-api

Conversation

@chaliy

@chaliy chaliy commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Superseded by #2062 — rebased cleanly on main.

Copilot AI review requested due to automatic review settings June 12, 2026 01:28
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit b33bd2c Commit Preview URL Jun 12 2026, 01:29 AM

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the bashkit JS async execute() path against memory/resource exhaustion by bounding per-instance async backlogs and performing early input-size validation before queued work can retain attacker-controlled command strings.

Changes:

  • Add a per-instance semaphore in the Rust N-API layer to reject excess pending async execute() calls before awaiting the interpreter mutex.
  • Add pre-queue maxInputBytes validation in both Rust and the TypeScript wrapper to fail oversized scripts early.
  • Add runtime-compat tests and README documentation for queue-full rejection and pre-queue input validation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
crates/bashkit-js/wrapper.ts Adds bounded per-instance async queue + early input-size checks; exposes maxInputBytes.
crates/bashkit-js/src/lib.rs Adds per-instance semaphore + early async input validation in native layer.
crates/bashkit-js/README.md Documents bounded async backlog and pre-queue input validation behavior.
crates/bashkit-js/test/runtime-compat/streaming-output.test.mjs Adds tests for queue-full rejection and pre-queue maxInputBytes validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 740 to 745
constructor(options?: BashOptions) {
const resolved = resolveFilesSync(options?.files);
this.native = new NativeBash(toNativeOptions(options, resolved));
this.maxInputBytes = options?.maxInputBytes ?? DEFAULT_MAX_INPUT_BYTES;
registerCustomBuiltins(this.native, options?.customBuiltins);
}
Comment on lines 761 to 766
static async create(options?: BashOptions): Promise<Bash> {
const resolved = await resolveFiles(options?.files);
const instance = Object.create(Bash.prototype) as Bash;
instance.native = new NativeBash(toNativeOptions(options, resolved));
instance.maxInputBytes = options?.maxInputBytes ?? DEFAULT_MAX_INPUT_BYTES;
registerCustomBuiltins(instance.native, options?.customBuiltins);
Comment on lines 1168 to 1173
constructor(options?: BashOptions) {
const resolved = resolveFilesSync(options?.files);
this.native = new NativeBashTool(toNativeOptions(options, resolved));
this.maxInputBytes = options?.maxInputBytes ?? DEFAULT_MAX_INPUT_BYTES;
registerCustomBuiltins(this.native, options?.customBuiltins);
}
Comment on lines 1178 to 1183
static async create(options?: BashOptions): Promise<BashTool> {
const resolved = await resolveFiles(options?.files);
const instance = Object.create(BashTool.prototype) as BashTool;
instance.native = new NativeBashTool(toNativeOptions(options, resolved));
instance.maxInputBytes = options?.maxInputBytes ?? DEFAULT_MAX_INPUT_BYTES;
registerCustomBuiltins(instance.native, options?.customBuiltins);
Comment on lines +1165 to +1170
fn max_input_bytes_for_state(state: &SharedState) -> usize {
state.max_input_bytes.map_or_else(
|| ExecutionLimits::default().max_input_bytes,
|v| v as usize,
)
}
@chaliy chaliy closed this Jun 12, 2026
chaliy added a commit that referenced this pull request Jun 12, 2026
…ueing

Closes #2042

execute() calls that arrive while the shell is busy were queued without limit. Caps the per-instance backlog at 8 pending calls and rejects further calls with a clear error. Also validates maxInputBytes before the call enters the queue, and forwards maxInputBytes through toNativeOptions so the Rust core enforces the same limit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants