Skip to content

ffi: new DynamicLibrary() reads a VFS path before checking --allow-ffi #67368

Open

Description

@trivikr

Version

main

Platform

macOS

Subsystem

ffi

What steps will reproduce the bug?

// repro.mjs
import { DynamicLibrary, dlopen } from 'node:ffi';
import { create } from 'node:vfs';

const path = `${create().mount()}/missing.so`;

for (const [name, open] of [
  ['new DynamicLibrary()', () => new DynamicLibrary(path)],
  ['ffi.dlopen()', () => dlopen(path, {})],
]) {
  try {
    open();
  } catch (err) {
    console.log(`${name}: ${err.code}`);
  }
}

Run with

$ node --permission '--allow-fs-read=*' --allow-fs-vfs --no-warnings repro.mjs

How often does it reproduce? Is there a required condition?

Always. It requires --permission without --allow-ffi, a mounted VFS, and a path under the VFS mount point. It happens only with new DynamicLibrary(path). ffi.dlopen() checks the permission first.

What is the expected behavior? Why is that the expected behavior?

Both calls should throw ERR_ACCESS_DENIED:

new DynamicLibrary(): ERR_ACCESS_DENIED
ffi.dlopen(): ERR_ACCESS_DENIED

The FFI docs say "When using the Permission Model, FFI APIs are restricted unless the --allow-ffi flag is provided". The new DynamicLibrary(path) section says a VFS path "loads the same way as with ffi.dlopen()", and ffi.dlopen() already throws ERR_ACCESS_DENIED here.

What do you see instead?

new DynamicLibrary(): ENOENT
ffi.dlopen(): ERR_ACCESS_DENIED

If the VFS file exists, the constructor reads all of its bytes and only then throws ERR_ACCESS_DENIED.

Additional information

No response

Activity

  1. self-assigned this
    on Nov 9, 2026
  2. added
    ffiIssues and PRs related to experimental Foreign Function Interface support.
    on Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

ffiIssues and PRs related to experimental Foreign Function Interface support.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions