feat: release Shipcheck v0.1.0#1
Conversation
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce1fb9ab83
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function forbiddenMatch(entry: string, forbidden: string): boolean { | ||
| const normalized = entry.replaceAll("\\", "/"); | ||
| const rule = forbidden.replaceAll("\\", "/"); | ||
| if (rule.endsWith("/")) return normalized === rule.slice(0, -1) || normalized.startsWith(rule); |
There was a problem hiding this comment.
Match forbidden directories below wrapper roots
When the forbidden rule ends in /, this branch only matches entries at the archive root (node_modules/... or .git/...). ZIPs with a single wrapper directory are explicitly supported elsewhere, so extension/node_modules/pkg/index.js or extension/.git/config will not produce ZIP_FORBIDDEN_ENTRY despite the default forbidden entries. Also check for nested /${rule} directory segments.
Useful? React with 👍 / 👎.
| const nameLength = u16(view, 26); | ||
| const extraLength = u16(view, 28); | ||
| const dataOffset = entry.localHeaderOffset + 30 + nameLength + extraLength; | ||
| const compressed = await readExactly(handle, dataOffset, entry.compressedSize); |
There was a problem hiding this comment.
Bound compressed ZIP reads before allocation
When an untrusted ZIP has a central-directory entry whose uncompressedSize is under maxEntryBytes but whose compressedSize is very large, this line allocates that advertised compressed length inside readExactly before any compressed-size or file-range bound. A malicious artifact selected by internalVersionSources can therefore force very large memory use instead of being rejected as invalid/unreadable. Bound compressedSize and dataOffset + compressedSize before reading.
Useful? React with 👍 / 👎.
| return current; | ||
| } | ||
|
|
||
| const SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/; |
There was a problem hiding this comment.
Make accepted SemVer forms consistent across checks
With a primary version like 1.2.3+build.7, this accepts the version source, but the README, CHANGELOG, and artifact filename matchers only capture through 1.2.3/prerelease. Matching docs or artifacts then report drift or a missing current version even though they contain the same SemVer. Either reject build metadata here or make every downstream matcher capture the optional +... portion.
Useful? React with 👍 / 👎.
Problem and product position
Release metadata can drift across package manifests, Chrome Extension manifests, README instructions, CHANGELOG headings, artifact filenames, and ZIP-internal manifests. Shipcheck is a local-first, deterministic, CI-friendly pre-release consistency checker.
Implemented
package.json,manifest.json, and arbitrary JSON pathsshipcheck initnpm auditExplicitly not included
Validation
Local validation completed:
npm ci: pass, 0 vulnerabilitiesnpm run lint: passnpm run typecheck: passnpm test: 88/88 passnpm run test:coverage: lines 94.91%, branches 84.36%, functions 97.99%npm run build: passnpm pack: pass; 65 files, 27.5 kB tarballnode dist/cli.js . --ci: pass, 0 errors/warnings/infoCross-platform validation
The final PR CI matrix passed on Ubuntu, Windows, and macOS with Node.js 20 and 24. Earlier runs exposed shell glob incompatibility and Windows command-shim behavior; both were fixed without skipping tests. The dedicated package job also passed coverage,
npm pack, tarball installation, self-check, andnpm audit.Security considerations
Shipcheck never executes scanned repository code or JavaScript configuration, never extracts ZIP files, and performs no network requests or telemetry. Paths must remain inside the selected root. ZIP inspection is bounded and rejects unsafe or unsupported structures. Runtime code intentionally has no third-party dependencies.
GitHub Dependency Review was attempted on the first PR run but the action failed because the new repository's dependency-review platform capability was unavailable. The workflow was removed rather than marked
continue-on-error; CodeQL andnpm auditremain enforced and both passed.Known limitations
Acceptance checklist
main(a14330cb101645f60f3aa10ca0df4a1a60bc0dac)mainpush-run status could not be queried by the connected GitHub tool; its workflow-run endpoint exposes pull-request runs onlyExternal release-tool limitation
The connected GitHub tool does not expose tag or GitHub Release creation endpoints. No branch was created as a fake substitute for tag
v0.1.0, and npm publication is not claimed.