This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: bun-ffi-pointer-ownership-guardrail

Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail

Enforces strict pointer lifetime management and explicit foreign heap deallocation semantics when interfacing with native dynamic libraries via Bun 1.2 `bun:ffi`. Prevents use-after-free, unmanaged memory leaks across event loop turns, and V8/JSC garbage collector desynchronization by strictly mandating explicit lifetime wrapping, finalization registration, and asynchronous boundary protection.

Prohibited Anti-Pattern: Escaping Raw FFI Pointers Across Asynchronous Event Loop Ticks Without Explicit Heap Ownership or Finalization

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail - Enforces strict pointer lifetime management and explicit foreign heap deallocation semantics when interfacing with native dynamic libraries via Bun 1.2 `bun:ffi`. Prevents use-after-free, unmanaged memory leaks across event loop turns, and V8/JSC garbage collector desynchronization by strictly mandating explicit lifetime wrapping, finalization registration, and asynchronous boundary protection.
globs: src/**/*.{ts,js}, lib/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/bun-ffi-pointer-ownership-guardrail"
---

# Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Escaping Raw FFI Pointers Across Asynchronous Event Loop Ticks Without Explicit Heap Ownership or Finalization

## System Constraints
You are a Principal Systems Engineer and Security Architect enforcing deterministic memory safety for Bun 1.2 native foreign function interfaces (bun:ffi). You must eliminate unmanaged heap leaks, double frees, invalid dereferencing, and asynchronous pointer aliasing by enforcing RAII wrappers, Symbol.dispose/AsyncDispose patterns, and deterministic pointer invalidation.

## Strict Guidelines
- Engineers MUST ALWAYS wrap raw `Pointer` or `JSCallback` values returned from `dlopen` calls into strongly typed RAII container classes implementing `Disposable` or `AsyncDisposable`.
- Engineers MUST NEVER permit raw unmanaged `Pointer` handles to escape into outer microservice application logic or cross `await` suspension boundaries without deterministic lifetime tracking.
- Code MUST explicitly set internal pointer handles to `0` or `null` immediately upon invoking foreign free routines to invalidate dangling pointers and prevent double-free vulnerabilities.
- Services MUST utilize `FinalizationRegistry` strictly as a fail-safe audit mechanism to log critical memory leaks, NEVER as the primary reclamation mechanism for high-throughput native allocations.
- Functions returning buffers or slices via `toArrayBuffer()` MUST explicitly specify byte length and copy the contents into managed JavaScript `Uint8Array` memory if the native backing buffer is freed within the same call frame.

## Bad vs Good Implementations
### Unsafe Raw Pointer Leaks Across Await vs Deterministic RAII Scope Disposal

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The raw FFI pointer `rawPtr` escapes into the asynchronous execution context without RAII protection. If an exception occurs during the async suspension or prior to `free_payload`, the unmanaged C heap memory leaks permanently. If another concurrent task aliases or corrupts the heap before resumption, undefined behavior ensues.
```typescript
import { dlopen, FFIType, ptr } from 'bun:ffi';

const lib = dlopen('libnative.so', {
  alloc_payload: { args: [FFIType.u32], returns: FFIType.ptr },
  free_payload: { args: [FFIType.ptr], returns: FFIType.void },
  process_payload: { args: [FFIType.ptr], returns: FFIType.i32 },
});

export async function handleRequest(size: number): Promise<number> {
  // Anti-pattern: Raw unmanaged pointer crosses async suspension boundary
  const rawPtr = lib.symbols.alloc_payload(size);
  
  // Network I/O or queue dispatch suspends event loop; pointer remains unmanaged
  await Bun.sleep(10);
  
  const result = lib.symbols.process_payload(rawPtr);
  
  // Memory leak or use-after-free if an unhandled rejection occurs prior to this line
  lib.symbols.free_payload(rawPtr);
  return result;
}
```

#### Production Standard (Correct)
> **Standard**: Implements deterministic RAII using TypeScript's `using` keyword and `Symbol.dispose`. The native pointer is validated upon access, zeroed prior to deallocation to preclude double-free bugs, and guaranteed to execute even if asynchronous exceptions occur. A `FinalizationRegistry` audits forgotten cleanup without relying on the garbage collector for deterministic deallocation.
```typescript
import { dlopen, FFIType, Pointer, toArrayBuffer } from 'bun:ffi';

const lib = dlopen('libnative.so', {
  alloc_payload: { args: [FFIType.u32], returns: FFIType.ptr },
  free_payload: { args: [FFIType.ptr], returns: FFIType.void },
  process_payload: { args: [FFIType.ptr], returns: FFIType.i32 },
});

const leakAuditor = new FinalizationRegistry((symbolName: string) => {
  console.error(`[CRITICAL FFI LEAK] Memory allocated by ${symbolName} was garbage collected without explicit disposal.`);
});

export class NativeBufferScope implements Disposable {
  private handle: Pointer | null;

  constructor(size: number) {
    this.handle = lib.symbols.alloc_payload(size);
    if (!this.handle) {
      throw new Error('Native allocation failed: Out of memory');
    }
    leakAuditor.register(this, 'alloc_payload', this);
  }

  get pointer(): Pointer {
    if (!this.handle) {
      throw new Error('Use-after-free error: Pointer has already been disposed');
    }
    return this.handle;
  }

  [Symbol.dispose](): void {
    if (this.handle !== null) {
      const ptrToFree = this.handle;
      this.handle = null; // Invalidate handle before native free to prevent re-entrancy bugs
      leakAuditor.unregister(this);
      lib.symbols.free_payload(ptrToFree);
    }
  }
}

export async function handleRequest(size: number): Promise<number> {
  // Deterministic RAII lifecycle: automatically disposed on scope exit regardless of async errors
  using scope = new NativeBufferScope(size);
  
  await Bun.sleep(10);
  
  return lib.symbols.process_payload(scope.pointer);
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail

Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail defines an industrial-grade behavioral standard for backend engineering. Enforces strict pointer lifetime management and explicit foreign heap deallocation semantics when interfacing with native dynamic libraries via Bun 1.2 `bun:ffi`. Prevents use-after-free, unmanaged memory leaks across event loop turns, and V8/JSC garbage collector desynchronization by strictly mandating explicit lifetime wrapping, finalization registration, and asynchronous boundary protection. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Escaping Raw FFI Pointers Across Asynchronous Event Loop Ticks Without Explicit Heap Ownership or Finalization Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftEscaping Raw FFI Pointers Across Asynchronous Event Loop Ticks Without Explicit Heap Ownership or FinalizationCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS wrap raw `Pointer` or `JSCallback` values returned from `dlopen` calls into strongly typed RAII container classes implementing `Disposable` or `AsyncDisposable`.

Engineers MUST ALWAYS wrap raw `Pointer` or `JSCallback` values returned from `dlopen` calls into strongly typed RAII container classes implementing `Disposable` or `AsyncDisposable`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NEVER permit raw unmanaged `Pointer` handles to escape into outer microservice application logic or cross `await` suspension boundaries without deterministic lifetime tracking.

Engineers MUST NEVER permit raw unmanaged `Pointer` handles to escape into outer microservice application logic or cross `await` suspension boundaries without deterministic lifetime tracking.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Code MUST explicitly set internal pointer handles to `0` or `null` immediately upon invoking foreign free routines to invalidate dangling pointers and prevent double-free vulnerabilities.

Code MUST explicitly set internal pointer handles to `0` or `null` immediately upon invoking foreign free routines to invalidate dangling pointers and prevent double-free vulnerabilities.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Services MUST utilize `FinalizationRegistry` strictly as a fail-safe audit mechanism to log critical memory leaks, NEVER as the primary reclamation mechanism for high-throughput native allocations.

Services MUST utilize `FinalizationRegistry` strictly as a fail-safe audit mechanism to log critical memory leaks, NEVER as the primary reclamation mechanism for high-throughput native allocations.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Functions returning buffers or slices via `toArrayBuffer()` MUST explicitly specify byte length and copy the contents into managed JavaScript `Uint8Array` memory if the native backing buffer is freed within the same call frame.

Functions returning buffers or slices via `toArrayBuffer()` MUST explicitly specify byte length and copy the contents into managed JavaScript `Uint8Array` memory if the native backing buffer is freed within the same call frame.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Deterministic Bun 1.2 Native FFI Pointer Ownership and Memory Safety Guardrail critical for AI coding assistants?

Enforces strict pointer lifetime management and explicit foreign heap deallocation semantics when interfacing with native dynamic libraries via Bun 1.2 `bun:ffi`. Prevents use-after-free, unmanaged memory leaks across event loop turns, and V8/JSC garbage collector desynchronization by strictly mandating explicit lifetime wrapping, finalization registration, and asynchronous boundary protection. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Escaping Raw FFI Pointers Across Asynchronous Event Loop Ticks Without Explicit Heap Ownership or Finalization) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Deterministic