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.
Summary
scripts/check-package.mjsrejects a valid npm tarball on Windows when the systemtarcommand emits CRLF line endings fortar -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\rand\n. The following\nis then tested as if it were the first character of a new line and triggers the non-regular-entry error.Affected version and environment
@openai/codex-security@0.1.1mainatf22d4a36f26d16287bcdfd707b369116e02a08c3Steps to reproduce
From the repository root:
Observed error:
I then captured the exact
tar --ignore-zeros -tvzfoutput and checked every non-empty line. The generated archive contained 178 entries, and every listing line began with-ord; there were no links, devices, or pipes.The package installation smoke test also passed:
A minimal diagnostic using the same listing demonstrated the false match:
Expected behavior
A valid npm tarball containing only regular files and allowed directories should pass
check-package.mjsregardless of whether the localtarcommand 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
tarimplementation cannot run the repository's package-boundary validation locally, even though the generated package is valid and installable.Relevant code
codex-security/sdk/typescript/scripts/check-package.mjs
Lines 183 to 190 in f22d4a3
listingLines:codex-security/sdk/typescript/scripts/check-package.mjs
Lines 188 to 198 in f22d4a3
PR #3 introduced the package-boundary checker and validated a Windows CI configuration, but its patch and review discussion do not cover a
tarimplementation 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:
A focused regression test can pass a CRLF-formatted verbose listing with only regular files and assert that it is accepted.