[{"data":1,"prerenderedAt":1733},["ShallowReactive",2],{"blog-en-cicd-pipeline-security-devsecops":3,"blog-en-cicd-pipeline-security-devsecops-alt":148},{"id":4,"title":5,"author":6,"body":7,"date":1718,"description":1719,"extension":1720,"image":58,"locale":1721,"meta":1722,"navigation":148,"path":1723,"seo":1724,"stem":1725,"tags":1726,"__hash__":1732},"blog\u002Fblog\u002Fen\u002Fcicd-pipeline-security-devsecops.md","ci-cd Pipeline Security: A Practical DevSecOps Guide","Kubo Team",{"type":8,"value":9,"toc":1687},"minimark",[10,28,33,47,52,201,210,214,424,432,436,439,443,446,480,484,487,572,576,579,601,605,687,707,711,764,771,775,784,788,844,848,871,945,949,1068,1077,1081,1084,1088,1218,1222,1415,1430,1434,1447,1451,1454,1458,1536,1544,1548,1551,1584,1590,1594,1598,1601,1648,1659,1663,1666,1683],[11,12,13,14,21,22,27],"p",{},"Your ci-cd pipeline is the fastest route for code to reach production---and the most attractive target for attackers. The GhostAction attack in early 2025 compromised a widely-used GitHub Action, exfiltrating secrets from thousands of repositories. According to ",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Fwww.qualys.com\u002Ffundamentals\u002Fci-cd-security-best-practices",[19],"nofollow","Qualys research",", 68% of organizations have now implemented DevSecOps, but technical complexity (41%), resource constraints (35%), and cultural resistance (38%) remain significant challenges. ",[15,23,26],{"href":24,"rel":25},"https:\u002F\u002Fkubo.hexabase.io\u002F",[19],"Kubo"," provides a ci-cd foundation with security built in, and the practices in this article are available as standard capabilities.",[29,30,32],"h2",{"id":31},"shift-left-embed-security-from-the-start","Shift-Left: Embed Security from the Start",[11,34,35,36,40,41,46],{},"The core DevSecOps principle is ",[37,38,39],"strong",{},"\"Shift-Left\"","---moving security checks to the earliest possible stage of the pipeline. According to ",[15,42,45],{"href":43,"rel":44},"https:\u002F\u002Fwww.practical-devsecops.com\u002Fdevsecops-best-practices\u002F",[19],"Practical DevSecOps",", the cost of fixing security issues increases exponentially the later they are discovered.",[48,49,51],"h3",{"id":50},"security-in-the-development-environment","Security in the Development Environment",[53,54,59],"pre",{"className":55,"code":56,"language":57,"meta":58,"style":58},"language-yaml shiki shiki-themes tokyo-night","# pre-commit hook configuration example\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","",[60,61,62,71,82,99,110,118,132,143,150,162,172,179,191],"code",{"__ignoreMap":58},[63,64,67],"span",{"class":65,"line":66},"line",1,[63,68,70],{"class":69},"sbD-w","# pre-commit hook configuration example\n",[63,72,74,78],{"class":65,"line":73},2,[63,75,77],{"class":76},"s0U2E","repos",[63,79,81],{"class":80},"sAklC",":\n",[63,83,85,89,92,95],{"class":65,"line":84},3,[63,86,88],{"class":87},"sgJMe","  -",[63,90,91],{"class":76}," repo",[63,93,94],{"class":80},":",[63,96,98],{"class":97},"sPY7s"," https:--github.com-gitleaks-gitleaks\n",[63,100,102,105,107],{"class":65,"line":101},4,[63,103,104],{"class":76},"    rev",[63,106,94],{"class":80},[63,108,109],{"class":97}," v8.18.0\n",[63,111,113,116],{"class":65,"line":112},5,[63,114,115],{"class":76},"    hooks",[63,117,81],{"class":80},[63,119,121,124,127,129],{"class":65,"line":120},6,[63,122,123],{"class":87},"      -",[63,125,126],{"class":76}," id",[63,128,94],{"class":80},[63,130,131],{"class":97}," gitleaks\n",[63,133,135,138,140],{"class":65,"line":134},7,[63,136,137],{"class":76},"        name",[63,139,94],{"class":80},[63,141,142],{"class":97}," Detect hardcoded secrets\n",[63,144,146],{"class":65,"line":145},8,[63,147,149],{"emptyLinePlaceholder":148},true,"\n",[63,151,153,155,157,159],{"class":65,"line":152},9,[63,154,88],{"class":87},[63,156,91],{"class":76},[63,158,94],{"class":80},[63,160,161],{"class":97}," https:--github.com-hadolint-hadolint\n",[63,163,165,167,169],{"class":65,"line":164},10,[63,166,104],{"class":76},[63,168,94],{"class":80},[63,170,171],{"class":97}," v2.12.0\n",[63,173,175,177],{"class":65,"line":174},11,[63,176,115],{"class":76},[63,178,81],{"class":80},[63,180,182,184,186,188],{"class":65,"line":181},12,[63,183,123],{"class":87},[63,185,126],{"class":76},[63,187,94],{"class":80},[63,189,190],{"class":97}," hadolint-docker\n",[63,192,194,196,198],{"class":65,"line":193},13,[63,195,137],{"class":76},[63,197,94],{"class":80},[63,199,200],{"class":97}," Lint Dockerfile\n",[11,202,203,204,209],{},"Detect accidental secret commits and Dockerfile best practice violations at the developer IDE or pre-commit stage. Tools like ",[15,205,208],{"href":206,"rel":207},"https:\u002F\u002Fblog.gitguardian.com\u002Fsupply-chain-security-sigstore-and-cosign-part-ii\u002F",[19],"GitGuardian"," automate secret scanning across entire repositories.",[48,211,213],{"id":212},"early-ci-pipeline-stage","Early CI Pipeline Stage",[53,215,217],{"className":55,"code":216,"language":57,"meta":58,"style":58},"# Shift-Left security in GitHub Actions\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",[60,218,219,224,231,241,248,261,265,277,287,294,304,314,318,329,339,346,357,362,374,384,392,409],{"__ignoreMap":58},[63,220,221],{"class":65,"line":66},[63,222,223],{"class":69},"# Shift-Left security in GitHub Actions\n",[63,225,226,229],{"class":65,"line":73},[63,227,228],{"class":76},"security-checks",[63,230,81],{"class":80},[63,232,233,236,238],{"class":65,"line":84},[63,234,235],{"class":76},"  runs-on",[63,237,94],{"class":80},[63,239,240],{"class":97}," ubuntu-latest\n",[63,242,243,246],{"class":65,"line":101},[63,244,245],{"class":76},"  steps",[63,247,81],{"class":80},[63,249,250,253,256,258],{"class":65,"line":112},[63,251,252],{"class":87},"    -",[63,254,255],{"class":76}," uses",[63,257,94],{"class":80},[63,259,260],{"class":97}," actions-checkout@v4\n",[63,262,263],{"class":65,"line":120},[63,264,149],{"emptyLinePlaceholder":148},[63,266,267,269,272,274],{"class":65,"line":134},[63,268,252],{"class":87},[63,270,271],{"class":76}," name",[63,273,94],{"class":80},[63,275,276],{"class":97}," SAST - SonarQube Scan\n",[63,278,279,282,284],{"class":65,"line":145},[63,280,281],{"class":76},"      uses",[63,283,94],{"class":80},[63,285,286],{"class":97}," SonarSource\u002Fsonarqube-scan-action@master\n",[63,288,289,292],{"class":65,"line":152},[63,290,291],{"class":76},"      env",[63,293,81],{"class":80},[63,295,296,299,301],{"class":65,"line":164},[63,297,298],{"class":76},"        SONAR_TOKEN",[63,300,94],{"class":80},[63,302,303],{"class":97}," ${{ secrets.SONAR_TOKEN }}\n",[63,305,306,309,311],{"class":65,"line":174},[63,307,308],{"class":76},"        SONAR_HOST_URL",[63,310,94],{"class":80},[63,312,313],{"class":97}," ${{ secrets.SONAR_HOST_URL }}\n",[63,315,316],{"class":65,"line":181},[63,317,149],{"emptyLinePlaceholder":148},[63,319,320,322,324,326],{"class":65,"line":193},[63,321,252],{"class":87},[63,323,271],{"class":76},[63,325,94],{"class":80},[63,327,328],{"class":97}," Secrets Detection\n",[63,330,332,334,336],{"class":65,"line":331},14,[63,333,281],{"class":76},[63,335,94],{"class":80},[63,337,338],{"class":97}," gitleaks\u002Fgitleaks-action@v2\n",[63,340,342,344],{"class":65,"line":341},15,[63,343,291],{"class":76},[63,345,81],{"class":80},[63,347,349,352,354],{"class":65,"line":348},16,[63,350,351],{"class":76},"        GITLEAKS_LICENSE",[63,353,94],{"class":80},[63,355,356],{"class":97}," ${{ secrets.GITLEAKS_LICENSE }}\n",[63,358,360],{"class":65,"line":359},17,[63,361,149],{"emptyLinePlaceholder":148},[63,363,365,367,369,371],{"class":65,"line":364},18,[63,366,252],{"class":87},[63,368,271],{"class":76},[63,370,94],{"class":80},[63,372,373],{"class":97}," Dependency Check\n",[63,375,377,379,381],{"class":65,"line":376},19,[63,378,281],{"class":76},[63,380,94],{"class":80},[63,382,383],{"class":97}," dependency-check\u002FDependency-Check_Action@main\n",[63,385,387,390],{"class":65,"line":386},20,[63,388,389],{"class":76},"      with",[63,391,81],{"class":80},[63,393,395,398,400,403,406],{"class":65,"line":394},21,[63,396,397],{"class":76},"        path",[63,399,94],{"class":80},[63,401,402],{"class":80}," '",[63,404,405],{"class":97},".",[63,407,408],{"class":80},"'\n",[63,410,412,415,417,419,422],{"class":65,"line":411},22,[63,413,414],{"class":76},"        format",[63,416,94],{"class":80},[63,418,402],{"class":80},[63,420,421],{"class":97},"SARIF",[63,423,408],{"class":80},[11,425,426,431],{},[15,427,430],{"href":428,"rel":429},"https:\u002F\u002Fwww.hexabase.com\u002Fproduct\u002Fcaptain-ai\u002F",[19],"Captain.AI"," helps analyze security scan results and prioritize issues with AI, clarifying which problems developers should act on.",[29,433,435],{"id":434},"multi-layer-automated-security-testing","Multi-Layer Automated Security Testing",[11,437,438],{},"Embed multiple security testing layers into your ci-cd pipeline to detect different threats at different stages.",[48,440,442],{"id":441},"sast-static-application-security-testing","SAST (Static Application Security Testing)",[11,444,445],{},"Analyzes source code before compilation to detect vulnerabilities like SQL injection, XSS, and buffer overflows.",[447,448,449,460,470],"ul",{},[450,451,452,459],"li",{},[37,453,454],{},[15,455,458],{"href":456,"rel":457},"https:--www.sonarqube.org-",[19],"sonarqube",": multi-language support, quality gate features",[450,461,462,469],{},[37,463,464],{},[15,465,468],{"href":466,"rel":467},"https:\u002F\u002Fsemgrep.dev\u002F",[19],"Semgrep",": Lightweight, fast, easy custom rule definitions",[450,471,472,479],{},[37,473,474],{},[15,475,478],{"href":476,"rel":477},"https:\u002F\u002Fcodeql.github.com\u002F",[19],"CodeQL",": GitHub-native, semantic analysis",[48,481,483],{"id":482},"sca-software-composition-analysis","SCA (Software Composition Analysis)",[11,485,486],{},"Detects known vulnerabilities in open-source dependencies.",[53,488,490],{"className":55,"code":489,"language":57,"meta":58,"style":58},"    - 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",[60,491,492,503,512,518,532,545,558],{"__ignoreMap":58},[63,493,494,496,498,500],{"class":65,"line":66},[63,495,252],{"class":87},[63,497,271],{"class":76},[63,499,94],{"class":80},[63,501,502],{"class":97}," SCA Scan\n",[63,504,505,507,509],{"class":65,"line":73},[63,506,281],{"class":76},[63,508,94],{"class":80},[63,510,511],{"class":97}," aquasecurity\u002Ftrivy-action@master\n",[63,513,514,516],{"class":65,"line":84},[63,515,389],{"class":76},[63,517,81],{"class":80},[63,519,520,523,525,527,530],{"class":65,"line":101},[63,521,522],{"class":76},"        scan-type",[63,524,94],{"class":80},[63,526,402],{"class":80},[63,528,529],{"class":97},"fs",[63,531,408],{"class":80},[63,533,534,537,539,541,543],{"class":65,"line":112},[63,535,536],{"class":76},"        scan-ref",[63,538,94],{"class":80},[63,540,402],{"class":80},[63,542,405],{"class":97},[63,544,408],{"class":80},[63,546,547,549,551,553,556],{"class":65,"line":120},[63,548,414],{"class":76},[63,550,94],{"class":80},[63,552,402],{"class":80},[63,554,555],{"class":97},"sarif",[63,557,408],{"class":80},[63,559,560,563,565,567,570],{"class":65,"line":134},[63,561,562],{"class":76},"        severity",[63,564,94],{"class":80},[63,566,402],{"class":80},[63,568,569],{"class":97},"CRITICAL,HIGH",[63,571,408],{"class":80},[48,573,575],{"id":574},"dast-dynamic-application-security-testing","DAST (Dynamic Application Security Testing)",[11,577,578],{},"Tests against running applications to detect authentication bypass and session management issues.",[447,580,581,591],{},[450,582,583,590],{},[37,584,585],{},[15,586,589],{"href":587,"rel":588},"https:--www.zaproxy.org-",[19],"owasp zap",": open-source web application scanner",[450,592,593,600],{},[37,594,595],{},[15,596,599],{"href":597,"rel":598},"https:\u002F\u002Fgithub.com\u002Fprojectdiscovery\u002Fnuclei",[19],"Nuclei",": Template-based vulnerability scanner",[48,602,604],{"id":603},"container-scanning","Container Scanning",[53,606,608],{"className":55,"code":607,"language":57,"meta":58,"style":58},"    - 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",[60,609,610,621,629,635,649,661,673],{"__ignoreMap":58},[63,611,612,614,616,618],{"class":65,"line":66},[63,613,252],{"class":87},[63,615,271],{"class":76},[63,617,94],{"class":80},[63,619,620],{"class":97}," Container Image Scan\n",[63,622,623,625,627],{"class":65,"line":73},[63,624,281],{"class":76},[63,626,94],{"class":80},[63,628,511],{"class":97},[63,630,631,633],{"class":65,"line":84},[63,632,389],{"class":76},[63,634,81],{"class":80},[63,636,637,640,642,644,647],{"class":65,"line":101},[63,638,639],{"class":76},"        image-ref",[63,641,94],{"class":80},[63,643,402],{"class":80},[63,645,646],{"class":97},"ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}",[63,648,408],{"class":80},[63,650,651,653,655,657,659],{"class":65,"line":112},[63,652,414],{"class":76},[63,654,94],{"class":80},[63,656,402],{"class":80},[63,658,555],{"class":97},[63,660,408],{"class":80},[63,662,663,665,667,669,671],{"class":65,"line":120},[63,664,562],{"class":76},[63,666,94],{"class":80},[63,668,402],{"class":80},[63,670,569],{"class":97},[63,672,408],{"class":80},[63,674,675,678,680,682,685],{"class":65,"line":134},[63,676,677],{"class":76},"        exit-code",[63,679,94],{"class":80},[63,681,402],{"class":80},[63,683,684],{"class":97},"1",[63,686,408],{"class":80},[11,688,689,694,695,700,701,706],{},[15,690,693],{"href":691,"rel":692},"https:\u002F\u002Ftrivy.dev\u002F",[19],"Trivy",", ",[15,696,699],{"href":697,"rel":698},"https:\u002F\u002Fgithub.com\u002Fanchore\u002Fgrype",[19],"Grype",", and ",[15,702,705],{"href":703,"rel":704},"https:\u002F\u002Fsnyk.io\u002Fproduct\u002Fcontainer-vulnerability-management\u002F",[19],"Snyk Container"," detect vulnerabilities in both OS and application layers of container images.",[48,708,710],{"id":709},"iac-scanning","IaC Scanning",[53,712,716],{"className":713,"code":714,"language":715,"meta":58,"style":58},"language-bash shiki shiki-themes tokyo-night","# Scan Kubernetes manifests and Helm charts\ntrivy config .\u002Fk8s-manifests\u002F\nkubescape scan framework nsa .\u002Fhelm-charts\u002F\ncheckov -d .\u002Fterraform\u002F\n","bash",[60,717,718,723,735,752],{"__ignoreMap":58},[63,719,720],{"class":65,"line":66},[63,721,722],{"class":69},"# Scan Kubernetes manifests and Helm charts\n",[63,724,725,729,732],{"class":65,"line":73},[63,726,728],{"class":727},"sE3pS","trivy",[63,730,731],{"class":97}," config",[63,733,734],{"class":97}," .\u002Fk8s-manifests\u002F\n",[63,736,737,740,743,746,749],{"class":65,"line":84},[63,738,739],{"class":727},"kubescape",[63,741,742],{"class":97}," scan",[63,744,745],{"class":97}," framework",[63,747,748],{"class":97}," nsa",[63,750,751],{"class":97}," .\u002Fhelm-charts\u002F\n",[63,753,754,757,761],{"class":65,"line":101},[63,755,756],{"class":727},"checkov",[63,758,760],{"class":759},"sT800"," -d",[63,762,763],{"class":97}," .\u002Fterraform\u002F\n",[11,765,766,770],{},[15,767,769],{"href":24,"rel":768},[19],"Kubo's"," deployment pipelines come with these security scans integrated as standard.",[29,772,774],{"id":773},"supply-chain-security-and-the-slsa-framework","Supply Chain Security and the SLSA Framework",[11,776,777,778,783],{},"As software supply chain attacks surge, the ",[15,779,782],{"href":780,"rel":781},"https:\u002F\u002Fslsa.dev\u002F",[19],"SLSA (Supply-chain Levels for Software Artifacts)"," framework has become essential for ensuring build integrity.",[48,785,787],{"id":786},"graduated-slsa-level-adoption","Graduated SLSA Level Adoption",[789,790,791,807],"table",{},[792,793,794],"thead",{},[795,796,797,801,804],"tr",{},[798,799,800],"th",{},"Level",[798,802,803],{},"Requirements",[798,805,806],{},"Goal",[808,809,810,822,833],"tbody",{},[795,811,812,816,819],{},[813,814,815],"td",{},"SLSA 1",[813,817,818],{},"Build process documentation",[813,820,821],{},"Basic transparency",[795,823,824,827,830],{},[813,825,826],{},"SLSA 2",[813,828,829],{},"Hosted build service + provenance generation",[813,831,832],{},"Tamper detection",[795,834,835,838,841],{},[813,836,837],{},"SLSA 3",[813,839,840],{},"Hardened build platform + verifiable provenance",[813,842,843],{},"Tamper prevention",[48,845,847],{"id":846},"container-signing-with-sigstore","Container Signing with Sigstore",[11,849,850,855,856,694,861,700,866,405],{},[15,851,854],{"href":852,"rel":853},"https:\u002F\u002Fwww.sigstore.dev\u002F",[19],"Sigstore"," is open infrastructure for signing and verifying container images. It consists of three components: ",[15,857,860],{"href":858,"rel":859},"https:\u002F\u002Fdocs.sigstore.dev\u002Fcosign\u002Foverview\u002F",[19],"Cosign",[15,862,865],{"href":863,"rel":864},"https:\u002F\u002Fdocs.sigstore.dev\u002Ffulcio\u002Foverview\u002F",[19],"Fulcio",[15,867,870],{"href":868,"rel":869},"https:\u002F\u002Fdocs.sigstore.dev\u002Frekor\u002Foverview\u002F",[19],"Rekor",[53,872,874],{"className":713,"code":873,"language":715,"meta":58,"style":58},"# Sign an image with Cosign (keyless signing)\ncosign sign --yes ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n\n# Verify the signature\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",[60,875,876,881,895,899,904,914,924,940],{"__ignoreMap":58},[63,877,878],{"class":65,"line":66},[63,879,880],{"class":69},"# Sign an image with Cosign (keyless signing)\n",[63,882,883,886,889,892],{"class":65,"line":73},[63,884,885],{"class":727},"cosign",[63,887,888],{"class":97}," sign",[63,890,891],{"class":759}," --yes",[63,893,894],{"class":97}," ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n",[63,896,897],{"class":65,"line":84},[63,898,149],{"emptyLinePlaceholder":148},[63,900,901],{"class":65,"line":101},[63,902,903],{"class":69},"# Verify the signature\n",[63,905,906,908,911],{"class":65,"line":112},[63,907,885],{"class":727},[63,909,910],{"class":97}," verify",[63,912,913],{"class":80}," \\\n",[63,915,916,919,922],{"class":65,"line":120},[63,917,918],{"class":759},"  --certificate-oidc-issuer",[63,920,921],{"class":97}," https:\u002F\u002Ftoken.actions.githubusercontent.com",[63,923,913],{"class":80},[63,925,926,929,932,935,938],{"class":65,"line":134},[63,927,928],{"class":759},"  --certificate-identity-regexp",[63,930,931],{"class":80}," \"",[63,933,934],{"class":97},"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F",[63,936,937],{"class":80},"\"",[63,939,913],{"class":80},[63,941,942],{"class":65,"line":145},[63,943,944],{"class":97},"  ghcr.io\u002Fyour-org\u002Fapp@sha256:abc123\n",[48,946,948],{"id":947},"sbom-software-bill-of-materials-generation","SBOM (Software Bill of Materials) Generation",[53,950,952],{"className":55,"code":951,"language":57,"meta":58,"style":58},"    - 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",[60,953,954,965,974,980,990,999,1009,1013,1024,1033,1039,1049,1059],{"__ignoreMap":58},[63,955,956,958,960,962],{"class":65,"line":66},[63,957,252],{"class":87},[63,959,271],{"class":76},[63,961,94],{"class":80},[63,963,964],{"class":97}," Generate SBOM\n",[63,966,967,969,971],{"class":65,"line":73},[63,968,281],{"class":76},[63,970,94],{"class":80},[63,972,973],{"class":97}," anchore\u002Fsbom-action@v0\n",[63,975,976,978],{"class":65,"line":84},[63,977,389],{"class":76},[63,979,81],{"class":80},[63,981,982,985,987],{"class":65,"line":101},[63,983,984],{"class":76},"        image",[63,986,94],{"class":80},[63,988,989],{"class":97}," ghcr.io\u002Fyour-org\u002Fapp:${{ github.sha }}\n",[63,991,992,994,996],{"class":65,"line":112},[63,993,414],{"class":76},[63,995,94],{"class":80},[63,997,998],{"class":97}," spdx-json\n",[63,1000,1001,1004,1006],{"class":65,"line":120},[63,1002,1003],{"class":76},"        output-file",[63,1005,94],{"class":80},[63,1007,1008],{"class":97}," sbom.spdx.json\n",[63,1010,1011],{"class":65,"line":134},[63,1012,149],{"emptyLinePlaceholder":148},[63,1014,1015,1017,1019,1021],{"class":65,"line":145},[63,1016,252],{"class":87},[63,1018,271],{"class":76},[63,1020,94],{"class":80},[63,1022,1023],{"class":97}," Attest SBOM\n",[63,1025,1026,1028,1030],{"class":65,"line":152},[63,1027,281],{"class":76},[63,1029,94],{"class":80},[63,1031,1032],{"class":97}," actions\u002Fattest-sbom@v1\n",[63,1034,1035,1037],{"class":65,"line":164},[63,1036,389],{"class":76},[63,1038,81],{"class":80},[63,1040,1041,1044,1046],{"class":65,"line":174},[63,1042,1043],{"class":76},"        subject-name",[63,1045,94],{"class":80},[63,1047,1048],{"class":97}," ghcr.io\u002Fyour-org\u002Fapp\n",[63,1050,1051,1054,1056],{"class":65,"line":181},[63,1052,1053],{"class":76},"        subject-digest",[63,1055,94],{"class":80},[63,1057,1058],{"class":97}," sha256:abc123\n",[63,1060,1061,1064,1066],{"class":65,"line":193},[63,1062,1063],{"class":76},"        sbom-path",[63,1065,94],{"class":80},[63,1067,1008],{"class":97},[11,1069,1070,1071,1076],{},"According to the ",[15,1072,1075],{"href":1073,"rel":1074},"https:\u002F\u002Fgithub.blog\u002Fsecurity\u002Fsupply-chain-security\u002Fslsa-3-compliance-with-github-actions\u002F",[19],"GitHub Blog",", SLSA Level 2 can be achieved in hours with GitHub Actions and Sigstore, and Level 3 can be implemented in weeks.",[29,1078,1080],{"id":1079},"policy-as-code-and-guardrails","Policy as Code and Guardrails",[11,1082,1083],{},"Define security policies as code and enforce them automatically across the pipeline.",[48,1085,1087],{"id":1086},"admission-control-with-opagatekeeper","Admission Control with OPA\u002FGatekeeper",[53,1089,1091],{"className":55,"code":1090,"language":57,"meta":58,"style":58},"# Policy to deny privileged containers\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",[60,1092,1093,1098,1108,1118,1125,1135,1142,1149,1156,1174,1192,1199,1206],{"__ignoreMap":58},[63,1094,1095],{"class":65,"line":66},[63,1096,1097],{"class":69},"# Policy to deny privileged containers\n",[63,1099,1100,1103,1105],{"class":65,"line":73},[63,1101,1102],{"class":76},"apiVersion",[63,1104,94],{"class":80},[63,1106,1107],{"class":97}," constraints.gatekeeper.sh\u002Fv1beta1\n",[63,1109,1110,1113,1115],{"class":65,"line":84},[63,1111,1112],{"class":76},"kind",[63,1114,94],{"class":80},[63,1116,1117],{"class":97}," K8sPSPPrivilegedContainer\n",[63,1119,1120,1123],{"class":65,"line":101},[63,1121,1122],{"class":76},"metadata",[63,1124,81],{"class":80},[63,1126,1127,1130,1132],{"class":65,"line":112},[63,1128,1129],{"class":76},"  name",[63,1131,94],{"class":80},[63,1133,1134],{"class":97}," deny-privileged\n",[63,1136,1137,1140],{"class":65,"line":120},[63,1138,1139],{"class":76},"spec",[63,1141,81],{"class":80},[63,1143,1144,1147],{"class":65,"line":134},[63,1145,1146],{"class":76},"  match",[63,1148,81],{"class":80},[63,1150,1151,1154],{"class":65,"line":145},[63,1152,1153],{"class":76},"    kinds",[63,1155,81],{"class":80},[63,1157,1158,1160,1163,1165,1168,1171],{"class":65,"line":152},[63,1159,123],{"class":87},[63,1161,1162],{"class":76}," apiGroups",[63,1164,94],{"class":80},[63,1166,1167],{"class":80}," [",[63,1169,1170],{"class":80},"\"\"",[63,1172,1173],{"class":80},"]\n",[63,1175,1176,1179,1181,1183,1185,1188,1190],{"class":65,"line":164},[63,1177,1178],{"class":76},"        kinds",[63,1180,94],{"class":80},[63,1182,1167],{"class":80},[63,1184,937],{"class":80},[63,1186,1187],{"class":97},"Pod",[63,1189,937],{"class":80},[63,1191,1173],{"class":80},[63,1193,1194,1197],{"class":65,"line":174},[63,1195,1196],{"class":76},"  parameters",[63,1198,81],{"class":80},[63,1200,1201,1204],{"class":65,"line":181},[63,1202,1203],{"class":76},"    exemptImages",[63,1205,81],{"class":80},[63,1207,1208,1210,1212,1215],{"class":65,"line":193},[63,1209,123],{"class":87},[63,1211,931],{"class":80},[63,1213,1214],{"class":97},"istio-proxyv2:*",[63,1216,1217],{"class":80},"\"\n",[48,1219,1221],{"id":1220},"policy-enforcement-with-kyverno","Policy Enforcement with Kyverno",[53,1223,1225],{"className":55,"code":1224,"language":57,"meta":58,"style":58},"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",[60,1226,1227,1236,1245,1251,1260,1266,1276,1283,1294,1301,1308,1318,1325,1333,1340,1350,1362,1369,1378,1387,1401],{"__ignoreMap":58},[63,1228,1229,1231,1233],{"class":65,"line":66},[63,1230,1102],{"class":76},[63,1232,94],{"class":80},[63,1234,1235],{"class":97}," kyverno.io\u002Fv1\n",[63,1237,1238,1240,1242],{"class":65,"line":73},[63,1239,1112],{"class":76},[63,1241,94],{"class":80},[63,1243,1244],{"class":97}," ClusterPolicy\n",[63,1246,1247,1249],{"class":65,"line":84},[63,1248,1122],{"class":76},[63,1250,81],{"class":80},[63,1252,1253,1255,1257],{"class":65,"line":101},[63,1254,1129],{"class":76},[63,1256,94],{"class":80},[63,1258,1259],{"class":97}," require-signed-images\n",[63,1261,1262,1264],{"class":65,"line":112},[63,1263,1139],{"class":76},[63,1265,81],{"class":80},[63,1267,1268,1271,1273],{"class":65,"line":120},[63,1269,1270],{"class":76},"  validationFailureAction",[63,1272,94],{"class":80},[63,1274,1275],{"class":97}," Enforce\n",[63,1277,1278,1281],{"class":65,"line":134},[63,1279,1280],{"class":76},"  rules",[63,1282,81],{"class":80},[63,1284,1285,1287,1289,1291],{"class":65,"line":145},[63,1286,252],{"class":87},[63,1288,271],{"class":76},[63,1290,94],{"class":80},[63,1292,1293],{"class":97}," verify-signature\n",[63,1295,1296,1299],{"class":65,"line":152},[63,1297,1298],{"class":76},"      match",[63,1300,81],{"class":80},[63,1302,1303,1306],{"class":65,"line":164},[63,1304,1305],{"class":76},"        any",[63,1307,81],{"class":80},[63,1309,1310,1313,1316],{"class":65,"line":174},[63,1311,1312],{"class":87},"          -",[63,1314,1315],{"class":76}," resources",[63,1317,81],{"class":80},[63,1319,1320,1323],{"class":65,"line":181},[63,1321,1322],{"class":76},"              kinds",[63,1324,81],{"class":80},[63,1326,1327,1330],{"class":65,"line":193},[63,1328,1329],{"class":87},"                -",[63,1331,1332],{"class":97}," Pod\n",[63,1334,1335,1338],{"class":65,"line":331},[63,1336,1337],{"class":76},"      verifyImages",[63,1339,81],{"class":80},[63,1341,1342,1345,1348],{"class":65,"line":341},[63,1343,1344],{"class":87},"        -",[63,1346,1347],{"class":76}," imageReferences",[63,1349,81],{"class":80},[63,1351,1352,1355,1357,1360],{"class":65,"line":348},[63,1353,1354],{"class":87},"            -",[63,1356,931],{"class":80},[63,1358,1359],{"class":97},"ghcr.io-your-org-*",[63,1361,1217],{"class":80},[63,1363,1364,1367],{"class":65,"line":359},[63,1365,1366],{"class":76},"          attestors",[63,1368,81],{"class":80},[63,1370,1371,1373,1376],{"class":65,"line":364},[63,1372,1354],{"class":87},[63,1374,1375],{"class":76}," entries",[63,1377,81],{"class":80},[63,1379,1380,1382,1385],{"class":65,"line":376},[63,1381,1329],{"class":87},[63,1383,1384],{"class":76}," keyless",[63,1386,81],{"class":80},[63,1388,1389,1392,1394,1396,1399],{"class":65,"line":386},[63,1390,1391],{"class":76},"                    subject",[63,1393,94],{"class":80},[63,1395,931],{"class":80},[63,1397,1398],{"class":97},"https:\u002F\u002Fgithub.com\u002Fyour-org\u002F*",[63,1400,1217],{"class":80},[63,1402,1403,1406,1408,1410,1413],{"class":65,"line":394},[63,1404,1405],{"class":76},"                    issuer",[63,1407,94],{"class":80},[63,1409,931],{"class":80},[63,1411,1412],{"class":97},"https:\u002F\u002Ftoken.actions.githubusercontent.com",[63,1414,1217],{"class":80},[11,1416,1417,1418,1423,1424,1429],{},"Deploy ",[15,1419,1422],{"href":1420,"rel":1421},"https:\u002F\u002Fkyverno.io\u002F",[19],"Kyverno"," and ",[15,1425,1428],{"href":1426,"rel":1427},"https:\u002F\u002Fopen-policy-agent.github.io\u002Fgatekeeper\u002F",[19],"OPA Gatekeeper"," to your Kubernetes cluster to block unsigned images and privileged container deployments.",[48,1431,1433],{"id":1432},"baseline-policy-configuration","Baseline Policy Configuration",[11,1435,1436,1437,1442,1443,1446],{},"As ",[15,1438,1441],{"href":1439,"rel":1440},"https:\u002F\u002Fwww.wiz.io\u002Facademy\u002Fapplication-security\u002Fci-cd-security-best-practices",[19],"Wiz's guide"," recommends, set baseline policies that block ",[37,1444,1445],{},"clearly unacceptable risks"," (actively exploited vulnerabilities, unsigned images, etc.) without overly constraining development velocity.",[29,1448,1450],{"id":1449},"runtime-monitoring-and-feedback-loops","Runtime Monitoring and Feedback Loops",[11,1452,1453],{},"Security monitoring must continue post-deployment.",[48,1455,1457],{"id":1456},"runtime-drift-detection","Runtime Drift Detection",[53,1459,1461],{"className":55,"code":1460,"language":57,"meta":58,"style":58},"# Runtime security monitoring with 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",[60,1462,1463,1468,1481,1491,1502,1507,1516,1521,1526],{"__ignoreMap":58},[63,1464,1465],{"class":65,"line":66},[63,1466,1467],{"class":69},"# Runtime security monitoring with Falco\n",[63,1469,1470,1473,1476,1478],{"class":65,"line":73},[63,1471,1472],{"class":87},"-",[63,1474,1475],{"class":76}," rule",[63,1477,94],{"class":80},[63,1479,1480],{"class":97}," Unexpected Network Connection\n",[63,1482,1483,1486,1488],{"class":65,"line":84},[63,1484,1485],{"class":76},"  desc",[63,1487,94],{"class":80},[63,1489,1490],{"class":97}," Detect network connections to unexpected destinations\n",[63,1492,1493,1496,1498],{"class":65,"line":101},[63,1494,1495],{"class":76},"  condition",[63,1497,94],{"class":80},[63,1499,1501],{"class":1500},"sEsAJ"," >\n",[63,1503,1504],{"class":65,"line":112},[63,1505,1506],{"class":97},"    outbound and not (fd.sip in (allowed_outbound_destinations))\n",[63,1508,1509,1512,1514],{"class":65,"line":120},[63,1510,1511],{"class":76},"  output",[63,1513,94],{"class":80},[63,1515,1501],{"class":1500},[63,1517,1518],{"class":65,"line":134},[63,1519,1520],{"class":97},"    Unexpected outbound connection\n",[63,1522,1523],{"class":65,"line":145},[63,1524,1525],{"class":97},"    (command=%proc.cmdline connection=%fd.name user=%user.name)\n",[63,1527,1528,1531,1533],{"class":65,"line":152},[63,1529,1530],{"class":76},"  priority",[63,1532,94],{"class":80},[63,1534,1535],{"class":97}," WARNING\n",[11,1537,1538,1543],{},[15,1539,1542],{"href":1540,"rel":1541},"https:\u002F\u002Ffalco.org\u002F",[19],"Falco"," is a Kubernetes runtime security monitoring tool that detects unauthorized process execution, network connections, and file access in real time.",[48,1545,1547],{"id":1546},"building-the-feedback-loop","Building the Feedback Loop",[11,1549,1550],{},"Build a cycle that feeds runtime-detected issues back into ci-cd improvements.",[1552,1553,1554,1560,1566,1572,1578],"ol",{},[450,1555,1556,1559],{},[37,1557,1558],{},"Detect",": Falco identifies runtime anomalies",[450,1561,1562,1565],{},[37,1563,1564],{},"Notify",": Send alerts to Slack\u002FPagerDuty",[450,1567,1568,1571],{},[37,1569,1570],{},"Analyze",": Identify root cause as a pipeline gap",[450,1573,1574,1577],{},[37,1575,1576],{},"Fix",": Update policies or scan rules",[450,1579,1580,1583],{},[37,1581,1582],{},"Verify",": Confirm the fix in the next deployment",[11,1585,1586,1589],{},[15,1587,430],{"href":428,"rel":1588},[19]," accelerates this feedback loop with AI, automating the path from detection to remediation recommendations.",[29,1591,1593],{"id":1592},"compliance-and-audit","Compliance and Audit",[48,1595,1597],{"id":1596},"automated-audit-trails","Automated Audit Trails",[11,1599,1600],{},"Each ci-cd pipeline step automatically generates audit evidence, simplifying compliance with major frameworks (SOC 2, ISO 27001, NIST, PCI DSS).",[53,1602,1604],{"className":55,"code":1603,"language":57,"meta":58,"style":58},"    - 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",[60,1605,1606,1617,1626,1632,1640],{"__ignoreMap":58},[63,1607,1608,1610,1612,1614],{"class":65,"line":66},[63,1609,252],{"class":87},[63,1611,271],{"class":76},[63,1613,94],{"class":80},[63,1615,1616],{"class":97}," Generate Attestation\n",[63,1618,1619,1621,1623],{"class":65,"line":73},[63,1620,281],{"class":76},[63,1622,94],{"class":80},[63,1624,1625],{"class":97}," actions\u002Fattest-build-provenance@v1\n",[63,1627,1628,1630],{"class":65,"line":84},[63,1629,389],{"class":76},[63,1631,81],{"class":80},[63,1633,1634,1636,1638],{"class":65,"line":101},[63,1635,1043],{"class":76},[63,1637,94],{"class":80},[63,1639,1048],{"class":97},[63,1641,1642,1644,1646],{"class":65,"line":112},[63,1643,1053],{"class":76},[63,1645,94],{"class":80},[63,1647,1058],{"class":97},[11,1649,1650,1654,1655,1658],{},[15,1651,1653],{"href":780,"rel":1652},[19],"SLSA"," provenance, ",[15,1656,854],{"href":852,"rel":1657},[19]," signing logs (Rekor), and SBOMs serve as compliance evidence.",[29,1660,1662],{"id":1661},"conclusion-achieve-secure-ci-cd-with-kubo","Conclusion: Achieve Secure ci-cd with Kubo",[11,1664,1665],{},"ci-cd pipeline security consists of five layers: Shift-Left, multi-layer testing, supply chain protection, Policy as Code, and runtime monitoring. You don't need to implement everything at once. Start with SAST and container scanning, then gradually increase maturity.",[11,1667,1668,1671,1672,1676,1677,1682],{},[15,1669,26],{"href":24,"rel":1670},[19]," provides a ci-cd foundation with security built in, including container scanning, policy enforcement, and signature verification as standard features. ",[15,1673,1675],{"href":428,"rel":1674},[19],"Captain.AI's"," AI security assistant automates vulnerability prioritization and remediation recommendations, enabling security operations that don't slow development. Ready to build a secure ci-cd pipeline? ",[15,1678,1681],{"href":1679,"rel":1680},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[19],"Contact us"," today.",[1684,1685,1686],"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":58,"searchDepth":73,"depth":73,"links":1688},[1689,1693,1700,1705,1710,1714,1717],{"id":31,"depth":73,"text":32,"children":1690},[1691,1692],{"id":50,"depth":84,"text":51},{"id":212,"depth":84,"text":213},{"id":434,"depth":73,"text":435,"children":1694},[1695,1696,1697,1698,1699],{"id":441,"depth":84,"text":442},{"id":482,"depth":84,"text":483},{"id":574,"depth":84,"text":575},{"id":603,"depth":84,"text":604},{"id":709,"depth":84,"text":710},{"id":773,"depth":73,"text":774,"children":1701},[1702,1703,1704],{"id":786,"depth":84,"text":787},{"id":846,"depth":84,"text":847},{"id":947,"depth":84,"text":948},{"id":1079,"depth":73,"text":1080,"children":1706},[1707,1708,1709],{"id":1086,"depth":84,"text":1087},{"id":1220,"depth":84,"text":1221},{"id":1432,"depth":84,"text":1433},{"id":1449,"depth":73,"text":1450,"children":1711},[1712,1713],{"id":1456,"depth":84,"text":1457},{"id":1546,"depth":84,"text":1547},{"id":1592,"depth":73,"text":1593,"children":1715},[1716],{"id":1596,"depth":84,"text":1597},{"id":1661,"depth":73,"text":1662},"2026-05-27","A practical guide to ci-cd pipeline security from a DevSecOps perspective. Covers SAST\u002FDAST, supply chain protection, the SLSA framework, and Policy as Code.","md","en",{},"\u002Fblog\u002Fen\u002Fcicd-pipeline-security-devsecops",{"title":5,"description":1719},"blog\u002Fen\u002Fcicd-pipeline-security-devsecops",[1727,1728,1729,1730,1653,1731],"DevSecOps","ci-cd","Security","Supply Chain","Kubernetes","WGWtrw1PR2e9Av4DgIJfFztsiGKKzpS9vg9C8w05On8",1779964618722]