[{"data":1,"prerenderedAt":1676},["ShallowReactive",2],{"/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd":3,"navigation-en-us":880,"banner-en-us":1307,"footer-en-us":1317,"blog-post-authors-en-us-João Pereira|Tim Rizzi":1561,"blog-related-posts-en-us-annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd":1589,"blog-promotions-en-us":1614,"next-steps-en-us":1666},{"id":4,"title":5,"authors":6,"body":9,"category":858,"date":859,"description":860,"extension":861,"externalUrl":862,"faq":862,"featured":863,"heroImage":864,"meta":865,"navigation":140,"path":866,"seo":867,"slug":872,"stem":873,"tags":874,"template":878,"updatedDate":862,"__hash__":879},"blogPosts/en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd.md","Annotate container images with build provenance using Cosign in GitLab CI/CD",[7,8],"João Pereira","Tim Rizzi",{"type":10,"value":11,"toc":843},"minimark",[12,16,19,24,34,43,47,56,59,72,81,85,88,91,95,103,511,514,518,523,526,548,552,555,573,576,580,583,625,628,632,635,642,678,681,684,691,694,714,717,721,724,727,741,744,748,751,788,791,794,806,810,839],[13,14,15],"p",{},"Container security has become a critical concern in software development. As organizations increasingly rely on containerized applications, ensuring the integrity and traceability of container images is paramount. Enhancing the security and traceability of your container images directly in your GitLab CI/CD pipeline can streamline your development process while significantly boosting your security posture.",[13,17,18],{},"This tutorial demonstrates setting up a GitLab pipeline to automate the process of building, signing, and annotating Docker images using Cosign and the GitLab container registry. By integrating these practices, you'll secure your images and ensure that each one is easily traceable, aligning with best practices in DevSecOps.",[20,21,23],"h2",{"id":22},"background-on-container-image-security","Background on container image security",[13,25,26,27,33],{},"Before we dive into the technical details, it's crucial to understand why container image security is so important. In ",[28,29,32],"a",{"href":30,"rel":31},"https://about.gitlab.com/topics/microservices/",[],"microservices"," and cloud-native applications, containers have become the standard for packaging and deploying software. However, this widespread adoption has also made containers an attractive target for cyber attacks.",[13,35,36,37,42],{},"Container image security is a vital component of the broader ",[28,38,41],{"href":39,"rel":40},"https://about.gitlab.com/blog/the-ultimate-guide-to-software-supply-chain-security/",[],"software supply chain security"," concept. This encompasses all the tools, processes, and practices that ensure your software's integrity, authenticity, and security from development to deployment. By securing your container images, you're protecting your application and your entire software supply chain.",[20,44,46],{"id":45},"introduction-to-cosign","Introduction to Cosign",[13,48,49,50,55],{},"Enter ",[28,51,54],{"href":52,"rel":53},"https://about.gitlab.com/blog/keyless-signing-with-cosign/",[],"Cosign",", a tool designed to address these security concerns. Cosign is part of the Sigstore project, an open-source initiative aimed at improving the security of the software supply chain. Cosign allows developers to sign and verify container images, ensuring their integrity and authenticity.",[13,57,58],{},"Key benefits of Cosign include:",[60,61,62,66,69],"ul",{},[63,64,65],"li",{},"easy integration with existing CI/CD pipelines",[63,67,68],{},"support for various signing methods, including keyless signing",[63,70,71],{},"ability to attach and verify arbitrary metadata to container images",[13,73,74,75,80],{},"By incorporating Cosign into your GitLab CI/CD pipeline, you're taking a significant step towards robust ",[28,76,79],{"href":77,"rel":78},"https://about.gitlab.com/topics/devsecops/",[],"DevSecOps"," practices.",[20,82,84],{"id":83},"benefits-of-image-signing-and-annotation","Benefits of image signing and annotation",[13,86,87],{},"Image signing serves as a seal of authenticity for your container images. It helps prevent tampering and ensures that the image deployed in your production environment is precisely the one that passed through your secure build process.",[13,89,90],{},"Annotations, on the other hand, provide valuable metadata about the build process. This information is used for auditing and traceability. In a security incident, having detailed provenance data can significantly speed up the investigation and remediation process.",[20,92,94],{"id":93},"gitlab-cicd-pipeline-configuration","GitLab CI/CD pipeline configuration",[13,96,97,98,102],{},"Let's look at an example ",[99,100,101],"code",{},".gitlab-ci.yml"," file that outlines the process of building, signing, and annotating a Docker image using Cosign:",[104,105,110],"pre",{"className":106,"code":107,"language":108,"meta":109,"style":109},"language-yaml shiki shiki-themes github-light","stages:\n  - build\n\nbuild_and_sign:\n  stage: build\n  image: docker:latest\n  services:\n    - docker:dind  # Enable Docker-in-Docker service to allow Docker commands inside the container\n  variables:\n    IMAGE_TAG: $CI_COMMIT_SHORT_SHA  # Use the commit short SHA as the image tag\n    IMAGE_URI: $CI_REGISTRY_IMAGE:$IMAGE_TAG  # Construct the full image URI with the registry, project path, and tag\n    COSIGN_YES: \"true\"  # Automatically confirm actions in Cosign without user interaction\n    FF_SCRIPT_SECTIONS: \"true\"  # Enables GitLab's CI script sections for better multi-line script output\n  id_tokens:\n    SIGSTORE_ID_TOKEN:\n      aud: sigstore  # Provide an OIDC token for keyless signing with Cosign\n  before_script:\n    - apk add --no-cache cosign jq  # Install Cosign (mandatory) and jq (optional)\n    - docker login -u \"gitlab-ci-token\" -p \"$CI_JOB_TOKEN\" \"$CI_REGISTRY\"  # Log in to the Docker registry using GitLab CI token\n  script:\n    # Build the Docker image using the specified tag and push it to the registry\n    - docker build --pull -t \"$IMAGE_URI\" .\n    - docker push \"$IMAGE_URI\"\n\n    # Retrieve the digest of the pushed image to use in the signing step\n    - IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \"$IMAGE_URI\")\n\n    # Sign the image using Cosign with annotations that provide metadata about the build and tag annotation to allow verifying\n    # the tag->digest mapping (https://github.com/sigstore/cosign?tab=readme-ov-file#tag-signing)\n    - |\n      cosign sign \"$IMAGE_DIGEST\" \\\n        --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n        --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n        --annotations \"com.gitlab.ci.pipeline.url=$CI_PIPELINE_URL\" \\\n        --annotations \"com.gitlab.ci.job.id=$CI_JOB_ID\" \\\n        --annotations \"com.gitlab.ci.job.url=$CI_JOB_URL\" \\\n        --annotations \"com.gitlab.ci.commit.sha=$CI_COMMIT_SHA\" \\\n        --annotations \"com.gitlab.ci.commit.ref.name=$CI_COMMIT_REF_NAME\" \\\n        --annotations \"com.gitlab.ci.project.path=$CI_PROJECT_PATH\" \\\n        --annotations \"org.opencontainers.image.source=$CI_PROJECT_URL\" \\\n        --annotations \"org.opencontainers.image.revision=$CI_COMMIT_SHA\" \\\n        --annotations \"tag=$IMAGE_TAG\"\n\n    # Verify the image signature using Cosign to ensure it matches the expected annotations and certificate identity\n    - |\n      cosign verify \\\n        --annotations \"tag=$IMAGE_TAG\" \\\n        --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n        --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n        \"$IMAGE_URI\" | jq .  # Use jq to format the verification output for easier readability\n\n","yaml","",[99,111,112,125,135,142,150,161,172,180,193,201,215,229,243,256,264,272,286,294,305,316,324,330,338,346,351,357,365,370,376,382,391,397,403,409,415,421,427,433,439,445,451,457,463,468,474,481,487,493,499,505],{"__ignoreMap":109},[113,114,117,121],"span",{"class":115,"line":116},"line",1,[113,118,120],{"class":119},"shJU0","stages",[113,122,124],{"class":123},"sgsFI",":\n",[113,126,128,131],{"class":115,"line":127},2,[113,129,130],{"class":123},"  - ",[113,132,134],{"class":133},"sYBdl","build\n",[113,136,138],{"class":115,"line":137},3,[113,139,141],{"emptyLinePlaceholder":140},true,"\n",[113,143,145,148],{"class":115,"line":144},4,[113,146,147],{"class":119},"build_and_sign",[113,149,124],{"class":123},[113,151,153,156,159],{"class":115,"line":152},5,[113,154,155],{"class":119},"  stage",[113,157,158],{"class":123},": ",[113,160,134],{"class":133},[113,162,164,167,169],{"class":115,"line":163},6,[113,165,166],{"class":119},"  image",[113,168,158],{"class":123},[113,170,171],{"class":133},"docker:latest\n",[113,173,175,178],{"class":115,"line":174},7,[113,176,177],{"class":119},"  services",[113,179,124],{"class":123},[113,181,183,186,189],{"class":115,"line":182},8,[113,184,185],{"class":123},"    - ",[113,187,188],{"class":133},"docker:dind",[113,190,192],{"class":191},"sAwPA","  # Enable Docker-in-Docker service to allow Docker commands inside the container\n",[113,194,196,199],{"class":115,"line":195},9,[113,197,198],{"class":119},"  variables",[113,200,124],{"class":123},[113,202,204,207,209,212],{"class":115,"line":203},10,[113,205,206],{"class":119},"    IMAGE_TAG",[113,208,158],{"class":123},[113,210,211],{"class":133},"$CI_COMMIT_SHORT_SHA",[113,213,214],{"class":191},"  # Use the commit short SHA as the image tag\n",[113,216,218,221,223,226],{"class":115,"line":217},11,[113,219,220],{"class":119},"    IMAGE_URI",[113,222,158],{"class":123},[113,224,225],{"class":133},"$CI_REGISTRY_IMAGE:$IMAGE_TAG",[113,227,228],{"class":191},"  # Construct the full image URI with the registry, project path, and tag\n",[113,230,232,235,237,240],{"class":115,"line":231},12,[113,233,234],{"class":119},"    COSIGN_YES",[113,236,158],{"class":123},[113,238,239],{"class":133},"\"true\"",[113,241,242],{"class":191},"  # Automatically confirm actions in Cosign without user interaction\n",[113,244,246,249,251,253],{"class":115,"line":245},13,[113,247,248],{"class":119},"    FF_SCRIPT_SECTIONS",[113,250,158],{"class":123},[113,252,239],{"class":133},[113,254,255],{"class":191},"  # Enables GitLab's CI script sections for better multi-line script output\n",[113,257,259,262],{"class":115,"line":258},14,[113,260,261],{"class":119},"  id_tokens",[113,263,124],{"class":123},[113,265,267,270],{"class":115,"line":266},15,[113,268,269],{"class":119},"    SIGSTORE_ID_TOKEN",[113,271,124],{"class":123},[113,273,275,278,280,283],{"class":115,"line":274},16,[113,276,277],{"class":119},"      aud",[113,279,158],{"class":123},[113,281,282],{"class":133},"sigstore",[113,284,285],{"class":191},"  # Provide an OIDC token for keyless signing with Cosign\n",[113,287,289,292],{"class":115,"line":288},17,[113,290,291],{"class":119},"  before_script",[113,293,124],{"class":123},[113,295,297,299,302],{"class":115,"line":296},18,[113,298,185],{"class":123},[113,300,301],{"class":133},"apk add --no-cache cosign jq",[113,303,304],{"class":191},"  # Install Cosign (mandatory) and jq (optional)\n",[113,306,308,310,313],{"class":115,"line":307},19,[113,309,185],{"class":123},[113,311,312],{"class":133},"docker login -u \"gitlab-ci-token\" -p \"$CI_JOB_TOKEN\" \"$CI_REGISTRY\"",[113,314,315],{"class":191},"  # Log in to the Docker registry using GitLab CI token\n",[113,317,319,322],{"class":115,"line":318},20,[113,320,321],{"class":119},"  script",[113,323,124],{"class":123},[113,325,327],{"class":115,"line":326},21,[113,328,329],{"class":191},"    # Build the Docker image using the specified tag and push it to the registry\n",[113,331,333,335],{"class":115,"line":332},22,[113,334,185],{"class":123},[113,336,337],{"class":133},"docker build --pull -t \"$IMAGE_URI\" .\n",[113,339,341,343],{"class":115,"line":340},23,[113,342,185],{"class":123},[113,344,345],{"class":133},"docker push \"$IMAGE_URI\"\n",[113,347,349],{"class":115,"line":348},24,[113,350,141],{"emptyLinePlaceholder":140},[113,352,354],{"class":115,"line":353},25,[113,355,356],{"class":191},"    # Retrieve the digest of the pushed image to use in the signing step\n",[113,358,360,362],{"class":115,"line":359},26,[113,361,185],{"class":123},[113,363,364],{"class":133},"IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \"$IMAGE_URI\")\n",[113,366,368],{"class":115,"line":367},27,[113,369,141],{"emptyLinePlaceholder":140},[113,371,373],{"class":115,"line":372},28,[113,374,375],{"class":191},"    # Sign the image using Cosign with annotations that provide metadata about the build and tag annotation to allow verifying\n",[113,377,379],{"class":115,"line":378},29,[113,380,381],{"class":191},"    # the tag->digest mapping (https://github.com/sigstore/cosign?tab=readme-ov-file#tag-signing)\n",[113,383,385,387],{"class":115,"line":384},30,[113,386,185],{"class":123},[113,388,390],{"class":389},"sD7c4","|\n",[113,392,394],{"class":115,"line":393},31,[113,395,396],{"class":133},"      cosign sign \"$IMAGE_DIGEST\" \\\n",[113,398,400],{"class":115,"line":399},32,[113,401,402],{"class":133},"        --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n",[113,404,406],{"class":115,"line":405},33,[113,407,408],{"class":133},"        --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n",[113,410,412],{"class":115,"line":411},34,[113,413,414],{"class":133},"        --annotations \"com.gitlab.ci.pipeline.url=$CI_PIPELINE_URL\" \\\n",[113,416,418],{"class":115,"line":417},35,[113,419,420],{"class":133},"        --annotations \"com.gitlab.ci.job.id=$CI_JOB_ID\" \\\n",[113,422,424],{"class":115,"line":423},36,[113,425,426],{"class":133},"        --annotations \"com.gitlab.ci.job.url=$CI_JOB_URL\" \\\n",[113,428,430],{"class":115,"line":429},37,[113,431,432],{"class":133},"        --annotations \"com.gitlab.ci.commit.sha=$CI_COMMIT_SHA\" \\\n",[113,434,436],{"class":115,"line":435},38,[113,437,438],{"class":133},"        --annotations \"com.gitlab.ci.commit.ref.name=$CI_COMMIT_REF_NAME\" \\\n",[113,440,442],{"class":115,"line":441},39,[113,443,444],{"class":133},"        --annotations \"com.gitlab.ci.project.path=$CI_PROJECT_PATH\" \\\n",[113,446,448],{"class":115,"line":447},40,[113,449,450],{"class":133},"        --annotations \"org.opencontainers.image.source=$CI_PROJECT_URL\" \\\n",[113,452,454],{"class":115,"line":453},41,[113,455,456],{"class":133},"        --annotations \"org.opencontainers.image.revision=$CI_COMMIT_SHA\" \\\n",[113,458,460],{"class":115,"line":459},42,[113,461,462],{"class":133},"        --annotations \"tag=$IMAGE_TAG\"\n",[113,464,466],{"class":115,"line":465},43,[113,467,141],{"emptyLinePlaceholder":140},[113,469,471],{"class":115,"line":470},44,[113,472,473],{"class":191},"    # Verify the image signature using Cosign to ensure it matches the expected annotations and certificate identity\n",[113,475,477,479],{"class":115,"line":476},45,[113,478,185],{"class":123},[113,480,390],{"class":389},[113,482,484],{"class":115,"line":483},46,[113,485,486],{"class":133},"      cosign verify \\\n",[113,488,490],{"class":115,"line":489},47,[113,491,492],{"class":133},"        --annotations \"tag=$IMAGE_TAG\" \\\n",[113,494,496],{"class":115,"line":495},48,[113,497,498],{"class":133},"        --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n",[113,500,502],{"class":115,"line":501},49,[113,503,504],{"class":133},"        --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n",[113,506,508],{"class":115,"line":507},50,[113,509,510],{"class":133},"        \"$IMAGE_URI\" | jq .  # Use jq to format the verification output for easier readability\n",[13,512,513],{},"Let's break down this pipeline configuration and understand each part in detail.",[20,515,517],{"id":516},"detailed-explanation-of-the-pipeline","Detailed explanation of the pipeline",[519,520,522],"h3",{"id":521},"_1-setup-and-prerequisites","1. Setup and prerequisites",[13,524,525],{},"The pipeline starts by setting up the necessary environment:",[60,527,528,535,538,541],{},[63,529,530,531,534],{},"It uses the ",[99,532,533],{},"docker:latest"," image and enables Docker-in-Docker service, allowing Docker commands to be run within the CI job.",[63,536,537],{},"It defines variables for the image tag and URI using GitLab CI/CD predefined variables.",[63,539,540],{},"It sets up an OIDC token for keyless signing with Cosign.",[63,542,543,544,547],{},"In the ",[99,545,546],{},"before_script"," section, it installs Cosign and jq (for JSON processing) and logs into the GitLab container registry.",[519,549,551],{"id":550},"_2-building-and-pushing-the-image","2. Building and pushing the image",[13,553,554],{},"The first step in the script is to build the Docker image and push it to the GitLab container registry:",[104,556,558],{"className":106,"code":557,"language":108,"meta":109,"style":109},"- docker build --pull -t \"$IMAGE_URI\" .\n- docker push \"$IMAGE_URI\"\n",[99,559,560,567],{"__ignoreMap":109},[113,561,562,565],{"class":115,"line":116},[113,563,564],{"class":123},"- ",[113,566,337],{"class":133},[113,568,569,571],{"class":115,"line":127},[113,570,564],{"class":123},[113,572,345],{"class":133},[13,574,575],{},"This creates the image using the current directory's Dockerfile and pushes it to the registry.",[519,577,579],{"id":578},"_3-signing-the-image-with-cosign","3. Signing the image with Cosign",[13,581,582],{},"After building and pushing the image, the pipeline signs it using Cosign:",[104,584,586],{"className":106,"code":585,"language":108,"meta":109,"style":109},"- IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' \"$IMAGE_URI\")\n- |\n  cosign sign \"$IMAGE_DIGEST\" \\\n    --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n    --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n    # ... (other annotations) ...\n    --annotations \"tag=$IMAGE_TAG\"\n\n",[99,587,588,594,600,605,610,615,620],{"__ignoreMap":109},[113,589,590,592],{"class":115,"line":116},[113,591,564],{"class":123},[113,593,364],{"class":133},[113,595,596,598],{"class":115,"line":127},[113,597,564],{"class":123},[113,599,390],{"class":389},[113,601,602],{"class":115,"line":137},[113,603,604],{"class":133},"  cosign sign \"$IMAGE_DIGEST\" \\\n",[113,606,607],{"class":115,"line":144},[113,608,609],{"class":133},"    --annotations \"com.gitlab.ci.user.name=$GITLAB_USER_NAME\" \\\n",[113,611,612],{"class":115,"line":152},[113,613,614],{"class":133},"    --annotations \"com.gitlab.ci.pipeline.id=$CI_PIPELINE_ID\" \\\n",[113,616,617],{"class":115,"line":163},[113,618,619],{"class":133},"    # ... (other annotations) ...\n",[113,621,622],{"class":115,"line":174},[113,623,624],{"class":133},"    --annotations \"tag=$IMAGE_TAG\"\n",[13,626,627],{},"This step first retrieves the image digest and then uses Cosign to sign the image, adding several annotations.",[20,629,631],{"id":630},"verifying-the-signature-and-annotations","Verifying the signature and annotations",[13,633,634],{},"After signing the image, it's crucial to verify the signature and the annotations we've added. This verification step ensures that the provenance data attached to the image is correct and hasn't been tampered with.",[13,636,637,638,641],{},"In our pipeline, we've included a verification step using the ",[99,639,640],{},"cosign verify"," command:",[104,643,645],{"className":106,"code":644,"language":108,"meta":109,"style":109},"- |\n  cosign verify \\\n    --annotations \"tag=$IMAGE_TAG\" \\\n    --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n    --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n    \"$IMAGE_URI\" | jq .\n\n",[99,646,647,653,658,663,668,673],{"__ignoreMap":109},[113,648,649,651],{"class":115,"line":116},[113,650,564],{"class":123},[113,652,390],{"class":389},[113,654,655],{"class":115,"line":127},[113,656,657],{"class":133},"  cosign verify \\\n",[113,659,660],{"class":115,"line":137},[113,661,662],{"class":133},"    --annotations \"tag=$IMAGE_TAG\" \\\n",[113,664,665],{"class":115,"line":144},[113,666,667],{"class":133},"    --certificate-identity \"$CI_PROJECT_URL//.gitlab-ci.yml@refs/heads/$CI_COMMIT_REF_NAME\" \\\n",[113,669,670],{"class":115,"line":152},[113,671,672],{"class":133},"    --certificate-oidc-issuer \"$CI_SERVER_URL\" \\\n",[113,674,675],{"class":115,"line":163},[113,676,677],{"class":133},"    \"$IMAGE_URI\" | jq .\n",[13,679,680],{},"This command verifies the signature and checks the annotations. Its output will show all the annotations we've added to the image during the signing process.",[13,682,683],{},"Here's what you might see in your pipeline logs after running this command:",[13,685,686],{},[687,688],"img",{"alt":689,"src":690},"verifying the signature and checking annotations","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098404/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098404260.png",[13,692,693],{},"In this output, you should see all the annotations we added earlier, including:",[60,695,696,699,702,705,708,711],{},[63,697,698],{},"GitLab CI user name",[63,700,701],{},"Pipeline ID and URL",[63,703,704],{},"Job ID and URL",[63,706,707],{},"Commit SHA and reference name",[63,709,710],{},"Project path",[63,712,713],{},"Image source and revision",[13,715,716],{},"By verifying these annotations, you can ensure that the image's provenance data is intact and matches what you expect based on your build process. This verification step is crucial for maintaining the integrity of your software supply chain. It allows you to confirm that the image you're about to deploy has gone through your secure build process and has yet to be modified since it was signed.",[20,718,720],{"id":719},"summary","Summary",[13,722,723],{},"By integrating Cosign into your GitLab CI/CD pipeline, you've taken a significant step toward securing your software supply chain. This setup not only automates securing and annotating your container images with build metadata but also ensures a transparent and traceable build process.",[13,725,726],{},"The benefits of this approach are numerous:",[60,728,729,732,735,738],{},[63,730,731],{},"enhanced security through image signing",[63,733,734],{},"improved traceability with detailed build provenance data",[63,736,737],{},"automated verification process",[63,739,740],{},"alignment with DevSecOps best practices",[13,742,743],{},"As container security continues to be a critical concern in the software development lifecycle, implementing these practices puts you ahead of potential security threats and demonstrates a commitment to software integrity.",[20,745,747],{"id":746},"try-it-in-your-organization","Try it in your organization",[13,749,750],{},"Now that you've seen how to enhance your container security using Cosign in GitLab CI/CD, it's time to put this knowledge into practice:",[752,753,754,764,770,776,782],"ol",{},[63,755,756,760,761,763],{},[757,758,759],"strong",{},"Implement in your projects",": Adapt the provided ",[99,762,101],{}," file to fit your specific needs.",[63,765,766,769],{},[757,767,768],{},"Explore further",": Dive deeper into Cosign's capabilities. Consider exploring advanced features like policy enforcement or integration with vulnerability scanning tools.",[63,771,772,775],{},[757,773,774],{},"Share your experience",": After implementing this in your projects, share your experience with your team or the wider GitLab community. Your insights could help others enhance their security practices.",[63,777,778,781],{},[757,779,780],{},"Stay updated",": Container security is an evolving field. Check GitLab's blog and documentation for new features and best practices updates.",[63,783,784,787],{},[757,785,786],{},"Contribute",": If you find ways to improve this process or encounter any issues, consider contributing to the GitLab or Cosign open-source projects.",[13,789,790],{},"Remember, security is a journey, not a destination. By taking these steps, you're securing your containers and contributing to a more secure software ecosystem for everyone.",[13,792,793],{},"Start implementing these practices in your GitLab projects today, and take your container security to the next level!",[795,796,797],"blockquote",{},[13,798,799,800,805],{},"Get started today! Sign up for a ",[28,801,804],{"href":802,"rel":803},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/blog&glm_content=default-saas-trial",[],"free trial of GitLab Ultimate","!",[20,807,809],{"id":808},"read-more","Read more",[60,811,812,819,826,832],{},[63,813,814],{},[28,815,818],{"href":816,"rel":817},"https://about.gitlab.com/blog/next-generation-gitlab-container-registry-goes-ga/",[],"Next-generation GitLab container registry goes GA",[63,820,821],{},[28,822,825],{"href":823,"rel":824},"https://about.gitlab.com/topics/devsecops/beginners-guide-to-container-security/",[],"A beginner's guide to container security",[63,827,828],{},[28,829,831],{"href":77,"rel":830},[],"DevSecOps basics, including security",[63,833,834],{},[28,835,838],{"href":836,"rel":837},"https://about.gitlab.com/topics/ci-cd/",[],"What is CI/CD?",[840,841,842],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}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);}",{"title":109,"searchDepth":127,"depth":127,"links":844},[845,846,847,848,849,854,855,856,857],{"id":22,"depth":127,"text":23},{"id":45,"depth":127,"text":46},{"id":83,"depth":127,"text":84},{"id":93,"depth":127,"text":94},{"id":516,"depth":127,"text":517,"children":850},[851,852,853],{"id":521,"depth":137,"text":522},{"id":550,"depth":137,"text":551},{"id":578,"depth":137,"text":579},{"id":630,"depth":127,"text":631},{"id":719,"depth":127,"text":720},{"id":746,"depth":127,"text":747},{"id":808,"depth":127,"text":809},"security","2024-09-04","Use GitLab pipelines to automate building, signing, and annotating Docker images. This tutorial shares code to show you how. Try it out in your own organization.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098395/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2823%29_2w6waL76KROjhJHM2vXet6_1750098395162.png",{},"/en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd",{"title":868,"description":860,"ogTitle":868,"ogDescription":860,"noIndex":863,"ogImage":864,"ogUrl":869,"ogSiteName":870,"ogType":871,"canonicalUrls":869},"Container image provenance with Cosign in GitLab CI/CD","https://about.gitlab.com/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd","https://about.gitlab.com","article","annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd","en-us/blog/annotate-container-images-with-build-provenance-using-cosign-in-gitlab-ci-cd",[858,875,876,877],"tutorial","product","features","BlogPost","2LWANCJS_SOVECMdgqDpXR0cAIGUPoKE8Cb-Q4blG3o",{"logo":881,"freeTrial":886,"sales":891,"login":896,"items":901,"search":1227,"minimal":1258,"duo":1277,"switchNav":1286,"pricingDeployment":1297},{"config":882},{"href":883,"dataGaName":884,"dataGaLocation":885},"/","gitlab logo","header",{"text":887,"config":888},"Get free trial",{"href":889,"dataGaName":890,"dataGaLocation":885},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":892,"config":893},"Request a demo",{"href":894,"dataGaName":895,"dataGaLocation":885},"/sales/?contact-topic=request-demo","sales",{"text":897,"config":898},"Sign in",{"href":899,"dataGaName":900,"dataGaLocation":885},"https://gitlab.com/users/sign_in/","sign in",[902,931,1031,1036,1149,1205],{"text":903,"config":904,"menu":906},"Platform",{"dataNavLevelOne":905},"platform",{"type":907,"columns":908},"cards",[909,915,923],{"title":903,"description":910,"link":911},"The intelligent orchestration platform for DevSecOps",{"text":912,"config":913},"Explore our Platform",{"href":914,"dataGaName":905,"dataGaLocation":885},"/platform/",{"title":916,"description":917,"link":918},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":919,"config":920},"Meet GitLab Duo",{"href":921,"dataGaName":922,"dataGaLocation":885},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":924,"description":925,"link":926},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":927,"config":928},"Learn more",{"href":929,"dataGaName":930,"dataGaLocation":885},"/why-gitlab/","why gitlab",{"text":932,"left":140,"config":933,"menu":935},"Product",{"dataNavLevelOne":934},"solutions",{"type":936,"link":937,"columns":941,"feature":1010},"lists",{"text":938,"config":939},"View all Solutions",{"href":940,"dataGaName":934,"dataGaLocation":885},"/solutions/",[942,966,989],{"title":943,"description":944,"link":945,"items":950},"Automation","CI/CD and automation to accelerate deployment",{"config":946},{"icon":947,"href":948,"dataGaName":949,"dataGaLocation":885},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[951,955,958,962],{"text":952,"config":953},"CI/CD",{"href":954,"dataGaLocation":885,"dataGaName":952},"/solutions/continuous-integration/",{"text":916,"config":956},{"href":921,"dataGaLocation":885,"dataGaName":957},"gitlab duo agent platform - product menu",{"text":959,"config":960},"Source Code Management",{"href":961,"dataGaLocation":885,"dataGaName":959},"/solutions/source-code-management/",{"text":963,"config":964},"Automated Software Delivery",{"href":948,"dataGaLocation":885,"dataGaName":965},"Automated software delivery",{"title":967,"description":968,"link":969,"items":974},"Security","Deliver code faster without compromising security",{"config":970},{"href":971,"dataGaName":972,"dataGaLocation":885,"icon":973},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[975,979,984],{"text":976,"config":977},"Application Security Testing",{"href":971,"dataGaName":978,"dataGaLocation":885},"Application security testing",{"text":980,"config":981},"Software Supply Chain Security",{"href":982,"dataGaLocation":885,"dataGaName":983},"/solutions/supply-chain/","Software supply chain security",{"text":985,"config":986},"Software Compliance",{"href":987,"dataGaName":988,"dataGaLocation":885},"/solutions/software-compliance/","software compliance",{"title":990,"link":991,"items":996},"Measurement",{"config":992},{"icon":993,"href":994,"dataGaName":995,"dataGaLocation":885},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[997,1001,1005],{"text":998,"config":999},"Visibility & Measurement",{"href":994,"dataGaLocation":885,"dataGaName":1000},"Visibility and Measurement",{"text":1002,"config":1003},"Value Stream Management",{"href":1004,"dataGaLocation":885,"dataGaName":1002},"/solutions/value-stream-management/",{"text":1006,"config":1007},"Analytics & Insights",{"href":1008,"dataGaLocation":885,"dataGaName":1009},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1011,"type":936,"items":1012},"GitLab for",[1013,1019,1025],{"text":1014,"config":1015},"Enterprise",{"icon":1016,"href":1017,"dataGaLocation":885,"dataGaName":1018},"Building","/enterprise/","enterprise",{"text":1020,"config":1021},"Small Business",{"icon":1022,"href":1023,"dataGaLocation":885,"dataGaName":1024},"Work","/small-business/","small business",{"text":1026,"config":1027},"Public Sector",{"icon":1028,"href":1029,"dataGaLocation":885,"dataGaName":1030},"Organization","/solutions/public-sector/","public sector",{"text":1032,"config":1033},"Pricing",{"href":1034,"dataGaName":1035,"dataGaLocation":885,"dataNavLevelOne":1035},"/pricing/","pricing",{"text":1037,"config":1038,"menu":1040},"Resources",{"dataNavLevelOne":1039},"resources",{"type":936,"link":1041,"columns":1045,"feature":1138},{"text":1042,"config":1043},"View all resources",{"href":1044,"dataGaName":1039,"dataGaLocation":885},"/resources/",[1046,1079,1106],{"title":1047,"items":1048},"Getting started",[1049,1054,1059,1064,1069,1074],{"text":1050,"config":1051},"Install",{"href":1052,"dataGaName":1053,"dataGaLocation":885},"/install/","install",{"text":1055,"config":1056},"Quick start guides",{"href":1057,"dataGaName":1058,"dataGaLocation":885},"/get-started/","quick setup checklists",{"text":1060,"config":1061},"Learn",{"href":1062,"dataGaLocation":885,"dataGaName":1063},"https://university.gitlab.com/","learn",{"text":1065,"config":1066},"Product documentation",{"href":1067,"dataGaName":1068,"dataGaLocation":885},"https://docs.gitlab.com/","product documentation",{"text":1070,"config":1071},"Best practice videos",{"href":1072,"dataGaName":1073,"dataGaLocation":885},"/getting-started-videos/","best practice videos",{"text":1075,"config":1076},"Integrations",{"href":1077,"dataGaName":1078,"dataGaLocation":885},"/integrations/","integrations",{"title":1080,"items":1081},"Discover",[1082,1087,1092,1097,1101],{"text":1083,"config":1084},"Customer success stories",{"href":1085,"dataGaName":1086,"dataGaLocation":885},"/customers/","customer success stories",{"text":1088,"config":1089},"Blog",{"href":1090,"dataGaName":1091,"dataGaLocation":885},"/blog/","blog",{"text":1093,"config":1094},"Demo Hub",{"href":1095,"dataGaName":1096,"dataGaLocation":885},"/demo-hub/","demo hub",{"text":1098,"config":1099},"The Source",{"href":1100,"dataGaName":1091,"dataGaLocation":885},"/the-source/",{"text":1102,"config":1103},"Remote",{"href":1104,"dataGaName":1105,"dataGaLocation":885},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1107,"items":1108},"Connect",[1109,1114,1118,1123,1128,1133],{"text":1110,"config":1111},"GitLab Services",{"href":1112,"dataGaName":1113,"dataGaLocation":885},"/services/","services",{"text":786,"config":1115},{"href":1116,"dataGaName":1117,"dataGaLocation":885},"https://contributors.gitlab.com","contribute",{"text":1119,"config":1120},"Community",{"href":1121,"dataGaName":1122,"dataGaLocation":885},"/community/","community",{"text":1124,"config":1125},"Forum",{"href":1126,"dataGaName":1127,"dataGaLocation":885},"https://forum.gitlab.com/","forum",{"text":1129,"config":1130},"Events",{"href":1131,"dataGaName":1132,"dataGaLocation":885},"/events/","events",{"text":1134,"config":1135},"Partners",{"href":1136,"dataGaName":1137,"dataGaLocation":885},"/partners/","partners",{"config":1139,"title":1142,"text":1143,"link":1144},{"background":1140,"textColor":1141},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1145,"config":1146},"Read the latest",{"href":1147,"dataGaName":1148,"dataGaLocation":885},"/whats-new/","whats new",{"text":1150,"config":1151,"menu":1153},"Company",{"dataNavLevelOne":1152},"company",{"type":936,"columns":1154},[1155],{"items":1156},[1157,1162,1168,1170,1175,1180,1185,1190,1195,1200],{"text":1158,"config":1159},"About",{"href":1160,"dataGaName":1161,"dataGaLocation":885},"/company/","about",{"text":1163,"config":1164,"footerGa":1167},"Jobs",{"href":1165,"dataGaName":1166,"dataGaLocation":885},"/jobs/","jobs",{"dataGaName":1166},{"text":1129,"config":1169},{"href":1131,"dataGaName":1132,"dataGaLocation":885},{"text":1171,"config":1172},"Leadership",{"href":1173,"dataGaName":1174,"dataGaLocation":885},"/company/team/e-group/","leadership",{"text":1176,"config":1177},"Handbook",{"href":1178,"dataGaName":1179,"dataGaLocation":885},"https://handbook.gitlab.com/","handbook",{"text":1181,"config":1182},"Investor relations",{"href":1183,"dataGaName":1184,"dataGaLocation":885},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1186,"config":1187},"Trust Center",{"href":1188,"dataGaName":1189,"dataGaLocation":885},"/security/","trust center",{"text":1191,"config":1192},"AI Transparency Center",{"href":1193,"dataGaName":1194,"dataGaLocation":885},"/ai-transparency-center/","ai transparency center",{"text":1196,"config":1197},"Newsletter",{"href":1198,"dataGaName":1199,"dataGaLocation":885},"/company/contact/#contact-forms","newsletter",{"text":1201,"config":1202},"Press",{"href":1203,"dataGaName":1204,"dataGaLocation":885},"/press/","press",{"text":1206,"config":1207,"menu":1208},"Contact us",{"dataNavLevelOne":1152},{"type":936,"columns":1209},[1210],{"items":1211},[1212,1217,1222],{"text":1213,"config":1214},"Talk to sales",{"href":1215,"dataGaName":1216,"dataGaLocation":885},"/sales/","talk to sales",{"text":1218,"config":1219},"Support portal",{"href":1220,"dataGaName":1221,"dataGaLocation":885},"https://support.gitlab.com/hc/en-us","support portal",{"text":1223,"config":1224},"Customer portal",{"href":1225,"dataGaName":1226,"dataGaLocation":885},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1228,"login":1229,"suggestions":1236},"Close",{"text":1230,"link":1231},"To search repositories and projects, login to",{"text":1232,"config":1233},"gitlab.com",{"href":899,"dataGaName":1234,"dataGaLocation":1235},"search login","search",{"text":1237,"default":1238},"Suggestions",[1239,1241,1245,1247,1251,1255],{"text":916,"config":1240},{"href":921,"dataGaName":916,"dataGaLocation":1235},{"text":1242,"config":1243},"Code Suggestions (AI)",{"href":1244,"dataGaName":1242,"dataGaLocation":1235},"/solutions/code-suggestions/",{"text":952,"config":1246},{"href":954,"dataGaName":952,"dataGaLocation":1235},{"text":1248,"config":1249},"GitLab on AWS",{"href":1250,"dataGaName":1248,"dataGaLocation":1235},"/partners/technology-partners/aws/",{"text":1252,"config":1253},"GitLab on Google Cloud",{"href":1254,"dataGaName":1252,"dataGaLocation":1235},"/partners/technology-partners/google-cloud-platform/",{"text":1256,"config":1257},"Why GitLab?",{"href":929,"dataGaName":1256,"dataGaLocation":1235},{"freeTrial":1259,"mobileIcon":1264,"desktopIcon":1269,"secondaryButton":1272},{"text":1260,"config":1261},"Start free trial",{"href":1262,"dataGaName":890,"dataGaLocation":1263},"https://gitlab.com/-/trials/new/","nav",{"altText":1265,"config":1266},"Gitlab Icon",{"src":1267,"dataGaName":1268,"dataGaLocation":1263},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1265,"config":1270},{"src":1271,"dataGaName":1268,"dataGaLocation":1263},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1273,"config":1274},"Get Started",{"href":1275,"dataGaName":1276,"dataGaLocation":1263},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1278,"mobileIcon":1282,"desktopIcon":1284},{"text":1279,"config":1280},"Learn more about GitLab Duo",{"href":921,"dataGaName":1281,"dataGaLocation":1263},"gitlab duo",{"altText":1265,"config":1283},{"src":1267,"dataGaName":1268,"dataGaLocation":1263},{"altText":1265,"config":1285},{"src":1271,"dataGaName":1268,"dataGaLocation":1263},{"button":1287,"mobileIcon":1292,"desktopIcon":1294},{"text":1288,"config":1289},"/switch",{"href":1290,"dataGaName":1291,"dataGaLocation":1263},"#contact","switch",{"altText":1265,"config":1293},{"src":1267,"dataGaName":1268,"dataGaLocation":1263},{"altText":1265,"config":1295},{"src":1296,"dataGaName":1268,"dataGaLocation":1263},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1298,"mobileIcon":1303,"desktopIcon":1305},{"text":1299,"config":1300},"Back to pricing",{"href":1034,"dataGaName":1301,"dataGaLocation":1263,"icon":1302},"back to pricing","GoBack",{"altText":1265,"config":1304},{"src":1267,"dataGaName":1268,"dataGaLocation":1263},{"altText":1265,"config":1306},{"src":1271,"dataGaName":1268,"dataGaLocation":1263},{"title":1308,"titleMobile":1309,"button":1310,"config":1315},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":927,"config":1311},{"href":1312,"dataGaName":1313,"dataGaLocation":1314},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1316,"disabled":863},"release",{"data":1318},{"text":1319,"source":1320,"edit":1326,"contribute":1331,"config":1336,"items":1341,"minimal":1550},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1321,"config":1322},"View page source",{"href":1323,"dataGaName":1324,"dataGaLocation":1325},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1327,"config":1328},"Edit this page",{"href":1329,"dataGaName":1330,"dataGaLocation":1325},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1332,"config":1333},"Please contribute",{"href":1334,"dataGaName":1335,"dataGaLocation":1325},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1337,"facebook":1338,"youtube":1339,"linkedin":1340},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1342,1389,1442,1486,1518],{"title":1032,"links":1343,"subMenu":1358},[1344,1348,1353],{"text":1345,"config":1346},"View plans",{"href":1034,"dataGaName":1347,"dataGaLocation":1325},"view plans",{"text":1349,"config":1350},"Why Premium?",{"href":1351,"dataGaName":1352,"dataGaLocation":1325},"/pricing/premium/","why premium",{"text":1354,"config":1355},"Why Ultimate?",{"href":1356,"dataGaName":1357,"dataGaLocation":1325},"/pricing/ultimate/","why ultimate",[1359],{"title":1360,"links":1361},"Contact Us",[1362,1365,1367,1369,1374,1379,1384],{"text":1363,"config":1364},"Contact sales",{"href":1215,"dataGaName":895,"dataGaLocation":1325},{"text":1218,"config":1366},{"href":1220,"dataGaName":1221,"dataGaLocation":1325},{"text":1223,"config":1368},{"href":1225,"dataGaName":1226,"dataGaLocation":1325},{"text":1370,"config":1371},"Status",{"href":1372,"dataGaName":1373,"dataGaLocation":1325},"https://status.gitlab.com/","status",{"text":1375,"config":1376},"Terms of use",{"href":1377,"dataGaName":1378,"dataGaLocation":1325},"/terms/","terms of use",{"text":1380,"config":1381},"Privacy statement",{"href":1382,"dataGaName":1383,"dataGaLocation":1325},"/privacy/","privacy statement",{"text":1385,"config":1386},"Cookie preferences",{"dataGaName":1387,"dataGaLocation":1325,"id":1388,"isOneTrustButton":140},"cookie preferences","ot-sdk-btn",{"title":932,"links":1390,"subMenu":1399},[1391,1395],{"text":1392,"config":1393},"DevSecOps platform",{"href":914,"dataGaName":1394,"dataGaLocation":1325},"devsecops platform",{"text":1396,"config":1397},"AI-Assisted Development",{"href":921,"dataGaName":1398,"dataGaLocation":1325},"ai-assisted development",[1400],{"title":1401,"links":1402},"Topics",[1403,1408,1413,1418,1423,1427,1432,1437],{"text":1404,"config":1405},"CICD",{"href":1406,"dataGaName":1407,"dataGaLocation":1325},"/topics/ci-cd/","cicd",{"text":1409,"config":1410},"GitOps",{"href":1411,"dataGaName":1412,"dataGaLocation":1325},"/topics/gitops/","gitops",{"text":1414,"config":1415},"DevOps",{"href":1416,"dataGaName":1417,"dataGaLocation":1325},"/topics/devops/","devops",{"text":1419,"config":1420},"Version Control",{"href":1421,"dataGaName":1422,"dataGaLocation":1325},"/topics/version-control/","version control",{"text":79,"config":1424},{"href":1425,"dataGaName":1426,"dataGaLocation":1325},"/topics/devsecops/","devsecops",{"text":1428,"config":1429},"Cloud Native",{"href":1430,"dataGaName":1431,"dataGaLocation":1325},"/topics/cloud-native/","cloud native",{"text":1433,"config":1434},"AI for Coding",{"href":1435,"dataGaName":1436,"dataGaLocation":1325},"/topics/devops/ai-for-coding/","ai for coding",{"text":1438,"config":1439},"Agentic AI",{"href":1440,"dataGaName":1441,"dataGaLocation":1325},"/topics/agentic-ai/","agentic ai",{"title":1443,"links":1444},"Solutions",[1445,1447,1449,1454,1458,1461,1465,1468,1470,1473,1476,1481],{"text":976,"config":1446},{"href":971,"dataGaName":976,"dataGaLocation":1325},{"text":965,"config":1448},{"href":948,"dataGaName":949,"dataGaLocation":1325},{"text":1450,"config":1451},"Agile development",{"href":1452,"dataGaName":1453,"dataGaLocation":1325},"/solutions/agile-delivery/","agile delivery",{"text":1455,"config":1456},"SCM",{"href":961,"dataGaName":1457,"dataGaLocation":1325},"source code management",{"text":1404,"config":1459},{"href":954,"dataGaName":1460,"dataGaLocation":1325},"continuous integration & delivery",{"text":1462,"config":1463},"Value stream management",{"href":1004,"dataGaName":1464,"dataGaLocation":1325},"value stream management",{"text":1409,"config":1466},{"href":1467,"dataGaName":1412,"dataGaLocation":1325},"/solutions/gitops/",{"text":1014,"config":1469},{"href":1017,"dataGaName":1018,"dataGaLocation":1325},{"text":1471,"config":1472},"Small business",{"href":1023,"dataGaName":1024,"dataGaLocation":1325},{"text":1474,"config":1475},"Public sector",{"href":1029,"dataGaName":1030,"dataGaLocation":1325},{"text":1477,"config":1478},"Education",{"href":1479,"dataGaName":1480,"dataGaLocation":1325},"/solutions/education/","education",{"text":1482,"config":1483},"Financial services",{"href":1484,"dataGaName":1485,"dataGaLocation":1325},"/solutions/finance/","financial services",{"title":1037,"links":1487},[1488,1490,1492,1494,1497,1499,1502,1504,1506,1508,1510,1512,1514,1516],{"text":1050,"config":1489},{"href":1052,"dataGaName":1053,"dataGaLocation":1325},{"text":1055,"config":1491},{"href":1057,"dataGaName":1058,"dataGaLocation":1325},{"text":1060,"config":1493},{"href":1062,"dataGaName":1063,"dataGaLocation":1325},{"text":1065,"config":1495},{"href":1067,"dataGaName":1496,"dataGaLocation":1325},"docs",{"text":1088,"config":1498},{"href":1090,"dataGaName":1091,"dataGaLocation":1325},{"text":1500,"config":1501},"What's new",{"href":1147,"dataGaName":1148,"dataGaLocation":1325},{"text":1083,"config":1503},{"href":1085,"dataGaName":1086,"dataGaLocation":1325},{"text":1102,"config":1505},{"href":1104,"dataGaName":1105,"dataGaLocation":1325},{"text":1110,"config":1507},{"href":1112,"dataGaName":1113,"dataGaLocation":1325},{"text":786,"config":1509},{"href":1116,"dataGaName":1117,"dataGaLocation":1325},{"text":1119,"config":1511},{"href":1121,"dataGaName":1122,"dataGaLocation":1325},{"text":1124,"config":1513},{"href":1126,"dataGaName":1127,"dataGaLocation":1325},{"text":1129,"config":1515},{"href":1131,"dataGaName":1132,"dataGaLocation":1325},{"text":1134,"config":1517},{"href":1136,"dataGaName":1137,"dataGaLocation":1325},{"title":1150,"links":1519},[1520,1522,1524,1526,1528,1530,1534,1539,1541,1543,1545],{"text":1158,"config":1521},{"href":1160,"dataGaName":1152,"dataGaLocation":1325},{"text":1163,"config":1523},{"href":1165,"dataGaName":1166,"dataGaLocation":1325},{"text":1171,"config":1525},{"href":1173,"dataGaName":1174,"dataGaLocation":1325},{"text":1176,"config":1527},{"href":1178,"dataGaName":1179,"dataGaLocation":1325},{"text":1181,"config":1529},{"href":1183,"dataGaName":1184,"dataGaLocation":1325},{"text":1531,"config":1532},"Sustainability",{"href":1533,"dataGaName":1531,"dataGaLocation":1325},"/sustainability/",{"text":1535,"config":1536},"Diversity, inclusion and belonging (DIB)",{"href":1537,"dataGaName":1538,"dataGaLocation":1325},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1186,"config":1540},{"href":1188,"dataGaName":1189,"dataGaLocation":1325},{"text":1196,"config":1542},{"href":1198,"dataGaName":1199,"dataGaLocation":1325},{"text":1201,"config":1544},{"href":1203,"dataGaName":1204,"dataGaLocation":1325},{"text":1546,"config":1547},"Modern Slavery Transparency Statement",{"href":1548,"dataGaName":1549,"dataGaLocation":1325},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1551},[1552,1555,1558],{"text":1553,"config":1554},"Terms",{"href":1377,"dataGaName":1378,"dataGaLocation":1325},{"text":1556,"config":1557},"Cookies",{"dataGaName":1387,"dataGaLocation":1325,"id":1388,"isOneTrustButton":140},{"text":1559,"config":1560},"Privacy",{"href":1382,"dataGaName":1383,"dataGaLocation":1325},[1562,1577],{"id":1563,"title":1564,"body":862,"config":1565,"content":1567,"description":862,"extension":1571,"meta":1572,"navigation":140,"path":1573,"seo":1574,"stem":1575,"__hash__":1576},"blogAuthors/en-us/blog/authors/joo-pereira.yml","Joo Pereira",{"template":1566},"BlogAuthor",{"name":7,"config":1568},{"headshot":1569,"ctfId":1570},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665547/Blog/Author%20Headshots/joao_pereira.png","7wLh5rwID5R39PRA6aiAb0","yml",{},"/en-us/blog/authors/joo-pereira",{},"en-us/blog/authors/joo-pereira","Es0uVQmP666TPLDCygzdThz9kJqj0uzVe55c0M7j2Kc",{"id":1578,"title":8,"body":862,"config":1579,"content":1580,"description":862,"extension":1571,"meta":1584,"navigation":140,"path":1585,"seo":1586,"stem":1587,"__hash__":1588},"blogAuthors/en-us/blog/authors/tim-rizzi.yml",{"template":1566},{"name":8,"config":1581},{"headshot":1582,"ctfId":1583},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661866/Blog/Author%20Headshots/trizzi-headshot.jpg","trizzi",{},"/en-us/blog/authors/tim-rizzi",{},"en-us/blog/authors/tim-rizzi","ADPqrpcnKveFJS0m_zFV0VLtb_h_txu59QVgz_YwKMc",[1590,1598,1606],{"title":1591,"description":1592,"heroImage":1593,"category":858,"date":1594,"authors":1595,"slug":1597,"externalUrl":862},"How GitLab tracks vulnerabilities through refactors and reformatting","Learn how GitLab's improved Scope+Offset fingerprinting keeps vulnerability tracking stable across comments, blank lines, and reformatting.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1759320418/xjmqcozxzt4frx0hori3.png","2026-08-12",[1596],"Julian Thome","improved-scope-offset-fingerprinting",{"title":1599,"description":1600,"heroImage":1593,"category":858,"date":1601,"authors":1602,"slug":1605,"externalUrl":862},"GitLab Secrets Manager adds ESO, Terraform, API support","Simplify credential management across your stack. GitLab Secrets Manager provides secure retrieval in Kubernetes, Terraform, and external workflows.","2026-08-06",[1603,1604],"Erick Bajao","Joe Randazzo","gitlab-secrets-manager-add-eso-terraform-api-support",{"title":1607,"description":1608,"heroImage":1609,"category":858,"date":1610,"authors":1611,"slug":1613,"externalUrl":862},"Secure every commit to production with Claude and GitLab","Claude Security catches vulnerabilities inside a coding session. GitLab picks up from there, scanning, enforcing policy, and producing audit evidence for the software lifecycle. ","https://res.cloudinary.com/about-gitlab-com/image/upload/v1756122536/akivvcnafog9c4dhhzkp.png","2026-08-03",[1612],"Alisa Ho","claude-security-and-gitlab",{"promotions":1615},[1616,1630,1641,1652],{"id":1617,"categories":1618,"header":1620,"text":1621,"button":1622,"image":1627},"ai-modernization",[1619],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1623,"config":1624},"Get your AI maturity score",{"href":1625,"dataGaName":1626,"dataGaLocation":1091},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1628},{"src":1629},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1631,"categories":1632,"header":1633,"text":1621,"button":1634,"image":1638},"devops-modernization",[876,1426],"Are you just managing tools or shipping innovation?",{"text":1635,"config":1636},"Get your DevOps maturity score",{"href":1637,"dataGaName":1626,"dataGaLocation":1091},"/assessments/devops-modernization-assessment/",{"config":1639},{"src":1640},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1642,"categories":1643,"header":1644,"text":1621,"button":1645,"image":1649},"security-modernization",[858],"Are you trading speed for security?",{"text":1646,"config":1647},"Get your security maturity score",{"href":1648,"dataGaName":1626,"dataGaLocation":1091},"/assessments/security-modernization-assessment/",{"config":1650},{"src":1651},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1653,"paths":1654,"header":1657,"text":1658,"button":1659,"image":1664},"github-azure-migration",[1655,1656],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1660,"config":1661},"See how GitLab compares to GitHub",{"href":1662,"dataGaName":1663,"dataGaLocation":1091},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1665},{"src":1640},{"header":1667,"blurb":1668,"button":1669,"secondaryButton":1674},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1670,"config":1671},"Get your free trial",{"href":1672,"dataGaName":890,"dataGaLocation":1673},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1363,"config":1675},{"href":1215,"dataGaName":895,"dataGaLocation":1673},1786803742178]