Skip to content

check-package.mjs rejects valid npm tarballs when Windows tar emits CRLF #32

Description

@ShawnSiao

Summary

scripts/check-package.mjs rejects a valid npm tarball on Windows when the system tar command emits CRLF line endings for tar -tvzf.

The validation uses a multiline regular expression directly on the complete listing. In JavaScript, both CR and LF are line terminators for multiline anchors, so ^ can match between the \r and \n. The following \n is then tested as if it were the first character of a new line and triggers the non-regular-entry error.

Affected version and environment

  • Released package: @openai/codex-security@0.1.1
  • Confirmed still present on current main at f22d4a36f26d16287bcdfd707b369116e02a08c3
  • Microsoft Windows NT 10.0.19045.0
  • PowerShell 7.6.3
  • Node.js 24.18.0
  • pnpm 11.17.0
  • bsdtar 3.5.2 / libarchive 3.5.2

Steps to reproduce

From the repository root:

cd sdk/typescript
corepack pnpm install --frozen-lockfile
corepack pnpm run build
corepack pnpm pack --pack-destination ../../dist
node scripts/check-package.mjs ../../dist/openai-codex-security-0.1.1.tgz

Observed error:

Error: npm tarball contains a non-regular entry (symbolic or hard link, device, or pipe).
    at scripts/check-package.mjs:185

I then captured the exact tar --ignore-zeros -tvzf output and checked every non-empty line. The generated archive contained 178 entries, and every listing line began with - or d; there were no links, devices, or pipes.

The package installation smoke test also passed:

Validated installed @openai/codex-security@0.1.1: public import, CLI, and 94 bundled plugin files.

A minimal diagnostic using the same listing demonstrated the false match:

/^[^d-]/mu.exec(listing) matches the LF in the first CRLF sequence.

Expected behavior

A valid npm tarball containing only regular files and allowed directories should pass check-package.mjs regardless of whether the local tar command emits LF or CRLF.

Actual behavior

The validator reports a non-regular tar entry before the later code normalizes the same listing with split(/\r?\n/u).

Impact

Windows contributors using a CRLF-emitting tar implementation cannot run the repository's package-boundary validation locally, even though the generated package is valid and installable.

Relevant code

  • Current check:
    const listing = tar(["-tvzf", archive], "utf8");
    if (/^[^d-]/mu.test(listing)) {
    throw new Error(
    "npm tarball contains a non-regular entry (symbolic or hard link, device, or pipe).",
    );
    }
    const listingLines = listing.split(/\r?\n/u).filter(Boolean);
    if (
  • The code immediately below already creates normalized listingLines:
    }
    const listingLines = listing.split(/\r?\n/u).filter(Boolean);
    if (
    listingLines.length !== entries.length ||
    listingLines.some(
    (line, index) => line.startsWith("d") !== entries[index].endsWith("/"),
    )
    ) {
    throw new Error("npm tarball contains an invalid tar entry.");
    }
    const launcherPermissions =

PR #3 introduced the package-boundary checker and validated a Windows CI configuration, but its patch and review discussion do not cover a tar implementation that emits CRLF for verbose listings.

Suggested direction

Normalize the listing before checking entry types and reuse the normalized lines for both validations. For example:

const listingLines = listing.split(/\r?\n/u).filter(Boolean);
if (
  listingLines.some(
    (line) => !line.startsWith("d") && !line.startsWith("-"),
  )
) {
  throw new Error(
    "npm tarball contains a non-regular entry (symbolic or hard link, device, or pipe).",
  );
}

A focused regression test can pass a CRLF-formatted verbose listing with only regular files and assert that it is accepted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions