Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
109 changes: 109 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Publish to npm

on:
push:
tags:
- 'v*'

jobs:
publish:
runs-on: ubuntu-latest
# 環境保護: production環境を使用(要手動承認設定)
environment:
name: npm-publish
url: https://www.npmjs.com/package/react-github-ribbons

# 最小権限原則
permissions:
contents: read
id-token: write # provenance署名用

steps:
- name: Checkout code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# タグの完全な履歴を取得
fetch-depth: 0

- name: Verify tag format
run: |
TAG_NAME="${GITHUB_REF#refs/tags/}"
if ! [[ "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
echo "Error: Invalid tag format. Expected vX.Y.Z or vX.Y.Z-prerelease"
exit 1
fi
echo "Tag format verified: $TAG_NAME"

- name: Setup Node.js
uses: actions/setup-node@60edb5dd545a775178f52524783378180ac39da4 # v4.0.2
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
cache: 'npm'

- name: Verify package-lock.json integrity
run: |
if ! npm ci --dry-run; then
echo "Error: package-lock.json integrity check failed"
exit 1
fi

- name: Install dependencies
run: npm ci --audit=true

- name: Audit dependencies
run: |
npm audit --audit-level=high || {
echo "Warning: High severity vulnerabilities detected"
# 本番環境では exit 1 を検討
}

- name: Lint
run: npm run lint

- name: Build
run: npm run build

- name: Test
run: npm test

- name: Verify package contents
run: |
# distディレクトリが存在し、空でないことを確認
if [ ! -d "dist" ] || [ -z "$(ls -A dist)" ]; then
echo "Error: dist directory is missing or empty"
exit 1
fi
# 必須ファイルの存在確認
if [ ! -f "dist/index.js" ] || [ ! -f "dist/index.cjs" ] || [ ! -f "dist/index.d.ts" ]; then
echo "Error: Required build artifacts are missing"
exit 1
fi

- name: Verify package version matches tag
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
PACKAGE_VERSION=$(node -p "require('./package.json').version")
if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then
echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)"
exit 1
fi
echo "Version verified: $PACKAGE_VERSION"

- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Comment on lines +93 to +96

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Missing NPM_CONFIG_PROVENANCE environment variable for provenance signing.

npm provenance requires the NPM_CONFIG_PROVENANCE environment variable set to true in the GitHub Actions workflow, in addition to the --provenance flag. Without this environment variable, provenance signing may not be properly configured.

Add the missing environment variable:

  - name: Publish to npm
    run: npm publish --provenance --access public
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+     NPM_CONFIG_PROVENANCE: true

Additionally, npm classic token creation is now disabled as of November 19, 2025, and you should migrate to trusted publishing or granular access tokens to avoid disruption. Consider migrating from long-lived tokens to trusted publishers which use short-lived, scoped credentials that eliminate the need for long-lived tokens and reduce security risks.

🤖 Prompt for AI Agents
.github/workflows/publish.yml around lines 38 to 41: the Publish to npm step is
missing the NPM_CONFIG_PROVENANCE environment variable required for npm
provenance signing; add NPM_CONFIG_PROVENANCE set to "true" to the step's env
block so the --provenance flag works as intended, and keep NODE_AUTH_TOKEN
as-is; additionally, plan to migrate from classic long-lived tokens to trusted
publishers or granular access tokens and update workflow secrets accordingly.


- name: Create GitHub Release
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const tagName = context.ref.replace('refs/tags/', '');
await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tagName,
name: tagName,
generate_release_notes: true,
});
7 changes: 7 additions & 0 deletions .nprc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"yarn": false,
"anyBranch": false,
"2fa": false,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

Disabling two-factor authentication (2FA) for publishing ("2fa": false) is a critical security risk. If your npm credentials are ever compromised, an attacker could publish malicious versions of your package. It is strongly recommended to enable 2FA on your npm account and require it for publishing.

  "2fa": true,

"contents": ".",
"cleanup": true
}
Comment on lines +1 to +7

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Disable 2FA requirement in .nprc introduces security risk.

The setting "2fa": false disables npm's 2-factor authentication verification for releases. This weakens the security posture when publishing packages, as it removes an important protection against account compromise or unauthorized releases.

Enable 2FA verification to strengthen package security:

{
  "yarn": false,
  "anyBranch": false,
-  "2fa": false,
+  "2fa": true,
  "contents": ".",
  "cleanup": true
}

If there are operational reasons for disabling 2FA here, consider implementing compensating controls such as:

  • GitHub branch protections requiring approval before tag pushes
  • IP allow-lists on the GitHub organization or npm account
  • Audit logging and alerts on all releases
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"yarn": false,
"anyBranch": false,
"2fa": false,
"contents": ".",
"cleanup": true
}
{
"yarn": false,
"anyBranch": false,
"2fa": true,
"contents": ".",
"cleanup": true
}
🤖 Prompt for AI Agents
.nprc lines 1-7: the config currently sets "2fa": false which disables npm
two-factor auth for releases; change this to enable 2FA by setting "2fa": true
(or remove the key so the default enforces 2FA) and update release docs to
require personal or org-level 2FA for any account that publishes; if there are
operational constraints that prevent enabling 2FA, implement compensating
controls such as branch protections preventing direct tag pushes, IP allow-lists
for CI/publish runners, and alerting/audit logging for all publish events and
document those exceptions.

57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,59 @@ npm run format
3. Run `npm test` to verify tests pass
4. Run `npm run lint` to check code quality

The library will be built to `/dist` with both ESM and CommonJS formats.
The library will be built to `/dist` with both ESM and CommonJS formats.

## Release

