Skip to content

fs: keep openAsBlob paths stable across chdir - #67346

Open
cqxg wants to merge 1 commit into
nodejs:mainfrom
cqxg:fs-openasblob-pin-cwd
Open

cqxg wants to merge 1 commit into
nodejs:mainfrom
cqxg:fs-openasblob-pin-cwd

Conversation

@cqxg

@cqxg cqxg commented Nov 8, 2026 •

Copy link
Copy Markdown

openAsBlob() and openAsBlobSync() stored the caller path and reopened it on every read. A relative path was resolved against the cwd again, so process.chdir() could read a different file of the same size and mtime, or fail the read. Pin the directory the path was opened against when the blob is created, without lexically collapsing ".." so symlink traversal stays the same.

Verified on Linux x64 by building this tree. The new test failed on the
unfixed binary ('from-b' !== 'from-a') and passed after the rebuild.
Also passed: test-blob-file-backed, test-fs-openAsBlobSync,
test-vfs-fs-openAsBlob, test-blob-file-webidl,
test-permission-fs-read, and test-permission-fs-supported.
cpplint, the include check, clang-format, and ESLint were clean.
Windows and macOS were not run.

A coding agent prepared the change. The build and the test results above
were run locally.

Fixes: #67282

openAsBlob() and openAsBlobSync() stored the caller path and reopened
it on every read. A relative path was resolved against the cwd again,
so process.chdir() could read a different file of the same size and
mtime, or fail the read. Pin the directory the path was opened
against when the blob is created, without lexically collapsing ".."
so symlink traversal stays the same.

Signed-off-by: Ihar Ivaniuk <ihar.o.ivaniuk@gmail.com>
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Nov 8, 2026
@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Welcome to Node.js, and thank you for your first contribution!

Before review, please take a moment to read:

Please make sure every commit is signed off. For a first pull request, GitHub Actions require collaborator approval and Jenkins CI must be started by a collaborator or triager, so an initial wait is normal.

Comment thread src/node_blob.cc
return buf;
}

#ifdef _WIN32

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On Windows, could we just store the path already resolved by ToNamespacedPath() instead of adding all this?

const { pathToFileURL } = require('node:url');

if (process.argv[2] !== 'child') {
const child = spawnSync(process.execPath, [__filename, 'child'], {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this to avoid the worker thread from the test harness? You can skip instead. It's not necessary to test this under worker mode.

if (!common.isMainThread)
  common.skip('process.chdir is not available in Workers');

assert.strictEqual(child.status, 0, output);
} else {
(async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'openasblob-chdir-'));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The convention is to use common/tmpdir

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blob created by openAsBlob changes contents after chdir

3 participants