github-auth-shiyoka
Agentic Skill — デフォルトでは
disable-model-invocation: trueのため、/github-auth-shiyokaと明示的に入力して起動します。
キーワード(「GitHub認証」「PAT設定」「git clone で認証エラー」など)を会話中に検出して 自動起動させたい場合 は、このファイルの frontmatter を以下のように変更してください:disable-model-invocation: false
git credential helper を設定し、以降の git clone / git push / git pull で
GitHub 認証を自動的に行えるようにする。
このスキルは以下の方式を扱う。リポジトリ単位の権限制御を重視した優先順位:
| 優先順位 | 方式 | 権限スコープ | 特徴 |
|---|---|---|---|
| 1(最高) | Fine-grained PAT + 1Password CLI | リポジトリ単位・操作種別 | 最小権限・PAT を 1Password で管理 |
| 2 | Deploy Key | リポジトリ単位 | SSH・特定リポジトリ専用鍵・CI/CD 向き |
| 3 | SSH + 1Password SSH Agent | アカウント全体 | PAT 不要・秘密鍵ディスク非保存 |
| 4 | GCM(Git Credential Manager) | アカウント全体 | OAuth 使用・OS キーチェーンに保存 |
セキュリティ監査モード(スキル起動時に常に最初に実行)
スキル起動直後にまずユーザーへの確認を行い、その後セキュリティ監査と設定手順に進む。
0. 対象ユーザー・リポジトリを確認する(最初に必ず実行)
まずカレントディレクトリに .git があるかを確認し、あれば remote URL から自動検出する:
# .git の有無を確認
if [ -d .git ] || git rev-parse --git-dir >/dev/null 2>&1; then
echo "✅ git リポジトリを検出"
# remote URL を取得
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "")
if [ -n "$REMOTE_URL" ]; then
echo "remote URL: $REMOTE_URL"
# HTTPS / SSH どちらの形式でも user と repo を抽出
if echo "$REMOTE_URL" | grep -q "github.com"; then
# HTTPS: https://github.com/<user>/<repo>.git
# SSH: git@github.com:<user>/<repo>.git
GITHUB_PATH=$(echo "$REMOTE_URL" \
| sed -E 's|https://github.com/||; s|git@github.com:||; s|\.git$||')
TARGET_USER=$(echo "$GITHUB_PATH" | cut -d'/' -f1)
TARGET_REPO=$(echo "$GITHUB_PATH" | cut -d'/' -f2)
echo "検出: ユーザー/組織 = $TARGET_USER, リポジトリ = $TARGET_REPO"
else
echo "ℹ️ GitHub 以外のリモートのため手動入力が必要"
fi
else
echo "ℹ️ remote origin が未設定"
fi
else
echo "ℹ️ git リポジトリが見つかりません"
fi
検出結果をもとに、以下をユーザーに確認する:
.gitあり・remote あり → 検出したTARGET_USER/TARGET_REPOを提示して「この内容で合っていますか?」と確認する.gitなし・remote なし → 以下を手動で確認する:
以下を教えてください:
1. GitHub ユーザー名(または組織名)
例:myuser / my-org
2. アクセスしたいリポジトリ名
例:my-repo(複数ある場合はカンマ区切りで)
加えて、どちらの場合も以下を確認する:
3. 必要な操作
- clone / pull のみ(Read-only)
- push も必要(Read and write)
4. 現在の状況
- 初めて設定する
- 認証エラーが出ている(エラーメッセージを貼ってください)
- 既存設定のセキュリティ確認をしたい
確認が取れたら TARGET_USER・TARGET_REPO・NEED_WRITE として以降の手順に引き継ぐ。
1. 現在の GitHub 認証状態を診断
# GitHub CLI による認証状態確認(グローバル設定の参照のみ・変更しない)
gh auth status 2>&1 || echo "gh コマンドが見つからないか未認証"
# credential helper の確認(グローバル・ローカル両方)
echo "=== credential helper ==="
git config --global credential.helper 2>/dev/null || echo "(グローバル未設定)"
git config --local credential.helper 2>/dev/null || echo "(ローカル未設定)"
git config --global credential.https://github.com.helper 2>/dev/null || echo "(github.com 専用未設定)"
# OS 判定
if grep -qi microsoft /proc/version 2>/dev/null; then
OS_TYPE="WSL2"
elif [[ "$(uname)" == "Darwin" ]]; then
OS_TYPE="macOS"
else
OS_TYPE="Linux"
fi
echo "OS: $OS_TYPE"
注意: ここで確認するのは現在の設定状態のみ。Step 0 で確認した
TARGET_USER/TARGET_REPOに対してこれらの設定が適切かどうかを次のステップで判断する。
2. PAT 種別を確認(Fine-grained か Classic か)
gh auth status の出力または以下のコマンドでトークン種別を確認する:
# 現在のトークンを gh から取得して種別判定
gh auth token 2>/dev/null | head -c 20 || echo "(トークン取得不可)"
# Fine-grained PAT は "github_pat_" で始まる
# Classic PAT は "ghp_" で始まる
# OAuth トークンは "gho_" で始まる
判定基準:
github_pat_→ Fine-grained PAT(最推奨)ghp_→ Classic PAT(過剰権限の可能性あり → Fine-grained PAT への移行を推奨)gho_→ OAuth / GCM(アカウント全体アクセス)- 取得不可 → 未認証またはトークン管理外
3. 有効期限を確認(期限切れ・30日以内の警告)
# 1Password に保存された PAT の有効期限を取得(op がある場合)
if command -v op >/dev/null 2>&1; then
echo "=== 1Password: GitHub 関連アイテムの有効期限 ==="
op item list --categories "API Credential" --format=json 2>/dev/null \
| python3 -c "
import json, sys, datetime
items = json.load(sys.stdin)
today = datetime.date.today()
warn_days = 30
for item in items:
title = item.get('title', '')
if 'github' in title.lower():
for field in item.get('fields', []):
if field.get('id') == 'expires' or field.get('label', '').lower() == 'expires':
val = field.get('value', '')
if val:
try:
exp = datetime.date.fromisoformat(val)
delta = (exp - today).days
if delta < 0:
print(f'🔴 期限切れ: {title} (期限: {val})')
elif delta <= warn_days:
print(f'⚠️ {delta}日後に期限切れ: {title} (期限: {val})')
else:
print(f'✅ 有効期限OK: {title} (期限: {val}, 残り{delta}日)')
except:
print(f'ℹ️ {title}: 期限値={val}')
" 2>/dev/null || echo "(有効期限の自動取得失敗 - 手動で確認してください)"
fi
# gh CLI でトークン有効期限確認
gh auth status 2>&1 | grep -i "expir\|token expir\|期限" || true
4. 権限スコープを精査(過剰権限の検出)
# gh CLI でスコープ確認
gh auth status 2>&1 | grep -i "scope\|権限" || true
# API で直接スコープ確認(Classic PAT / OAuth の場合)
SCOPES=$(curl -sI -H "Authorization: token $(gh auth token 2>/dev/null)" \
https://api.github.com/user 2>/dev/null \
| grep -i "^x-oauth-scopes:" | cut -d: -f2- | tr -d ' \r')
if [ -n "$SCOPES" ]; then
echo "現在のスコープ: $SCOPES"
else
echo "(スコープ取得不可 - Fine-grained PAT またはトークン未設定の可能性)"
fi
過剰権限の判定基準:
repo(フルアクセス)が設定されていて、Read のみで十分な場合 → Fine-grained PAT への移行推奨admin:org・delete_repo・workflowが不要なのに含まれている → 即時削除推奨- Classic PAT でスコープが広い → Fine-grained PAT に移行して最小権限化
5. 1Password Vault 連携状況を確認
# op CLI の有無とサインイン状態
if command -v op >/dev/null 2>&1; then
echo "op version: $(op --version 2>/dev/null)"
op account list 2>/dev/null | head -5 || echo "(未サインイン)"
echo "=== GitHub 関連アイテム ==="
op item list --categories "API Credential" --format=json 2>/dev/null \
| python3 -c "
import json, sys
items = json.load(sys.stdin)
found = [i['title'] for i in items if 'github' in i.get('title','').lower()]
print('\n'.join(found) if found else '(GitHub関連アイテムなし)')
" 2>/dev/null || echo "(取得失敗)"
else
echo "op: not found(1Password CLI 未インストール)"
fi
# credential helper が op を使っているか確認
# ローカル設定を優先確認(PAT 認証はプロジェクトローカルが正)
( git config --local credential.https://github.com.helper 2>/dev/null || \
git config --global credential.https://github.com.helper 2>/dev/null ) \
| grep -q "op read" \
&& echo "✅ credential helper: 1Password CLI 連携済み" \
|| echo "ℹ️ credential helper: 1Password CLI 未連携"
6. 総合セキュリティレポートを出力
上記 1〜5 のチェック結果をもとに、以下の形式でセキュリティレポートを出力する:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔐 GitHub 認証 セキュリティレポート
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【対象】
- ユーザー / 組織: <TARGET_USER>
- リポジトリ: <TARGET_REPO>
- 必要な操作: <Read-only / Read and write>
【現在の認証状態】
- 認証方式: <Fine-grained PAT / Classic PAT / OAuth / 未認証>
- トークン種別: <github_pat_ / ghp_ / gho_ / なし>
- 1Password 連携: <済 / 未連携>
【有効期限チェック】
- <✅ 有効期限OK / ⚠️ XX日後に期限切れ / 🔴 期限切れ>
【権限スコープチェック】
- <✅ 最小権限 / ⚠️ 過剰権限あり(詳細) / ℹ️ スコープ不明>
【問題点と即時対応策】
• <問題点があれば箇点で記載。なければ「問題なし」>
• <例: Classic PAT を使用中 → Fine-grained PAT への移行を推奨>
• <例: トークンが30日以内に期限切れ → Regenerate 手順を案内>
• <例: 1Password 未連携 → op.env 設定を推奨>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
7. 必要ならトークン回転手順を提案
以下の場合に、対応する回転手順を案内する:
PAT が期限切れ・30日以内の場合:
【トークン回転手順】
1. https://github.com/settings/personal-access-tokens を開く
2. 対象 PAT の "Regenerate token" をクリック
3. 新しいトークンをコピー
4. 1Password を更新:
op item edit "<アイテム名>" --vault="<Vault名>" "credential[concealed]=<新トークン>"
5. credential helper の再設定は不要(参照パスは変わらない)
Classic PAT → Fine-grained PAT へ移行する場合:
【移行手順】
1. Step 1 の手順で Fine-grained PAT を新規作成
2. 1Password に保存
3. op.env の参照パスを更新
4. 旧 Classic PAT を GitHub から削除:
https://github.com/settings/tokens
セキュリティ監査完了後、続けて以下の 事前チェック と 設定手順 を実行する。
事前チェック(スキル起動時に必ず実行)
重要:
~/.ssh/configはセキュリティポリシーにより Claude が直接読み取れない。 以下の手順で Claude が実行できるチェックとユーザーに依頼するチェックを分けて行う。
1. Claude が直接実行するチェック
以下をまとめて実行し、結果を解釈する:
# OS 判定
if grep -qi microsoft /proc/version 2>/dev/null; then
OS_TYPE="WSL2"
elif [[ "$(uname)" == "Darwin" ]]; then
OS_TYPE="macOS"
else
OS_TY