This project uses automated release tooling with security best practices.

### Publishing a New Version

```bash
npm run release
```

The `np` package will guide you through:
- Version selection (patch/minor/major)
- Running tests, lint, and build
- Creating git tags
- Publishing to npm with provenance
- Creating GitHub releases

### Security Features

Our release process includes multiple security layers:

- ✅ **Environment Protection** - Requires manual approval for npm publish
- ✅ **Tag Verification** - Validates semantic versioning format
- ✅ **Version Matching** - Ensures package.json and git tag alignment
- ✅ **Dependency Audits** - Scans for vulnerabilities before publish
- ✅ **Build Verification** - Validates all required artifacts exist
- ✅ **NPM Provenance** - Cryptographically signed build attestations
- ✅ **Pinned Actions** - GitHub Actions locked to SHA hashes

For complete security details, see [SECURITY.md](./SECURITY.md).

### First-time Setup (Maintainers)

1. **Configure npm-publish environment** in GitHub:
```
Settings → Environments → New environment: "npm-publish"
- Add required reviewers
- Set deployment branch rule: "Tags only"
```

2. **Add NPM_TOKEN secret**:
```
Settings → Secrets → New repository secret
Name: NPM_TOKEN
Value: [Your npm automation token]
```

3. **Enable npm 2FA**:
```bash
npm profile enable-2fa auth-and-writes
```

4. **Set up branch protection** for `main`/`master`
5. **Set up tag protection** for `v*` pattern
154 changes: 154 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Security Policy

## Release Security

このプロジェクトでは、サプライチェーン攻撃を防ぐため、以下のセキュリティ対策を実施しています。

### 🔒 実装済みの対策

#### 1. GitHub Environment Protection
- **環境名**: `npm-publish`
- **保護レベル**: 要手動承認(推奨設定)
- リリース時に信頼できる管理者の承認が必須

#### 2. タグとバージョンの検証
- セマンティックバージョニング形式の強制 (`vX.Y.Z`)
- package.jsonのバージョンとGitタグの一致確認
- 不正なタグによる公開を防止

#### 3. 依存関係の整合性チェック
- `package-lock.json`の整合性検証
- `npm audit`による脆弱性スキャン
- 高リスクの依存関係を検出

#### 4. ビルド成果物の検証
- 必須ファイルの存在確認
- 空ディレクトリの検出
- 改ざん防止

#### 5. GitHub Actions セキュリティ
- アクションをSHA256ハッシュで固定(タグ改ざん対策)
- 最小権限の原則(`permissions`で制限)
- Provenance署名によるパッケージの証明

#### 6. NPM Provenance
- `--provenance`フラグで公開
- 署名付きビルド証明書を生成
- サプライチェーンの透明性を確保

### 🛡️ 推奨する追加設定

#### GitHubリポジトリ設定

1. **ブランチ保護ルール** (`main`/`master`)
```
Settings → Branches → Add rule
- Require pull request reviews before merging
- Require status checks to pass
- Require signed commits (推奨)
- Do not allow bypassing the above settings
```

2. **タグ保護ルール**
```
Settings → Tags → Add rule
- Tag name pattern: v*
- Require signed commits
- 管理者のみタグ作成可能に設定
```

3. **Environment Protection** (`npm-publish`)
```
Settings → Environments → npm-publish
- Required reviewers: 信頼できる管理者を追加
- Wait timer: 5分(誤操作防止)
- Deployment branches: タグのみ許可
```

4. **Workflow保護**
```
Settings → Actions → General
- Require approval for all outside collaborators
- Fork pull request workflows: Require approval for first-time contributors
```

#### NPM設定

1. **2要素認証 (2FA) を有効化**
```bash
npm profile enable-2fa auth-and-writes
```

2. **NPM Token スコープを限定**
- Automation token (推奨)
- 公開のみ許可(読み取り・削除権限なし)
- トークンの定期更新

3. **パッケージ設定**
```bash
# npmウェブサイトで設定
- Require 2FA for package publishing
- Enable package provenance
```

### 🚨 セキュリティインシデント対応

#### NPM Tokenが漏洩した場合

1. **即座にトークンを無効化**
```bash
# npmウェブサイト → Access Tokens → Revoke
```

2. **GitHub Secretsを更新**
```
Settings → Secrets and variables → Actions → NPM_TOKEN
```

3. **最近のリリースを確認**
```bash
npm view react-github-ribbons versions --json
```

4. **不正なバージョンがあれば削除**
```bash
npm unpublish react-github-ribbons@x.x.x
```

#### 不審なタグが作成された場合

1. **タグを削除**
```bash
git tag -d v1.2.3
git push --delete origin v1.2.3
```

2. **GitHub Actionsログを確認**
```
Actions → Publish to npm → 該当ワークフローの確認
```

3. **環境保護で承認前なら拒否**

### 📋 リリースチェックリスト

リリース担当者は以下を確認してください:

- [ ] `package.json`のバージョンが正しい
- [ ] `CHANGELOG.md`が更新されている
- [ ] すべてのテストが通過
- [ ] `npm audit`で高リスクの脆弱性がない
- [ ] タグ名がセマンティックバージョニングに準拠
- [ ] コミットが署名されている(推奨)
- [ ] 信頼できるブランチからのリリース

### 🔗 参考資料

- [npm Provenance](https://docs.npmjs.com/generating-provenance-statements)
- [GitHub Actions Security](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)
- [Supply Chain Security Best Practices](https://slsa.dev/)

### 報告

セキュリティ上の懸念や脆弱性を発見した場合は、公開のIssueではなく、
リポジトリ管理者に直接連絡してください。
Loading
Loading