[{"data":1,"prerenderedAt":1719},["ShallowReactive",2],{"blog-ja-cicd-pipeline-security-devsecops":3,"blog-ja-cicd-pipeline-security-devsecops-alt":147},{"id":4,"title":5,"author":6,"body":7,"date":1704,"description":1705,"extension":1706,"image":57,"locale":1707,"meta":1708,"navigation":147,"path":1709,"seo":1710,"stem":1711,"tags":1712,"__hash__":1718},"blog\u002Fblog\u002Fja\u002Fcicd-pipeline-security-devsecops.md","ci-cd パイプラインのセキュリティ: DevSecOps 実践ガイド","Kubo Team",{"type":8,"value":9,"toc":1673},"minimark",[10,28,33,47,51,200,209,213,423,431,434,437,441,444,478,482,485,570,574,577,599,602,684,703,707,760,766,770,779,783,839,843,867,941,945,1064,1072,1076,1079,1083,1213,1217,1410,1424,1427,1439,1442,1445,1448,1526,1534,1537,1540,1573,1579,1582,1585,1588,1635,1646,1650,1653,1669],[11,12,13,14,21,22,27],"p",{},"ci-cd パイプラインは、コードを本番環境に届ける最短ルートであると同時に、攻撃者にとっても最も魅力的なターゲットです。2025 年初頭の GhostAction 攻撃では、広く使用されていた GitHub Action が侵害され、何千ものリポジトリからシークレットが流出しました。",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Fwww.qualys.com\u002Ffundamentals\u002Fci-cd-security-best-practices",[19],"nofollow","Qualys の調査","によると、DevSecOps を実装している組織は 68% に達しましたが、技術的複雑さ（41%）、リソース制約（35%）、文化的抵抗（38%）が依然として課題です。",[15,23,26],{"href":24,"rel":25},"https:\u002F\u002Fkubo.hexabase.io\u002F",[19],"Kubo"," はセキュリティを組み込んだ ci-cd 基盤を提供しており、本記事のプラクティスを標準で適用できます。",[29,30,32],"h2",{"id":31},"shift-left-セキュリティを開発の最初から組み込む","Shift-Left: セキュリティを開発の最初から組み込む",[11,34,35,36,40,41,46],{},"DevSecOps の基本原則は ",[37,38,39],"strong",{},"「Shift-Left」","、つまりセキュリティチェックをパイプラインの可能な限り早い段階に移動することです。",[15,42,45],{"href":43,"rel":44},"https:\u002F\u002Fwww.practical-devsecops.com\u002Fdevsecops-best-practices\u002F",[19],"Practical DevSecOps"," によると、セキュリティの問題は発見が遅いほど修正コストが指数関数的に増大します。",[48,49,50],"h3",{"id":50},"開発環境でのセキュリティ",[52,53,58],"pre",{"className":54,"code":55,"language":56,"meta":57,"style":57},"language-yaml shiki shiki-themes tokyo-night","# pre-commit フックの設定例\nrepos:\n  - repo: https:--github.com-gitleaks-gitleaks\n    rev: v8.18.0\n    hooks:\n      - id: gitleaks\n        name: Detect hardcoded secrets\n\n  - repo: https:--github.com-hadolint-hadolint\n    rev: v2.12.0\n    hooks:\n      - id: hadolint-docker\n        name: Lint Dockerfile\n","yaml","",[59,60,61,70,81,98,109,117,131,142,149,161,171,178,190],"code",{"__ignoreMap":57},[62,63,66],"span",{"class":64,"line":65},"line",1,[62,67,69],{"class":68},"sbD-w","# pre-commit フックの設定例\n",[62,71,73,77],{"class":64,"line":72},2,[62,74,76],{"class":75},"s0U2E","repos",[62,78,80],{"class":79},"sAklC",":\n",[62,82,84,88,91,94],{"class":64,"line":83},3,[62,85,87],{"class":86},"sgJMe","  -",[62,89,90],{"class":75}," repo",[62,92,93],{"class":79},":",[62,95,97],{"class":96},"sPY7s"," https:--github.com-gitleaks-gitleaks\n",[62,99,101,104,106],{"class":64,"line":100},4,[62,102,103],{"class":75},"    rev",[62,105,93],{"class":79},[62,107,108],{"class":96}," v8.18.0\n",[62,110,112,115],{"class":64,"line":111},5,[62,113,114],{"class":75},"    hooks",[62,116,80],{"class":79},[62,118,120,123,126,128],{"class":64,"line":119},6,[62,121,122],{"class":86},"      -",[62,124,125],{"class":75}," id",[62,127,93],{"class":79},[62,129,130],{"class":96}," gitleaks\n",[62,132,134,137,139],{"class":64,"line":133},7,[62,135,136],{"class":75},"        name",[62,138,93],{"class":79},[62,140,141],{"class":96}," Detect hardcoded secrets\n",[62,143,145],{"class":64,"line":144},8,[62,146,148],{"emptyLinePlaceholder":147},true,"\n",[62,150,152,154,156,158],{"class":64,"line":151},9,[62,153,87],{"class":86},[62,155,90],{"class":75},[62,157,93],{"class":79},[62,159,160],{"class":96}," https:--github.com-hadolint-hadolint\n",[62,162,164,166,168],{"class":64,"line":163},10,[62,165,103],{"class":75},[62,167,93],{"class":79},[62,169,170],{"class":96}," v2.12.0\n",[62,172,174,176],{"class":64,"line":173},11,[62,175,114],{"class":75},[62,177,80],{"class":79},[62,179,181,183,185,187],{"class":64,"line":180},12,[62,182,122],{"class":86},[62,184,125],{"class":75},[62,186,93],{"class":79},[62,188,189],{"class":96}," hadolint-docker\n",[62,191,193,195,197],{"class":64,"line":192},13,[62,194,136],{"class":75},[62,196,93],{"class":79},[62,198,199],{"class":96}," Lint Dockerfile\n",[11,201,202,203,208],{},"開発者の IDE やコミット前の段階で、シークレットの誤コミットや Dockerfile のベストプラクティス違反を検出します。",[15,204,207],{"href":205,"rel":206},"https:\u002F\u002Fblog.gitguardian.com\u002Fsupply-chain-security-sigstore-and-cosign-part-ii\u002F",[19],"GitGuardian"," などのツールは、リポジトリ全体のシークレットスキャンを自動化します。",[48,210,212],{"id":211},"ci-パイプラインの初期段階","CI パイプラインの初期段階",[52,214,216],{"className":54,"code":215,"language":56,"meta":57,"style":57},"# GitHub Actions での Shift-Left セキュリティ\nsecurity-checks:\n  runs-on: ubuntu-latest\n  steps:\n    - uses: actions-checkout@v4\n\n    - name: SAST - SonarQube Scan\n      uses: SonarSource\u002Fsonarqube-scan-action@master\n      env:\n        SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}\n        SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}\n\n    - name: Secrets Detection\n      uses: gitleaks\u002Fgitleaks-action@v2\n      env:\n        GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}\n\n    - name: Dependency Check\n      uses: dependency-check\u002FDependency-Check_Action@main\n      with:\n        path: '.'\n        format: 'SARIF'\n",[59,217,218,223,230,240,247,260,264,276,286,293,303,313,317,328,338,345,356,361,373,383,391,408],{"__ignoreMap":57},[62,219,220],{"class":64,"line":65},[62,221,222],{"class":68},"# GitHub Actions での Shift-Left セキュリティ\n",[62,224,225,228],{"class":64,"line":72},[62,226,227],{"class":75},"security-checks",[62,229,80],{"class":79},[62,231,232,235,237],{"class":64,"line":83},[62,233,234],{"class":75},"  runs-on",[62,236,93],{"class":79},[62,238,239],{"class":96}," ubuntu-latest\n",[62,241,242,245],{"class":64,"line":100},[62,243,244],{"class":75},"  steps",[62,246,80],{"class":79},[62,248,249,252,255,257],{"class":64,"line":111},[62,250,251],{"class":86},"    -",[62,253,254],{"class":75}," uses",[62,256,93],{"class":79},[62,258,259],{"class":96}," actions-checkout@v4\n",[62,261,262],{"class":64,"line":119},[62,263,148],{"emptyLinePlaceholder":147},[62,265,266,268,271,273],{"class":64,"line":133},[62,267,251],{"class":86},[62,269,270],{"class":75}," name",[62,272,93],{"class":79},[62,274,275],{"class":96}," SAST - SonarQube Scan\n",[62,277,278,281,283],{"class":64,"line":144},[62,279,280],{"class":75},"      uses",[62,282,93],{"class":79},[62,284,285],{"class":96}," SonarSource\u002Fsonarqube-scan-action@master\n",[62,287,288,291],{"class":64,"line":151},[62,289,290],{"class":75},"      env",[62,292,80],{"class":79},[62,294,295,298,300],{"class":64,"line":163},[62,296,297],{"class":75},"        SONAR_TOKEN",[62,299,93],{"class":79},[62,301,302],{"class":96}," ${{ secrets.SONAR_TOKEN }}\n",[62,304,305,308,310],{"class":64,"line":173},[62,306,307],{"class":75},"        SONAR_HOST_URL",[62,309,93],{"class":79},[62,311,312],{"class":96}," ${{ secrets.SONAR_HOST_URL }}\n",[62,314,315],{"class":64,"line":180},[62,316,148],{"emptyLinePlaceholder":147},[62,318,319,321,323,325],{"class":64,"line":192},[62,320,251],{"class":86},[62,322,270],{"class":75},[62,324,93],{"class":79},[62,326,327],{"class":96}," Secrets Detection\n",[62,329,331,333,335],{"class":64,"line":330},14,[62,332,280],{"class":75},[62,334,93],{"class":79},[62,336,337],{"class":96}," gitleaks\u002Fgitleaks-action@v2\n",[62,339,341,343],{"class":64,"line":340},15,[62,342,290],{"class":75},[62,344,80],{"class":79},[62,346,348,351,353],{"class":64,"line":347},16,[62,349,350],{"class":75},"        GITLEAKS_LICENSE",[62,352,93],{"class":79},[62,354,355],{"class":96}," ${{ secrets.GITLEAKS_LICENSE }}\n",[62,357,359],{"class":64,"line":358},17,[62,360,148],{"emptyLinePlaceholder":147},[62,362,364,366,368,370],{"class":64,"line":363},18,[62,365,251],{"class":86},[62,367,270],{"class":75},[62,369,93],{"class":79},[62,371,372],{"class":96}," Dependency Check\n",[62,374,376,378,380],{"class":64,"line":375},19,[62,377,280],{"class":75},[62,379,93],{"class":79},[62,381,382],{"class":96}," dependency-check\u002FDependency-Check_Action@main\n",[62,384,386,389],{"class":64,"line":385},20,[62,387,388],{"class":75},"      with",[62,390,80],{"class":79},[62,392,394,397,399,402,405],{"class":64,"line":393},21,[62,395,396],{"class":75},"        path",[62,398,93],{"class":79},[62,400,401],{"class":79}," '",[62,403,404],{"class":96},".",[62,406,407],{"class":79},"'\n",[62,409,411,414,416,418,421],{"class":64,"line":410},22,[62,412,413],{"class":75},"        format",[62,415,93],{"class":79},[62,417,401],{"class":79},[62,419,420],{"class":96},"SARIF",[62,422,407],{"class":79},[11,424,425,430],{},[15,426,429],{"href":427,"rel":428},"https:\u002F\u002Fwww.hexabase.com\u002Fproduct\u002Fcaptain-ai\u002F",[19],"Captain.AI"," は、セキュリティスキャン結果の分析と優先順位付けを AI で支援し、開発者がアクションすべき問題を明確にします。",[29,432,433],{"id":433},"自動セキュリティテストの多層防御",[11,435,436],{},"ci-cd パイプラインには複数のセキュリティテストレイヤーを組み込み、異なる脅威を異なる段階で検出します。",[48,438,440],{"id":439},"sast静的アプリケーションセキュリティテスト","SAST（静的アプリケーションセキュリティテスト）",[11,442,443],{},"ソースコードをコンパイル前に分析し、SQL インジェクション、XSS、バッファオーバーフローなどの脆弱性を検出します。",[445,446,447,458,468],"ul",{},[448,449,450,457],"li",{},[37,451,452],{},[15,453,456],{"href":454,"rel":455},"https:--www.sonarqube.org-",[19],"sonarqube",": 多言語対応、品質ゲート機能",[448,459,460,467],{},[37,461,462],{},[15,463,466],{"href":464,"rel":465},"https:\u002F\u002Fsemgrep.dev\u002F",[19],"Semgrep",": 軽量・高速、カスタムルール定義が容易",[448,469,470,477],{},[37,471,472],{},[15,473,476],{"href":474,"rel":475},"https:\u002F\u002Fcodeql.github.com\u002F",[19],"CodeQL",": GitHub ネイティブ、セマンティック分析",[48,479,481],{"id":480},"scaソフトウェア構成分析","SCA（ソフトウェア構成分析）",[11,483,484],{},"オープンソース依存関係の既知脆弱性を検出します。",[52,486,488],{"className":54,"code":487,"language":56,"meta":57,"style":57},"    - name: SCA Scan\n      uses: aquasecurity\u002Ftrivy-action@master\n      with:\n        scan-type: 'fs'\n        scan-ref: '.'\n        format: 'sarif'\n        severity: 'CRITICAL,HIGH'\n",[59,489,490,501,510,516,530,543,556],{"__ignoreMap":57},[62,491,492,494,496,498],{"class":64,"line":65},[62,493,251],{"class":86},[62,495,270],{"class":75},[62,497,93],{"class":79},[62,499,500],{"class":96}," SCA Scan\n",[62,502,503,505,507],{"class":64,"line":72},[62,504,280],{"class":75},[62,506,93],{"class":79},[62,508,509],{"class":96}," aquasecurity\u002Ftrivy-action@master\n",[62,511,512,514],{"class":64,"line":83},[62,513,388],{"class":75},[62,515,80],{"class":79},[62,517,518,521,523,525,528],{"class":64,"line":100},[62,519,520],{"class":75},"        scan-type",[62,522,93],{"class":79},[62,524,401],{"class":79},[62,526,527],{"class":96},"fs",[62,529,407],{"class":79},[62,531,532,535,537,539,541],{"class":64,"line":111},[62,533,534],{"class":75},"        scan-ref",[62,536,93],{"class":79},[62,538,401],{"class":79},[62,540,404],{"class":96},[62,542,407],{"class":79},[62,544,545,547,549,551,554],{"class":64,"line":119},[62,546,413],{"class":75},[62,548,93],{"class":79},[62,550,401],{"class":79},[62,552,553],{"class":96},"sarif",[62,555,407],{"class":79},[62,557,558,561,563,565,568],{"class":64,"line":133},[62,559,560],{"class":75},"        severity",[62,562,93],{"class":79},[62,564,401],{"class":79},[62,566,567],{"class":96},"CRITICAL,HIGH",[62,569,407],{"class":79},[48,571,573],{"id":572},"dast動的アプリケーションセキュリティテスト","DAST（動的アプリケーションセキュリティテスト）",[11,575,576],{},"実行中のアプリケーションに対してテストを実行し、認証バイパスやセッション管理の問題を検出します。",[445,578,579,589],{},[448,580,581,588],{},[37,582,583],{},[15,584,587],{"href":585,"rel":586},"https:--www.zaproxy.org-",[19],"owasp zap",": オープンソースの web アプリスキャナー",[448,590,591,598],{},[37,592,593],{},[15,594,597],{"href":595,"rel":596},"https:\u002F\u002Fgithub.com\u002Fprojectdiscovery\u002Fnuclei",[19],"Nuclei",": テンプレートベースの脆弱性スキャナー",[48,600,601],{"id":601},"コンテナスキャン",[52,603,605],{"className":54,"code":604,"language":56,"meta":57,"style":57},"    - name: Container Image Scan\n      uses: aquasecurity\u002Ftrivy-action@master\n      with:\n        image-ref: 'ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}'\n        format: 'sarif'\n        severity: 'CRITICAL,HIGH'\n        exit-code: '1'\n",[59,606,607,618,626,632,646,658,670],{"__ignoreMap":57},[62,608,609,611,613,615],{"class":64,"line":65},[62,610,251],{"class":86},[62,612,270],{"class":75},[62,614,93],{"class":79},[62,616,617],{"class":96}," Container Image Scan\n",[62,619,620,622,624],{"class":64,"line":72},[62,621,280],{"class":75},[62,623,93],{"class":79},[62,625,509],{"class":96},[62,627,628,630],{"class":64,"line":83},[62,629,388],{"class":75},[62,631,80],{"class":79},[62,633,634,637,639,641,644],{"class":64,"line":100},[62,635,636],{"class":75},"        image-ref",[62,638,93],{"class":79},[62,640,401],{"class":79},[62,642,643],{"class":96},"ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}",[62,645,407],{"class":79},[62,647,648,650,652,654,656],{"class":64,"line":111},[62,649,413],{"class":75},[62,651,93],{"class":79},[62,653,401],{"class":79},[62,655,553],{"class":96},[62,657,407],{"class":79},[62,659,660,662,664,666,668],{"class":64,"line":119},[62,661,560],{"class":75},[62,663,93],{"class":79},[62,665,401],{"class":79},[62,667,567],{"class":96},[62,669,407],{"class":79},[62,671,672,675,677,679,682],{"class":64,"line":133},[62,673,674],{"class":75},"        exit-code",[62,676,93],{"class":79},[62,678,401],{"class":79},[62,680,681],{"class":96},"1",[62,683,407],{"class":79},[11,685,686,691,692,691,697,702],{},[15,687,690],{"href":688,"rel":689},"https:\u002F\u002Ftrivy.dev\u002F",[19],"Trivy","、",[15,693,696],{"href":694,"rel":695},"https:\u002F\u002Fgithub.com\u002Fanchore\u002Fgrype",[19],"Grype",[15,698,701],{"href":699,"rel":700},"https:\u002F\u002Fsnyk.io\u002Fproduct\u002Fcontainer-vulnerability-management\u002F",[19],"Snyk Container"," がコンテナイメージの OS レイヤーとアプリケーションレイヤーの脆弱性を検出します。",[48,704,706],{"id":705},"iac-スキャン","IaC スキャン",[52,708,712],{"className":709,"code":710,"language":711,"meta":57,"style":57},"language-bash shiki shiki-themes tokyo-night","# Kubernetes マニフェストとHelmチャートのスキャン\ntrivy config .\u002Fk8s-manifests\u002F\nkubescape scan framework nsa .\u002Fhelm-charts\u002F\ncheckov -d .\u002Fterraform\u002F\n","bash",[59,713,714,719,731,748],{"__ignoreMap":57},[62,715,716],{"class":64,"line":65},[62,717,718],{"class":68},"# Kubernetes マニフェストとHelmチャートのスキャン\n",[62,720,721,725,728],{"class":64,"line":72},[62,722,724],{"class":723},"sE3pS","trivy",[62,726,727],{"class":96}," config",[62,729,730],{"class":96}," .\u002Fk8s-manifests\u002F\n",[62,732,733,736,739,742,745],{"class":64,"line":83},[62,734,735],{"class":723},"kubescape",[62,737,738],{"class":96}," scan",[62,740,741],{"class":96}," framework",[62,743,744],{"class":96}," nsa",[62,746,747],{"class":96}," .\u002Fhelm-charts\u002F\n",[62,749,750,753,757],{"class":64,"line":100},[62,751,752],{"class":723},"checkov",[62,754,756],{"class":755},"sT800"," -d",[62,758,759],{"class":96}," .\u002Fterraform\u002F\n",[11,761,762,765],{},[15,763,26],{"href":24,"rel":764},[19]," のデプロイパイプラインには、これらのセキュリティスキャンが標準で統合されています。",[29,767,769],{"id":768},"サプライチェーンセキュリティと-slsa-フレームワーク","サプライチェーンセキュリティと SLSA フレームワーク",[11,771,772,773,778],{},"ソフトウェアサプライチェーン攻撃が急増する中、",[15,774,777],{"href":775,"rel":776},"https:\u002F\u002Fslsa.dev\u002F",[19],"SLSA（Supply-chain Levels for Software Artifacts）","フレームワークによるビルドの完全性保証が重要になっています。",[48,780,782],{"id":781},"slsa-レベルの段階的導入","SLSA レベルの段階的導入",[784,785,786,802],"table",{},[787,788,789],"thead",{},[790,791,792,796,799],"tr",{},[793,794,795],"th",{},"レベル",[793,797,798],{},"要件",[793,800,801],{},"目標",[803,804,805,817,828],"tbody",{},[790,806,807,811,814],{},[808,809,810],"td",{},"SLSA 1",[808,812,813],{},"ビルドプロセスの文書化",[808,815,816],{},"基本的な透明性",[790,818,819,822,825],{},[808,820,821],{},"SLSA 2",[808,823,824],{},"ホステッドビルドサービス + 来歴（Provenance）生成",[808,826,827],{},"改ざん検出",[790,829,830,833,836],{},[808,831,832],{},"SLSA 3",[808,834,835],{},"ハード化されたビルドプラットフォーム + 検証可能な来歴",[808,837,838],{},"改ざん防止",[48,840,842],{"id":841},"sigstore-によるコンテナ署名","Sigstore によるコンテナ署名",[11,844,845,850,851,691,856,691,861,866],{},[15,846,849],{"href":847,"rel":848},"https:\u002F\u002Fwww.sigstore.dev\u002F",[19],"Sigstore"," は、コンテナイメージの署名と検証のためのオープンインフラです。",[15,852,855],{"href":853,"rel":854},"https:\u002F\u002Fdocs.sigstore.dev\u002Fcosign\u002Foverview\u002F",[19],"Cosign",[15,857,860],{"href":858,"rel":859},"https:\u002F\u002Fdocs.sigstore.dev\u002Ffulcio\u002Foverview\u002F",[19],"Fulcio",[15,862,865],{"href":863,"rel":864},"https:\u002F\u002Fdocs.sigstore.dev\u002Frekor\u002Foverview\u002F",[19],"Rekor"," の 3 コンポーネントで構成されます。",[52,868,870],{"className":709,"code":869,"language":711,"meta":57,"style":57},"# Cosign でイメージに署名（キーレス署名）\ncosign sign --yes ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n\n# 署名の検証\ncosign verify \\\n  --certificate-oidc-issuer https:\u002F\u002Ftoken.actions.githubusercontent.com \\\n  --certificate-identity-regexp \"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F\" \\\n  ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n",[59,871,872,877,891,895,900,910,920,936],{"__ignoreMap":57},[62,873,874],{"class":64,"line":65},[62,875,876],{"class":68},"# Cosign でイメージに署名（キーレス署名）\n",[62,878,879,882,885,888],{"class":64,"line":72},[62,880,881],{"class":723},"cosign",[62,883,884],{"class":96}," sign",[62,886,887],{"class":755}," --yes",[62,889,890],{"class":96}," ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n",[62,892,893],{"class":64,"line":83},[62,894,148],{"emptyLinePlaceholder":147},[62,896,897],{"class":64,"line":100},[62,898,899],{"class":68},"# 署名の検証\n",[62,901,902,904,907],{"class":64,"line":111},[62,903,881],{"class":723},[62,905,906],{"class":96}," verify",[62,908,909],{"class":79}," \\\n",[62,911,912,915,918],{"class":64,"line":119},[62,913,914],{"class":755},"  --certificate-oidc-issuer",[62,916,917],{"class":96}," https:\u002F\u002Ftoken.actions.githubusercontent.com",[62,919,909],{"class":79},[62,921,922,925,928,931,934],{"class":64,"line":133},[62,923,924],{"class":755},"  --certificate-identity-regexp",[62,926,927],{"class":79}," \"",[62,929,930],{"class":96},"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F",[62,932,933],{"class":79},"\"",[62,935,909],{"class":79},[62,937,938],{"class":64,"line":144},[62,939,940],{"class":96},"  ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n",[48,942,944],{"id":943},"sbomソフトウェア部品表の生成","SBOM（ソフトウェア部品表）の生成",[52,946,948],{"className":54,"code":947,"language":56,"meta":57,"style":57},"    - name: Generate SBOM\n      uses: anchore\u002Fsbom-action@v0\n      with:\n        image: ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}\n        format: spdx-json\n        output-file: sbom.spdx.json\n\n    - name: Attest SBOM\n      uses: actions\u002Fattest-sbom@v1\n      with:\n        subject-name: ghcr.io\u002Fyour-org\u002Fapp\n        subject-digest: sha256:abc123\n        sbom-path: sbom.spdx.json\n",[59,949,950,961,970,976,986,995,1005,1009,1020,1029,1035,1045,1055],{"__ignoreMap":57},[62,951,952,954,956,958],{"class":64,"line":65},[62,953,251],{"class":86},[62,955,270],{"class":75},[62,957,93],{"class":79},[62,959,960],{"class":96}," Generate SBOM\n",[62,962,963,965,967],{"class":64,"line":72},[62,964,280],{"class":75},[62,966,93],{"class":79},[62,968,969],{"class":96}," anchore\u002Fsbom-action@v0\n",[62,971,972,974],{"class":64,"line":83},[62,973,388],{"class":75},[62,975,80],{"class":79},[62,977,978,981,983],{"class":64,"line":100},[62,979,980],{"class":75},"        image",[62,982,93],{"class":79},[62,984,985],{"class":96}," ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}\n",[62,987,988,990,992],{"class":64,"line":111},[62,989,413],{"class":75},[62,991,93],{"class":79},[62,993,994],{"class":96}," spdx-json\n",[62,996,997,1000,1002],{"class":64,"line":119},[62,998,999],{"class":75},"        output-file",[62,1001,93],{"class":79},[62,1003,1004],{"class":96}," sbom.spdx.json\n",[62,1006,1007],{"class":64,"line":133},[62,1008,148],{"emptyLinePlaceholder":147},[62,1010,1011,1013,1015,1017],{"class":64,"line":144},[62,1012,251],{"class":86},[62,1014,270],{"class":75},[62,1016,93],{"class":79},[62,1018,1019],{"class":96}," Attest SBOM\n",[62,1021,1022,1024,1026],{"class":64,"line":151},[62,1023,280],{"class":75},[62,1025,93],{"class":79},[62,1027,1028],{"class":96}," actions\u002Fattest-sbom@v1\n",[62,1030,1031,1033],{"class":64,"line":163},[62,1032,388],{"class":75},[62,1034,80],{"class":79},[62,1036,1037,1040,1042],{"class":64,"line":173},[62,1038,1039],{"class":75},"        subject-name",[62,1041,93],{"class":79},[62,1043,1044],{"class":96}," ghcr.io\u002Fyour-org\u002Fapp\n",[62,1046,1047,1050,1052],{"class":64,"line":180},[62,1048,1049],{"class":75},"        subject-digest",[62,1051,93],{"class":79},[62,1053,1054],{"class":96}," sha256:abc123\n",[62,1056,1057,1060,1062],{"class":64,"line":192},[62,1058,1059],{"class":75},"        sbom-path",[62,1061,93],{"class":79},[62,1063,1004],{"class":96},[11,1065,1066,1071],{},[15,1067,1070],{"href":1068,"rel":1069},"https:\u002F\u002Fgithub.blog\u002Fsecurity\u002Fsupply-chain-security\u002Fslsa-3-compliance-with-github-actions\u002F",[19],"GitHub のブログ","によると、GitHub Actions と Sigstore を組み合わせることで SLSA Level 2 は数時間で達成可能、Level 3 も数週間で実装できます。",[29,1073,1075],{"id":1074},"policy-as-code-とガードレール","Policy as Code とガードレール",[11,1077,1078],{},"セキュリティポリシーをコードとして定義し、パイプライン全体で自動適用します。",[48,1080,1082],{"id":1081},"opagatekeeper-によるアドミッションコントロール","OPA\u002FGatekeeper によるアドミッションコントロール",[52,1084,1086],{"className":54,"code":1085,"language":56,"meta":57,"style":57},"# 特権コンテナの禁止ポリシー\napiVersion: constraints.gatekeeper.sh\u002Fv1beta1\nkind: K8sPSPPrivilegedContainer\nmetadata:\n  name: deny-privileged\nspec:\n  match:\n    kinds:\n      - apiGroups: [\"\"]\n        kinds: [\"Pod\"]\n  parameters:\n    exemptImages:\n      - \"istio-proxyv2:*\"\n",[59,1087,1088,1093,1103,1113,1120,1130,1137,1144,1151,1169,1187,1194,1201],{"__ignoreMap":57},[62,1089,1090],{"class":64,"line":65},[62,1091,1092],{"class":68},"# 特権コンテナの禁止ポリシー\n",[62,1094,1095,1098,1100],{"class":64,"line":72},[62,1096,1097],{"class":75},"apiVersion",[62,1099,93],{"class":79},[62,1101,1102],{"class":96}," constraints.gatekeeper.sh\u002Fv1beta1\n",[62,1104,1105,1108,1110],{"class":64,"line":83},[62,1106,1107],{"class":75},"kind",[62,1109,93],{"class":79},[62,1111,1112],{"class":96}," K8sPSPPrivilegedContainer\n",[62,1114,1115,1118],{"class":64,"line":100},[62,1116,1117],{"class":75},"metadata",[62,1119,80],{"class":79},[62,1121,1122,1125,1127],{"class":64,"line":111},[62,1123,1124],{"class":75},"  name",[62,1126,93],{"class":79},[62,1128,1129],{"class":96}," deny-privileged\n",[62,1131,1132,1135],{"class":64,"line":119},[62,1133,1134],{"class":75},"spec",[62,1136,80],{"class":79},[62,1138,1139,1142],{"class":64,"line":133},[62,1140,1141],{"class":75},"  match",[62,1143,80],{"class":79},[62,1145,1146,1149],{"class":64,"line":144},[62,1147,1148],{"class":75},"    kinds",[62,1150,80],{"class":79},[62,1152,1153,1155,1158,1160,1163,1166],{"class":64,"line":151},[62,1154,122],{"class":86},[62,1156,1157],{"class":75}," apiGroups",[62,1159,93],{"class":79},[62,1161,1162],{"class":79}," [",[62,1164,1165],{"class":79},"\"\"",[62,1167,1168],{"class":79},"]\n",[62,1170,1171,1174,1176,1178,1180,1183,1185],{"class":64,"line":163},[62,1172,1173],{"class":75},"        kinds",[62,1175,93],{"class":79},[62,1177,1162],{"class":79},[62,1179,933],{"class":79},[62,1181,1182],{"class":96},"Pod",[62,1184,933],{"class":79},[62,1186,1168],{"class":79},[62,1188,1189,1192],{"class":64,"line":173},[62,1190,1191],{"class":75},"  parameters",[62,1193,80],{"class":79},[62,1195,1196,1199],{"class":64,"line":180},[62,1197,1198],{"class":75},"    exemptImages",[62,1200,80],{"class":79},[62,1202,1203,1205,1207,1210],{"class":64,"line":192},[62,1204,122],{"class":86},[62,1206,927],{"class":79},[62,1208,1209],{"class":96},"istio-proxyv2:*",[62,1211,1212],{"class":79},"\"\n",[48,1214,1216],{"id":1215},"kyverno-によるポリシー適用","Kyverno によるポリシー適用",[52,1218,1220],{"className":54,"code":1219,"language":56,"meta":57,"style":57},"apiVersion: kyverno.io\u002Fv1\nkind: ClusterPolicy\nmetadata:\n  name: require-signed-images\nspec:\n  validationFailureAction: Enforce\n  rules:\n    - name: verify-signature\n      match:\n        any:\n          - resources:\n              kinds:\n                - Pod\n      verifyImages:\n        - imageReferences:\n            - \"ghcr.io-your-org-*\"\n          attestors:\n            - entries:\n                - keyless:\n                    subject: \"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F*\"\n                    issuer: \"https:\u002F\u002Ftoken.actions.githubusercontent.com\"\n",[59,1221,1222,1231,1240,1246,1255,1261,1271,1278,1289,1296,1303,1313,1320,1328,1335,1345,1357,1364,1373,1382,1396],{"__ignoreMap":57},[62,1223,1224,1226,1228],{"class":64,"line":65},[62,1225,1097],{"class":75},[62,1227,93],{"class":79},[62,1229,1230],{"class":96}," kyverno.io\u002Fv1\n",[62,1232,1233,1235,1237],{"class":64,"line":72},[62,1234,1107],{"class":75},[62,1236,93],{"class":79},[62,1238,1239],{"class":96}," ClusterPolicy\n",[62,1241,1242,1244],{"class":64,"line":83},[62,1243,1117],{"class":75},[62,1245,80],{"class":79},[62,1247,1248,1250,1252],{"class":64,"line":100},[62,1249,1124],{"class":75},[62,1251,93],{"class":79},[62,1253,1254],{"class":96}," require-signed-images\n",[62,1256,1257,1259],{"class":64,"line":111},[62,1258,1134],{"class":75},[62,1260,80],{"class":79},[62,1262,1263,1266,1268],{"class":64,"line":119},[62,1264,1265],{"class":75},"  validationFailureAction",[62,1267,93],{"class":79},[62,1269,1270],{"class":96}," Enforce\n",[62,1272,1273,1276],{"class":64,"line":133},[62,1274,1275],{"class":75},"  rules",[62,1277,80],{"class":79},[62,1279,1280,1282,1284,1286],{"class":64,"line":144},[62,1281,251],{"class":86},[62,1283,270],{"class":75},[62,1285,93],{"class":79},[62,1287,1288],{"class":96}," verify-signature\n",[62,1290,1291,1294],{"class":64,"line":151},[62,1292,1293],{"class":75},"      match",[62,1295,80],{"class":79},[62,1297,1298,1301],{"class":64,"line":163},[62,1299,1300],{"class":75},"        any",[62,1302,80],{"class":79},[62,1304,1305,1308,1311],{"class":64,"line":173},[62,1306,1307],{"class":86},"          -",[62,1309,1310],{"class":75}," resources",[62,1312,80],{"class":79},[62,1314,1315,1318],{"class":64,"line":180},[62,1316,1317],{"class":75},"              kinds",[62,1319,80],{"class":79},[62,1321,1322,1325],{"class":64,"line":192},[62,1323,1324],{"class":86},"                -",[62,1326,1327],{"class":96}," Pod\n",[62,1329,1330,1333],{"class":64,"line":330},[62,1331,1332],{"class":75},"      verifyImages",[62,1334,80],{"class":79},[62,1336,1337,1340,1343],{"class":64,"line":340},[62,1338,1339],{"class":86},"        -",[62,1341,1342],{"class":75}," imageReferences",[62,1344,80],{"class":79},[62,1346,1347,1350,1352,1355],{"class":64,"line":347},[62,1348,1349],{"class":86},"            -",[62,1351,927],{"class":79},[62,1353,1354],{"class":96},"ghcr.io-your-org-*",[62,1356,1212],{"class":79},[62,1358,1359,1362],{"class":64,"line":358},[62,1360,1361],{"class":75},"          attestors",[62,1363,80],{"class":79},[62,1365,1366,1368,1371],{"class":64,"line":363},[62,1367,1349],{"class":86},[62,1369,1370],{"class":75}," entries",[62,1372,80],{"class":79},[62,1374,1375,1377,1380],{"class":64,"line":375},[62,1376,1324],{"class":86},[62,1378,1379],{"class":75}," keyless",[62,1381,80],{"class":79},[62,1383,1384,1387,1389,1391,1394],{"class":64,"line":385},[62,1385,1386],{"class":75},"                    subject",[62,1388,93],{"class":79},[62,1390,927],{"class":79},[62,1392,1393],{"class":96},"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F*",[62,1395,1212],{"class":79},[62,1397,1398,1401,1403,1405,1408],{"class":64,"line":393},[62,1399,1400],{"class":75},"                    issuer",[62,1402,93],{"class":79},[62,1404,927],{"class":79},[62,1406,1407],{"class":96},"https:\u002F\u002Ftoken.actions.githubusercontent.com",[62,1409,1212],{"class":79},[11,1411,1412,1417,1418,1423],{},[15,1413,1416],{"href":1414,"rel":1415},"https:\u002F\u002Fkyverno.io\u002F",[19],"Kyverno"," と ",[15,1419,1422],{"href":1420,"rel":1421},"https:\u002F\u002Fopen-policy-agent.github.io\u002Fgatekeeper\u002F",[19],"OPA Gatekeeper"," を Kubernetes クラスタに導入し、署名されていないイメージや特権コンテナのデプロイをブロックします。",[48,1425,1426],{"id":1426},"ベースラインポリシーの設定",[11,1428,1429,1434,1435,1438],{},[15,1430,1433],{"href":1431,"rel":1432},"https:\u002F\u002Fwww.wiz.io\u002Facademy\u002Fapplication-security\u002Fci-cd-security-best-practices",[19],"Wiz のガイド","が推奨するように、",[37,1436,1437],{},"明確に許容できないリスク","（積極的に悪用されている脆弱性、署名なしイメージなど）をブロックするベースラインポリシーを設定し、開発速度を過度に制約しないバランスが重要です。",[29,1440,1441],{"id":1441},"ランタイム監視とフィードバックループ",[11,1443,1444],{},"デプロイ後のセキュリティも継続的に監視します。",[48,1446,1447],{"id":1447},"ランタイムドリフト検出",[52,1449,1451],{"className":54,"code":1450,"language":56,"meta":57,"style":57},"# Falco によるランタイムセキュリティ監視\n- rule: Unexpected Network Connection\n  desc: Detect network connections to unexpected destinations\n  condition: >\n    outbound and not (fd.sip in (allowed_outbound_destinations))\n  output: >\n    Unexpected outbound connection\n    (command=%proc.cmdline connection=%fd.name user=%user.name)\n  priority: WARNING\n",[59,1452,1453,1458,1471,1481,1492,1497,1506,1511,1516],{"__ignoreMap":57},[62,1454,1455],{"class":64,"line":65},[62,1456,1457],{"class":68},"# Falco によるランタイムセキュリティ監視\n",[62,1459,1460,1463,1466,1468],{"class":64,"line":72},[62,1461,1462],{"class":86},"-",[62,1464,1465],{"class":75}," rule",[62,1467,93],{"class":79},[62,1469,1470],{"class":96}," Unexpected Network Connection\n",[62,1472,1473,1476,1478],{"class":64,"line":83},[62,1474,1475],{"class":75},"  desc",[62,1477,93],{"class":79},[62,1479,1480],{"class":96}," Detect network connections to unexpected destinations\n",[62,1482,1483,1486,1488],{"class":64,"line":100},[62,1484,1485],{"class":75},"  condition",[62,1487,93],{"class":79},[62,1489,1491],{"class":1490},"sEsAJ"," >\n",[62,1493,1494],{"class":64,"line":111},[62,1495,1496],{"class":96},"    outbound and not (fd.sip in (allowed_outbound_destinations))\n",[62,1498,1499,1502,1504],{"class":64,"line":119},[62,1500,1501],{"class":75},"  output",[62,1503,93],{"class":79},[62,1505,1491],{"class":1490},[62,1507,1508],{"class":64,"line":133},[62,1509,1510],{"class":96},"    Unexpected outbound connection\n",[62,1512,1513],{"class":64,"line":144},[62,1514,1515],{"class":96},"    (command=%proc.cmdline connection=%fd.name user=%user.name)\n",[62,1517,1518,1521,1523],{"class":64,"line":151},[62,1519,1520],{"class":75},"  priority",[62,1522,93],{"class":79},[62,1524,1525],{"class":96}," WARNING\n",[11,1527,1528,1533],{},[15,1529,1532],{"href":1530,"rel":1531},"https:\u002F\u002Ffalco.org\u002F",[19],"Falco"," はKubernetes のランタイムセキュリティ監視ツールとして、不正なプロセス実行、ネットワーク接続、ファイルアクセスをリアルタイムで検出します。",[48,1535,1536],{"id":1536},"フィードバックループの構築",[11,1538,1539],{},"ランタイムで検出された問題を ci-cd の改善にフィードバックする循環を構築します。",[1541,1542,1543,1549,1555,1561,1567],"ol",{},[448,1544,1545,1548],{},[37,1546,1547],{},"検出",": Falco がランタイム異常を検出",[448,1550,1551,1554],{},[37,1552,1553],{},"通知",": Slack\u002FPagerDuty にアラート送信",[448,1556,1557,1560],{},[37,1558,1559],{},"分析",": 根本原因をパイプラインの欠陥と特定",[448,1562,1563,1566],{},[37,1564,1565],{},"修正",": ポリシーやスキャンルールを更新",[448,1568,1569,1572],{},[37,1570,1571],{},"検証",": 次回デプロイで修正を確認",[11,1574,1575,1578],{},[15,1576,429],{"href":427,"rel":1577},[19]," は、このフィードバックループを AI で高速化し、検出から修正提案までを自動化します。",[29,1580,1581],{"id":1581},"コンプライアンスと監査",[48,1583,1584],{"id":1584},"自動化された監査証跡",[11,1586,1587],{},"ci-cd パイプラインの各ステップが自動的に監査証跡を生成し、主要なコンプライアンスフレームワーク（SOC 2、ISO 27001、NIST、PCI DSS）への対応を簡素化します。",[52,1589,1591],{"className":54,"code":1590,"language":56,"meta":57,"style":57},"    - name: Generate Attestation\n      uses: actions\u002Fattest-build-provenance@v1\n      with:\n        subject-name: ghcr.io\u002Fyour-org\u002Fapp\n        subject-digest: sha256:abc123\n",[59,1592,1593,1604,1613,1619,1627],{"__ignoreMap":57},[62,1594,1595,1597,1599,1601],{"class":64,"line":65},[62,1596,251],{"class":86},[62,1598,270],{"class":75},[62,1600,93],{"class":79},[62,1602,1603],{"class":96}," Generate Attestation\n",[62,1605,1606,1608,1610],{"class":64,"line":72},[62,1607,280],{"class":75},[62,1609,93],{"class":79},[62,1611,1612],{"class":96}," actions\u002Fattest-build-provenance@v1\n",[62,1614,1615,1617],{"class":64,"line":83},[62,1616,388],{"class":75},[62,1618,80],{"class":79},[62,1620,1621,1623,1625],{"class":64,"line":100},[62,1622,1039],{"class":75},[62,1624,93],{"class":79},[62,1626,1044],{"class":96},[62,1628,1629,1631,1633],{"class":64,"line":111},[62,1630,1049],{"class":75},[62,1632,93],{"class":79},[62,1634,1054],{"class":96},[11,1636,1637,1641,1642,1645],{},[15,1638,1640],{"href":775,"rel":1639},[19],"SLSA"," の来歴情報、",[15,1643,849],{"href":847,"rel":1644},[19]," の署名ログ（Rekor）、SBOM がコンプライアンスの証拠として機能します。",[29,1647,1649],{"id":1648},"まとめ-kubo-でセキュアな-ci-cd-を実現する","まとめ: Kubo でセキュアな ci-cd を実現する",[11,1651,1652],{},"ci-cd パイプラインのセキュリティは、Shift-Left、多層テスト、サプライチェーン保護、Policy as Code、ランタイム監視の 5 層で構成されます。すべてを一度に導入する必要はありません。まず SAST とコンテナスキャンから始め、段階的に成熟度を高めていくアプローチが現実的です。",[11,1654,1655,1658,1659,1662,1663,1668],{},[15,1656,26],{"href":24,"rel":1657},[19]," はセキュリティを組み込んだ ci-cd 基盤を提供しており、コンテナスキャン、ポリシー適用、署名検証が標準で統合されています。",[15,1660,429],{"href":427,"rel":1661},[19]," の AI セキュリティアシスタントが脆弱性の優先順位付けと修正提案を自動化し、開発速度を落とさないセキュリティ運用を実現します。セキュアな ci-cd パイプラインを構築したい方は、ぜひ",[15,1664,1667],{"href":1665,"rel":1666},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[19],"お問い合わせ","ください。",[1670,1671,1672],"style",{},"html pre.shiki code .sbD-w, html code.shiki .sbD-w{--shiki-default:#51597D;--shiki-default-font-style:italic}html pre.shiki code .s0U2E, html code.shiki .s0U2E{--shiki-default:#F7768E}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sgJMe, html code.shiki .sgJMe{--shiki-default:#9ABDF5}html pre.shiki code .sPY7s, html code.shiki .sPY7s{--shiki-default:#9ECE6A}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sE3pS, html code.shiki .sE3pS{--shiki-default:#C0CAF5}html pre.shiki code .sT800, html code.shiki .sT800{--shiki-default:#E0AF68}html pre.shiki code .sEsAJ, html code.shiki .sEsAJ{--shiki-default:#BB9AF7;--shiki-default-font-style:italic}",{"title":57,"searchDepth":72,"depth":72,"links":1674},[1675,1679,1686,1691,1696,1700,1703],{"id":31,"depth":72,"text":32,"children":1676},[1677,1678],{"id":50,"depth":83,"text":50},{"id":211,"depth":83,"text":212},{"id":433,"depth":72,"text":433,"children":1680},[1681,1682,1683,1684,1685],{"id":439,"depth":83,"text":440},{"id":480,"depth":83,"text":481},{"id":572,"depth":83,"text":573},{"id":601,"depth":83,"text":601},{"id":705,"depth":83,"text":706},{"id":768,"depth":72,"text":769,"children":1687},[1688,1689,1690],{"id":781,"depth":83,"text":782},{"id":841,"depth":83,"text":842},{"id":943,"depth":83,"text":944},{"id":1074,"depth":72,"text":1075,"children":1692},[1693,1694,1695],{"id":1081,"depth":83,"text":1082},{"id":1215,"depth":83,"text":1216},{"id":1426,"depth":83,"text":1426},{"id":1441,"depth":72,"text":1441,"children":1697},[1698,1699],{"id":1447,"depth":83,"text":1447},{"id":1536,"depth":83,"text":1536},{"id":1581,"depth":72,"text":1581,"children":1701},[1702],{"id":1584,"depth":83,"text":1584},{"id":1648,"depth":72,"text":1649},"2026-05-27","ci-cd パイプラインのセキュリティを DevSecOps の観点で実践的に解説。SAST\u002FDAST、サプライチェーン保護、SLSA フレームワーク、Policy as Code まで。","md","ja",{},"\u002Fblog\u002Fja\u002Fcicd-pipeline-security-devsecops",{"title":5,"description":1705},"blog\u002Fja\u002Fcicd-pipeline-security-devsecops",[1713,1714,1715,1716,1640,1717],"DevSecOps","ci-cd","セキュリティ","サプライチェーン","Kubernetes","_zIhDaUpR6jqnFMIjlAP4QXq_z9T_3pUHlDYzTqGZro",1779964617052]