Docker Hubのアクセストークンが漏洩すると、単なる無料枠の消費ではなく、コンテナイメージへのマルウェア混入というサプライチェーン攻撃に直結する。本記事では漏洩時に起きる事故5パターンと、トークン管理のベストプラクティスを整理する。
事故パターン1: 公式イメージタグの上書き
攻撃者が docker push できる状態になると、タグを上書きして悪意あるイメージを配布できる。
mycompany/api:latest → 上書き → 攻撃者の改変イメージ
自動デプロイで latest を参照していると、次のデプロイで本番にマルウェアが入る。
防御策: Dockerコンテンツ署名 (Cosign)
cosign generate-key-pair
cosign sign --key cosign.key mycompany/api:v1.2.3
検証側はKubernetesのAdmission Controllerで署名を強制する。
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
name: mycompany-images
spec:
images:
- glob: "mycompany/*"
authorities:
- key:
data: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
事故パターン2: Tag Mutabilityの悪用
Docker Hubはデフォルトでタグの上書きが可能である。Immutableタグ運用に切り替える。
- 本番向けは常にバージョンタグ (
v1.2.3) -
latestを本番で参照しない - Pull時は必ずダイジェスト指定 (
@sha256:...)
# Kubernetesマニフェスト
image: mycompany/api@sha256:abc123def456...
ダイジェスト指定であれば、タグが上書きされても既存Podは影響を受けない。
事故パターン3: プライベートイメージの吸い出し
Read権限のトークンが漏れた場合、全イメージがpull可能になる。独自のモデルファイル、設定ファイル、API Keyなどが入っていると致命的である。
# 攻撃者視点の操作例
docker login -u stolen-user -p $STOLEN_TOKEN
docker pull mycompany/internal-tool:latest
docker save mycompany/internal-tool:latest -o loot.tar
防御策: イメージに秘密を含めない
.dockerignore を活用し、Multi-stage buildで最終イメージから依存を剥がす。
# .env や credentials.json を除外
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm ci --only=production && npm run build
FROM gcr.io/distroless/nodejs20
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["dist/index.js"]
事故パターン4: Rate Limit詐取
Docker Hubの無料枠では、認証あり200 pull/6h、認証なし100 pull/6hの制限がある。トークンが漏れた場合、他者が自社の枠を消費する事故が起きる。
防御策: Pull-through Cacheの導入
ECRやGAR、Harborなどのプライベートレジストリでキャッシュする。
aws ecr create-pull-through-cache-rule \
--ecr-repository-prefix docker-hub \
--upstream-registry-url registry-1.docker.io \
--credential-arn arn:aws:secretsmanager:...:secret:docker-hub-ro
以降 docker-hub/library/nginx:1.25 のように参照でき、Docker Hubへの直接Pullを減らせる。
事故パターン5: CI/CDのアクセストークン流出
GitHub ActionsのSecretsに保管していても、悪意あるPRでSecretsを流出させる手法が知られている。
防御策1: OIDCでの短命トークン発行
GitHub Actions → AWS IAMのOIDC連携はよく知られているが、Docker Hubも2025年以降でOIDC互換の署名フローに対応した。IaCで固定トークンを長期保有しない構造が推奨される。
防御策2: Permissionsを厳しく絞る
# .github/workflows/build.yml
permissions:
contents: read
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- run: docker build -t mycompany/api:${{ github.sha }} .
pull_request トリガーでは secrets を渡さないように、Environmentの required reviewers を設定する。
防御策3: トークンスコープを分離
Docker Hubのアクセストークンはスコープ指定が可能である。
- CI用: Public Repo Read + Write (
public_repo) - デプロイ用: 特定リポジトリのみRead
読み取り専用トークンと書き込みトークンを分け、漏洩時の影響範囲を限定する。
漏洩時の初動
# 1. トークン失効
curl -X DELETE https://hub.docker.com/v2/access-tokens/UUID \
-H "Authorization: Bearer $JWT"
# 2. 全タグの監査
for tag in $(curl -s "https://hub.docker.com/v2/repositories/mycompany/api/tags/" | jq -r .results[].name); do
echo "=== $tag ==="
curl -s "https://hub.docker.com/v2/repositories/mycompany/api/tags/$tag/" | \
jq '{last_updated, digest: .images[0].digest}'
done
# 3. 直近更新のあるタグの差分確認
# dive や docker image inspect で手動検証
まとめ
Docker Hubトークン漏洩の被害は「無料枠消費」にとどまらず、サプライチェーン攻撃へ拡大する。署名、Immutableタグ、Pull-through Cache、OIDC化、スコープ分離の5点を平時から整えることで、漏洩時の被害を大きく抑えられる。