Skip to content

Cancellation flag race condition with Relaxed ordering in Node.js bindings #992

@chaliy

Description

@chaliy

Summary

Both Bash::execute_sync and BashTool::execute_sync reset the cancellation flag at the start using Ordering::Relaxed. If two threads call execute_sync and cancel() concurrently, the relaxed ordering provides no happens-before guarantee. A cancel() call could be swallowed by a concurrent execute_sync that resets the flag. The async execute() method does NOT reset the flag, creating inconsistent behavior.

Severity: Low
Category: Race Condition / Concurrency

Affected Files

  • crates/bashkit-js/src/lib.rs lines 275-276, 584-585

Code

self.state.cancelled.store(false, Ordering::Relaxed);

Steps to Reproduce

// Thread 1:
bash.cancel();
// Thread 2 (concurrent):
bash.executeSync("sleep 10");  // Resets cancelled flag, swallowing the cancel

Impact

Cancellation requests silently lost in concurrent usage. Scripts continue running when they should have been cancelled.

Acceptance Criteria

  • Use Ordering::SeqCst or Release/Acquire pairs for the cancelled flag
  • Or: use a generation counter so cancellation targets a specific execution
  • Make execute_sync and execute consistent in their reset behavior
  • Test: Concurrent cancel + execute doesn't lose the cancellation

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerability or hardening

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions