Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/SECURITY-HARDENING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Recent npm compromises have used maintainer account takeover, malicious pull req
Required controls:

- Configure npm trusted publishing for package `veryfront` and every generated `@veryfront/ext-*` package: GitHub Actions publisher, owner `veryfront`, repository `veryfront-code`, workflow filename `cicd.yml`, environment `production`, action `npm publish`.
- Before merging a new publishable package into a stable release, an npm organization owner must create its package name once using a prerelease version and a non-`latest` dist-tag, then configure the trusted publisher above. Never use the intended stable release version for this bootstrap: npm versions are immutable, and a manual publish does not carry the GitHub release commit provenance required by CI.
Comment thread
kojiwakayama marked this conversation as resolved.
Outdated
- Keep `.github/workflows/cicd.yml` release jobs on `permissions: id-token: write` and publish with `npm publish --provenance --access public`.
- Do not reference `secrets.NPM_TOKEN` or `NODE_AUTH_TOKEN` in npm publish steps.
- Remove the repository or organization `NPM_TOKEN` secret after trusted publishing is configured and one dry release check confirms npm accepts OIDC authentication.
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "veryfront",
"version": "0.1.1188",
"version": "0.1.1189",
"license": "Apache-2.0",
"nodeModulesDir": "auto",
"minimumDependencyAge": {
Expand Down
17 changes: 17 additions & 0 deletions scripts/ci/publish-npm-packages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,25 @@ run_rc_publish() {
done
}

ensure_package_names_registered() {
MISSING_PACKAGE_NAMES=0

for PACKAGE_NAME in $(package_names_from_workspace); do
if ! npm view "${PACKAGE_NAME}@*" name >/dev/null 2>&1; then
echo "::error::${PACKAGE_NAME} is not registered on npm." >&2
MISSING_PACKAGE_NAMES=1
fi
done

if [ "${MISSING_PACKAGE_NAMES}" -ne 0 ]; then
echo "::error::Before releasing, bootstrap the package and configure trusted publishing. Use a prerelease version and a non-latest dist-tag so the stable release version remains available to CI." >&2
return 1
fi
Comment thread
kojiwakayama marked this conversation as resolved.
}

run_preflight() {
require_env VERSION GITHUB_SHA
ensure_package_names_registered

for PACKAGE_NAME in $(package_names_from_workspace); do
if npm view "${PACKAGE_NAME}@${VERSION}" version 2>/dev/null; then
Expand Down
49 changes: 49 additions & 0 deletions scripts/ci/publish-npm-packages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,52 @@ Deno.test("npm release rerun skips a package already published for the commit",
await Deno.remove(stateDir, { recursive: true });
}
});

Deno.test("npm release preflight rejects an unbootstrapped package name", async () => {
const stateDir = await Deno.makeTempDir();
const npmLog = `${stateDir}/npm.log`;
await Deno.writeTextFile(npmLog, "");

try {
const output = await runBash(
[
"set -euo pipefail",
'source "$SCRIPT_PATH"',
"package_names_from_workspace() {",
' printf "%s\\n" "@veryfront/ext-existing" "@veryfront/ext-new"',
"}",
"npm() {",
' printf "%s\\n" "$*" >> "$NPM_LOG"',
' if [ "$1" = "view" ] && [ "$2" = "@veryfront/ext-existing@*" ] && [ "$3" = "name" ]; then',
' printf "%s\\n" "@veryfront/ext-existing"',
" return 0",
" fi",
" return 1",
"}",
"run_preflight",
].join("\n"),
{
GITHUB_SHA: "expected-commit",
NPM_LOG: npmLog,
VERSION: "0.1.1189",
},
);

assertEquals(output.code, 1);
Comment thread
kojiwakayama marked this conversation as resolved.
Outdated
assertStringIncludes(
decoder.decode(output.stderr),
"@veryfront/ext-new is not registered on npm",
);
assertStringIncludes(
decoder.decode(output.stderr),
"bootstrap the package and configure trusted publishing",
);
const calls = (await Deno.readTextFile(npmLog)).trim().split("\n");
assertEquals(calls, [
"view @veryfront/ext-existing@* name",
"view @veryfront/ext-new@* name",
]);
} finally {
await Deno.remove(stateDir, { recursive: true });
}
});

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/utils/version-constant.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Keep in sync with deno.json version.
// scripts/release.ts updates this constant during releases.
/** Shared version value. */
export const VERSION = "0.1.1188";
export const VERSION = "0.1.1189";
Loading