Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM mcr.microsoft.com/devcontainers/base:2.0-ubuntu-24.04

# Build arguments
ARG CLAUDE_CODE_OAUTH_TOKEN

Check warning on line 4 in .devcontainer/Dockerfile

View workflow job for this annotation

GitHub Actions / Generate SBOM

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "CLAUDE_CODE_OAUTH_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 4 in .devcontainer/Dockerfile

View workflow job for this annotation

GitHub Actions / Trivy Container Scan

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "CLAUDE_CODE_OAUTH_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG ANTHROPIC_API_KEY

Check warning on line 5 in .devcontainer/Dockerfile

View workflow job for this annotation

GitHub Actions / Generate SBOM

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "ANTHROPIC_API_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 5 in .devcontainer/Dockerfile

View workflow job for this annotation

GitHub Actions / Trivy Container Scan

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "ANTHROPIC_API_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG IMAGE_VERSION="dev"

# OCI Image Labels for version tracking
Expand Down Expand Up @@ -66,7 +66,7 @@
&& rm node-${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs

RUN npm install -g pnpm
RUN npm install -g pnpm@10.30.3

USER vscode
ENV SHELL=/bin/bash
Expand Down
16 changes: 16 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# pnpm security settings
# Strict peer dependency resolution - fail on conflicts
strict-peer-dependencies=true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Move pnpm-only keys out of shared .npmrc

The new project-level .npmrc adds pnpm-specific options (for example strict-peer-dependencies, auto-install-peers, shamefully-hoist, and verify-store-integrity) that npm does not support, so every npm invocation now emits Unknown project config ... warnings; this affects this repo immediately because CI/workflows run npm commands, and npm already warns these unknown keys may stop working in a future major release. Keeping pnpm-only settings in the shared config introduces noisy logs now and a forward-compatibility risk for the npm-based pipeline.

Useful? React with 👍 / 👎.


# Auto-install missing peer dependencies
auto-install-peers=true

# Run security audit on install
audit=true
audit-level=moderate

# Prevent phantom dependencies (packages hoisting to root node_modules)
shamefully-hoist=false

# Use content-addressable storage (pnpm default - integrity verification)
verify-store-integrity=true
22 changes: 22 additions & 0 deletions docs/setup/npm-library-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,28 @@ pnpm exec lint-staged
- **ベースイメージ**: `ghcr.io/keito4/config-base:latest`
- **冗長 Features の削除**: ベースイメージに含まれるもの(node, gh 等)は更新後に削除を検討

## pnpm セキュリティ設定(supply chain attack 対策)

pnpm を使用する場合は以下を必ず設定する。

**`pnpm-workspace.yaml`**:

```yaml
# 公開から 2 日未満のパッケージをインストール禁止(pnpm v10.16.0+)
minimumReleaseAge: 2880
```

**`.npmrc`**:

```ini
strict-peer-dependencies=true
auto-install-peers=true
audit=true
audit-level=moderate
shamefully-hoist=false
verify-store-integrity=true
```

## 関連ドキュメント

| ドキュメント | 説明 |
Expand Down
22 changes: 22 additions & 0 deletions docs/setup/spa-react-vite.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,28 @@ module.exports = {

- **ベースイメージ**: `ghcr.io/keito4/config-base:latest`

## pnpm セキュリティ設定(supply chain attack 対策)

pnpm を使用する場合は以下を必ず設定する。

**`pnpm-workspace.yaml`**:

```yaml
# 公開から 2 日未満のパッケージをインストール禁止(pnpm v10.16.0+)
minimumReleaseAge: 2880
```

**`.npmrc`**:

```ini
strict-peer-dependencies=true
auto-install-peers=true
audit=true
audit-level=moderate
shamefully-hoist=false
verify-store-integrity=true
```

## 関連ドキュメント

| ドキュメント | 説明 |
Expand Down
38 changes: 38 additions & 0 deletions docs/setup/web-app-nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,44 @@ export default function RootLayout({ children }: { children: React.ReactNode })
- 例外・エラーは Sentry に `captureException` してアラートを受け取る
- `console.log` の本番利用は禁止 → Biome の `noConsole` ルールで CI がブロック

## pnpm セキュリティ設定(supply chain attack 対策)

pnpm v10.16.0+ のネイティブ機能で、公開直後の悪意あるパッケージのインストールを防ぐ。

### pnpm-workspace.yaml

プロジェクトルートに配置する。**pnpm を使用するすべてのプロジェクトで必須設定**。

```yaml
# supply chain attack 対策: 公開から 2 日未満のパッケージをインストール禁止
# pnpm v10.16.0+ でサポート(単位: 分)
minimumReleaseAge: 2880

# 信頼できるパッケージを除外する場合(例: 公式パッケージで更新頻度が高いもの)
minimumReleaseAgeExclude: []
```

> **動作**: `pnpm add` や `pnpm update` で依存解決する際に適用。
> `pnpm-lock.yaml` が存在する `pnpm install` では環境再現性優先のためスキップされる。

### .npmrc(pnpm セキュリティ強化)

```ini
# Strict peer dependency resolution
strict-peer-dependencies=true
auto-install-peers=true

# インストール時に脆弱性チェック
audit=true
audit-level=moderate

# Phantom dependencies の排除
shamefully-hoist=false

# コンテンツハッシュで改ざん検知
verify-store-integrity=true
```

## 関連ドキュメント

| ドキュメント | 説明 |
Expand Down
10 changes: 10 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# pnpm workspace configuration
# https://pnpm.io/pnpm-workspace_yaml

# supply chain attack 対策: 公開から 2 日未満のパッケージをインストール禁止
# pnpm v10.16.0+ でサポート
# 単位: 分(2880 = 2 days)
minimumReleaseAge: 2880
Comment on lines +5 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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# First, understand the repository structure
echo "=== Repository root files ==="
ls -la | head -20

echo
echo "=== Root package.json check ==="
if [ -f package.json ]; then
  cat package.json | head -30
else
  echo "No root package.json found"
fi

echo
echo "=== pnpm-workspace.yaml content ==="
if [ -f pnpm-workspace.yaml ]; then
  cat pnpm-workspace.yaml
else
  echo "No pnpm-workspace.yaml found"
fi

Repository: keito4/config

Length of output: 2727


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== packageManager field in root package.json ==="
if [ -f package.json ]; then
  jq -r '.packageManager // "NOT SET"' package.json
else
  echo "Root package.json not found"
fi

echo
echo "=== CI/workflow files referencing pnpm ==="
fd -HI '\.(ya?ml|json)$' -path '*/.github/*' -o -path '*/\.gitlab-ci\.yml' | while read f; do
  if rg -l 'pnpm|corepack|packageManager' "$f" 2>/dev/null; then
    echo "Found in: $f"
  fi
done

echo
echo "=== .npmrc or .pnpmrc files ==="
fd -HI '^\.(npmrc|pnpmrc)$'

echo
echo "=== All package.json files with packageManager field ==="
fd -HI '^package\.json$' -x sh -c '
  pkg_mgr=$(jq -r ".packageManager // \"<missing>\"" "{}" 2>/dev/null || echo "error")
  if [ "$pkg_mgr" != "<missing>" ] && [ "$pkg_mgr" != "error" ]; then
    echo "{}": $pkg_mgr
  fi
'

Repository: keito4/config

Length of output: 344


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== CI workflow files ==="
find .github/workflows -type f -name '*.yml' -o -name '*.yaml' 2>/dev/null | head -10

echo
echo "=== Content of CI workflows (checking for pnpm setup) ==="
find .github/workflows -type f \( -name '*.yml' -o -name '*.yaml' \) -exec sh -c '
  echo "--- File: {} ---"
  grep -n -i "pnpm\|corepack\|packageManager\|setup-node" "{}" || echo "No pnpm/corepack references found"
' \;

echo
echo "=== .npmrc and .pnpmrc files ==="
find . -maxdepth 3 -type f \( -name '.npmrc' -o -name '.pnpmrc' \) 2>/dev/null || echo "None found"

echo
echo "=== Checking devcontainer configuration ==="
if [ -d .devcontainer ]; then
  find .devcontainer -type f \( -name '*.json' -o -name 'Dockerfile' -o -name 'devcontainer.json' \) -exec sh -c '
    echo "--- File: {} ---"
    head -50 "{}"
  ' \;
fi

Repository: keito4/config

Length of output: 14236


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== All package.json files in the repo ==="
find . -name package.json -type f | head -20

echo
echo "=== Check which ones have packageManager field ==="
find . -name package.json -type f -exec sh -c '
  result=$(jq -r ".packageManager // \"<missing>\"" "{}" 2>/dev/null || echo "parse_error")
  if [ "$result" != "<missing>" ] && [ "$result" != "parse_error" ]; then
    echo "{}: $result"
  fi
' \;

Repository: keito4/config

Length of output: 166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Content of .npmrc ==="
cat -n .npmrc

echo
echo "=== Check for setup-node configuration in CI workflows ==="
grep -A5 "setup-node" .github/workflows/ci.yml | head -30

echo
echo "=== DevContainer node feature configuration ==="
echo "Local DevContainer:"
jq '.features | keys[] as $key | select($key | contains("node")) | {($key): .[$key]}' .devcontainer/devcontainer.json

echo
echo "Codespaces DevContainer:"
jq '.features | keys[] as $key | select($key | contains("node")) | {($key): .[$key]}' .devcontainer/codespaces/devcontainer.json

Repository: keito4/config

Length of output: 1351


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check for .node-version file ==="
if [ -f .node-version ]; then
  cat -n .node-version
else
  echo "No .node-version file found"
fi

echo
echo "=== Check pnpm-lock.yaml to understand pnpm version used ==="
if [ -f pnpm-lock.yaml ]; then
  head -5 pnpm-lock.yaml | grep -i "lockfile\|pnpm"
  echo "..."
else
  echo "No pnpm-lock.yaml found"
fi

echo
echo "=== Check for pnpm version in CI install steps ==="
grep -B5 -A5 "pnpm install\|npm install" .github/workflows/ci.yml | head -40

echo
echo "=== Check Dockerfile for pnpm installation ==="
grep -n -i "pnpm" .devcontainer/Dockerfile

Repository: keito4/config

Length of output: 246


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for pnpm installation in entire repo ==="
grep -r "pnpm" .devcontainer/Dockerfile .github/workflows/ --include="*.yml" --include="*.yaml" --include="*.json" | grep -v "pnpmVersion\|pnpm-workspace" | head -20

echo
echo "=== Check if npm scripts reference pnpm ==="
jq '.scripts' package.json

echo
echo "=== Verify current node setup in ci.yml - full install section ==="
sed -n '/Install dependencies/,/^      - /p' .github/workflows/ci.yml | head -20

echo
echo "=== Check root .npmrc comments for pnpm reference ==="
head -20 .npmrc

Repository: keito4/config

Length of output: 2018


Switch CI from npm ci to pnpm install and pin pnpm version globally.

The minimumReleaseAge control in pnpm-workspace.yaml (line 7) is currently non-functional because CI workflows use npm ci instead of pnpm install. The .npmrc file has pnpm-specific security settings, but npm ignores both the workspace configuration and supply chain controls.

To enforce the 2-day release age gate:

  1. Add packageManager: "pnpm@10.30.3" (or later) to root package.json
  2. Change all CI workflows from npm ci to pnpm install --frozen-lockfile
  3. Update setup-node cache from 'npm' to 'pnpm'
  4. Pin DevContainer Codespaces pnpmVersion from "latest" to a specific version

Additionally, generate a pnpm-lock.yaml file by running pnpm install locally and committing it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pnpm-workspace.yaml` around lines 5 - 7, The CI is using npm so pnpm
workspace controls like minimumReleaseAge in pnpm-workspace.yaml are ignored;
update the repo to enforce pnpm by adding packageManager: "pnpm@10.30.3" (or
later) to root package.json, change all CI workflow steps that run npm ci to run
pnpm install --frozen-lockfile, update any setup-node cache entries that use
'npm' to use 'pnpm', and pin DevContainer/Codespaces pnpmVersion from "latest"
to the same specific version; finally run pnpm install locally to generate and
commit pnpm-lock.yaml so the pnpm gate (minimumReleaseAge) and pnpm security
settings in .npmrc take effect.


# 除外パッケージ(公式・信頼できるリリースサイクルが速いもの)
minimumReleaseAgeExclude: []