[{"data":1,"prerenderedAt":757},["ShallowReactive",2],{"/en-us/blog/threat-modeling-kubernetes-agent":3,"navigation-en-us":33,"banner-en-us":461,"footer-en-us":478,"Vitor Meireles De Sousa":723,"next-steps-en-us":736,"footer-source-/en-us/blog/threat-modeling-kubernetes-agent/":751},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":23,"_id":26,"_type":27,"title":28,"_source":29,"_file":30,"_stem":31,"_extension":32},"/en-us/blog/threat-modeling-kubernetes-agent","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Threat modeling the Kubernetes Agent: from MVC to continuous improvement","Learn how we put our threat model into action iteratively and expanded the\nprocess into a full-fledged standalone activity.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682156/Blog/Hero%20Images/pexels-jesus-miron-garcia-3043592.jpg","https://about.gitlab.com/blog/threat-modeling-kubernetes-agent","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Threat modeling the Kubernetes Agent: from MVC to continuous improvement\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Vitor Meireles De Sousa\"}],\n        \"datePublished\": \"2021-10-11\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Vitor Meireles De Sousa","2021-10-11","Threat modeling is more common in people’s everyday lives than they might\nthink.  Each of us performs some level of threat modeling every time we’re\nin a situation where we’re evaluating threats. An everyday example I really\nlike: crossing the street. Before we cross the street we look both ways, we\nevaluate the speed of each oncoming vehicle and verify the driver has seen\nus. Finally, if the lights are green, we cross the street. This is threat\nmodeling!\n\n\n_If you’re interested in learning more about what threat modeling is and how\nwe’re developing our threat model here at GitLab, you can read about [“How\nwe’re creating a threat model framework that works for\nGitLab“](/blog/creating-a-threat-model-that-works-for-gitlab/) by\nmy teammate [Mark Loveless](/company/team/#mloveless)._\n\n\n## Threat modeling IRL\n\n\nIn this blog post I’ll talk about how we put our threat modeling process\ninto action iteratively with an in-depth look into how we developed the\nprocess from a security assessment with a side of threat modeling to a\nfull-fledged standalone activity.\n\n\n### Our threat modeling MVC\n\n\nWe rolled out the initial iteration of the GitLab threat model in November\nof 2020. One of the first projects we assessed through that new process was\nGitLab’s [Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/)\nbeta. At that time, my colleague [Joern\nSchneeweisz](/company/team/#joernchen) performed an initial threat model,\nwhich was actually more of a security assessment in which threat modeling\nactivities were incorporated. In this [data flow\ndiagram](https://handbook.gitlab.com/handbook/security/product-security/application-security/threat-modeling/howto/#tools-and) from our\ninitial threat model, you can see how the [architecture for the Kubernetes\nAgent looked in May\n2020](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/f374356751aec8cb65b9dea4de3ba618805c2414/docs/architecture.md):\n\n\n```mermaid\n\ngraph TB\n  agentk -- gRPC bidirectional streaming --> kgb\n\n  subgraph \"GitLab\"\n  kgb[kgb]\n  GitLabRoR[GitLab RoR] -- gRPC --> kgb\n  kgb -- gRPC --> Gitaly[Gitaly]\n  kgb -- REST API --> GitLabRoR\n  end\n\n  subgraph \"Kubernetes cluster\"\n  agentk[agentk]\n  end\n```\n\n\nThis first review, despite our threat model being early stage, still allowed\nus to identify issues and findings (like the Agent exposing public projects\nwith private repositories [(fixed with this merge\nrequest)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48314) or\nthe Agent name being vulnerable to path traversal attacks [(fixed with this\nmerge\nrequest)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37564)) that\nbenefited our security and the broader engineering teams. Plus, the\ncross-organizational feedback we received during this iteration was key to\nimproving our threat model integration and templates.\n\n\n### Increasing capabilities expand the threats\n\n\nFour months had passed since the initial assessment; it was time to revisit\nour previous findings and to review the expanded capabilities of the\nKubernetes Agent feature. The [architecture had also\nevolved](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/154f538c997b4064294a54695846092c348bada8/doc/architecture.md#high-level-architecture),\nand at a high level we can see the product is changing names (`kgb` changed\nto `kas`, for Kubernetes Agent Server (KAS)).\n\n\n```mermaid\n\ngraph TB\n  agentk -- gRPC bidirectional streaming --> nginx\n\n  subgraph \"GitLab\"\n  nginx -- proxy pass port 5005 --> kas\n  kas[kas]\n  GitLabRoR[GitLab RoR] -- gRPC --> kas\n  kas -- gRPC --> Gitaly[Gitaly]\n  kas -- REST API --> GitLabRoR\n  end\n\n  subgraph \"Kubernetes cluster\"\n  agentk[agentk]\n  end\n```\n\n\nBy this time the threat modeling template we were using had evolved, and our\n[Application Security\nteam](https://handbook.gitlab.com/handbook/security/security-engineering/application-security/) had\nused it in several other reviews.\n\n\nGitLab’s practice of [dogfooding](https://handbook.gitlab.com/handbook/values/#dogfooding) means we use\nissues to track our reviews. At the time of this second review, our threat\nmodeling template now had a more structured approach where reviewers had\nsections that would 1) guide them throughout the review 2) require them to\nprovide specific information.\n\n\nBecause our process was more robust now we moved the threat modeling\nactivity of our security assessments into a dedicated repository, giving us\na single source of truth. [The\ntemplate](https://gitlab.com/gitlab-com/gl-security/security-research/threat-modeling-template/-/blob/3486ca53baf13d4aaba28dd340df153b2b83ea05/threat_model.md)\nhad evolved to also include:\n\n\n* An “Application decomposition” section where the reviewer must enter\ndetails such as use case, external entry points, trust levels, data flow\ndiagram, previous security issues and known references and best practices.\n\n* A dedicated threat analysis section.\n\n* The use of issue comments to detail each section of the threat modeling\nallowing us to easily reference sections individually via direct link.\n\n* The conversion and merge of the completed issue to an MD file, saved into\nthe dedicated repository for future use.\n\n\n### What is better than iteration? More iteration\n\n\nSince our second review in October 2020, the Kubernetes Agent feature had\nevolved significantly, so we performed another assessment in February 2021.\nThe difference this time was that we now had a [formal threat modeling\nprocess in place](https://handbook.gitlab.com/handbook/security/threat_modeling/).\n\n\n**To better understand the Kubernetes Agent feature, we added more details\nto our architectural diagram:**\n\n\n_Legend:_\n\n* Dotted arrows/flow: out of scope of the Architecture or TM\n\n* grpc: Google Remote Procedure Call\n\n* grpcs: grpc over SSL/TLS\n\n* ws: WebSocket\n\n* wss: ws over SSL/TLS\n\n\n![Detailed architectural diagram of the Kubernetes\nAgent](https://about.gitlab.com/images/blogimages/threat-modeling-KA/ka-architectural-diagram.png){:\n.shadow.medium.center}\n\nDetailed architectural diagram of the Kubernetes Agent.\n\n{: .note.text-center}\n\n\n\n**The data flow diagram we were using also evolved:**\n\n\n_Legend:_\n\n* Dotted arrows/flow: out of scope of the architecture or threat model\n\n* grpc: Google remote procedure call\n\n* grpcs: grpc over SSL/TLS\n\n* ws: WebSocket\n\n* wss: ws over SSL/TLS\n\n\n![file\nname](https://about.gitlab.com/images/blogimages/threat-modeling-KA/ka-data-flow.png){:\n.shadow.medium.center}\n\nAn evolved data flow diagram for the Kubernetes Agent.\n\n{: .note.text-center}\n\n\nAnd, naturally, as the features evolved, the threats evolved. Through our\nlatest threat modeling we discovered that:\n\n\n* Listeners are used by the Agent and the KAS for observability and health\nchecking. These listeners are unrestricted but they do listen on localhost\nby default.\n\n* On GitLab’s side, developers would be able to deploy an application to\nanother cluster on another corporate network. This is limited by Kubernetes'\nown authorisations defined for each cluster.\n\n* While brainstorming for threats, we thought about whether a user would be\nable to access unauthorised projects through indirect access on Gitaly.\nThankfully, this is well mitigated since a few conditions are necessary:\n     * A user must have access to the Agent's pod\n     * A user must be able to modify and reply to requests from the Agent pod\n          * However, each Agent also needs to submit a secret token, otherwise the [request is denied](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/module/agent_configuration/server/server.go#L55) (using [GitLab's client](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/client.go)) GetAgentInfo implementation. That implementation [generates and passes a JWT token](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/client.go#L108-123), along with the [Agent token](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/5b7ca0b9fbc8daba28ca552dc26aab45e482cf0c/internal/gitlab/do_options.go#L103-109). The Agent must also be configured to consult only authorised repositories, which makes it impossible for a user to access other repositories from the Agent.\n* On local installations, it’s possible to use unencrypted communications\nbetween the Kubernetes Agent and the KAS. However, on gitlab.com we have\nenforced secure communications.\n\n\n## Continuous improvement and iteration\n\n\nThreat modeling, just like anything in security, isn’t something you do once\nand are done with it. As we’ve seen with the reviews we’ve performed on the\nKubernetes Agent, threat modeling involves iteration and constant adoption\nof ever-changing features and attack surfaces of a product.\n\n\nOur threat model is now mature enough that it's an established process,\nperformed as a separate review and merged into a dedicated repository at\ncompletion. In the future, we hope to be able to publicly share those threat\nmodels to help customers, the community and to continue strengthening our\n[hackerone program](https://hackerone.com/gitlab).\n\n\nFor the next iterations we’re looking for broad adoption of threat modeling\nacross GitLab's engineering teams and beyond. We plan to use our threat\nmodel as a way to improve  [asynchronous\ncommunication](https://handbook.gitlab.com/handbook/company/culture/all-remote/asynchronous/) between the\ndifferent [security stable\ncounterparts](https://handbook.gitlab.com/handbook/security/security-engineering/application-security/stable-counterparts.html)\nthat operate across the organization. These stable counterparts ensure\nsecurity practices are integrated early on in the development process and\nalso allow us to ensure better coverage across vacations and time zones.\n\n\n## About Kubernetes\n\n\nUntil then, if you’re interested in more threat modeling details specific to\nKubernetes itself, I highly recommend the [Kubernetes Security Audit Working\nGroup Kubernetes threat\nmodel](https://github.com/kubernetes/community/tree/d538271e3f5eed22429ded165aeb2557c6277967/wg-security-audit).\nOne of my fellow GitLab teammates, [Marco Lancini](/company/team/#mlancini)\nhas published a great post, [“The Current State of Kubernetes Threat\nModelling”](https://www.marcolancini.it/2020/blog-kubernetes-threat-modelling/)\non his personal blog which contains useful information on different methods\nused to perform a threat model for Kubernetes.\n\n\n## How to threat model\n\n\nAnd, if you’re interested in how we’re rolling out threat modeling across\nGitLab, to teams beyond Security and Engineering, we’ve been tweaking our\n[how to threat model](https://handbook.gitlab.com/handbook/security/product-security/application-security/threat-modeling/howto/) guide\nto help as many team members as possible understand what threat modeling is\nand how and where to get started. Perhaps you’ll find some helpful tips and\ntricks there.\n\n\nAnd, keep an eye on this space, we’re planning to revisit threat modeling in\nblog posts where we’ll dive deeper into the PASTA methodology we’re using\nand take a closer look at what threat modeling looks like in practice here\nat GitLab.\n\n\nHave something to share? Comment below or find me on twitter at\n[@muffinbox33](https://twitter.com/Muffinbox33).\n\n\n_Also, I would like to take a moment to thank the Configure team and\n[Mikhail](/company/team/#ash2k) for their awesome collaboration during the\nvarious threat models we have performed._\n\n\nHappy threat modeling!\n\n\nCover image by [Jesús Mirón\nGarcía](https://www.pexels.com/@jesus-miron-garcia-1583477?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\non\n[Pexels](https://www.pexels.com/photo/timelapse-photography-of-vehicles-on-road-3043592/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)\n\n{: .note}\n\n\n\n## Read more on Kubernetes:\n\n\n- [How to install and use the GitLab Kubernetes\nOperator](/blog/gko-on-ocp/)\n\n\n- [How to deploy the GitLab Agent for Kubernetes with limited\npermissions](/blog/setting-up-the-k-agent/)\n\n\n- [A new era of Kubernetes integrations on\nGitLab.com](/blog/gitlab-kubernetes-agent-on-gitlab-com/)\n\n\n- [Understand Kubernetes terminology from namespaces to\npods](/blog/kubernetes-terminology/)\n\n\n- [What we learned after a year of GitLab.com on\nKubernetes](/blog/year-of-kubernetes/)","security",[21],{"slug":24,"featured":6,"template":25},"threat-modeling-kubernetes-agent","BlogPost","content:en-us:blog:threat-modeling-kubernetes-agent.yml","yaml","Threat Modeling Kubernetes Agent","content","en-us/blog/threat-modeling-kubernetes-agent.yml","en-us/blog/threat-modeling-kubernetes-agent","yml",{"_path":34,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"data":36,"_id":457,"_type":27,"title":458,"_source":29,"_file":459,"_stem":460,"_extension":32},"/shared/en-us/main-navigation","en-us",{"logo":37,"freeTrial":42,"sales":47,"login":52,"items":57,"search":388,"minimal":419,"duo":438,"pricingDeployment":447},{"config":38},{"href":39,"dataGaName":40,"dataGaLocation":41},"/","gitlab logo","header",{"text":43,"config":44},"Get free trial",{"href":45,"dataGaName":46,"dataGaLocation":41},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":48,"config":49},"Talk to sales",{"href":50,"dataGaName":51,"dataGaLocation":41},"/sales/","sales",{"text":53,"config":54},"Sign in",{"href":55,"dataGaName":56,"dataGaLocation":41},"https://gitlab.com/users/sign_in/","sign in",[58,102,199,204,309,369],{"text":59,"config":60,"cards":62,"footer":85},"Platform",{"dataNavLevelOne":61},"platform",[63,69,77],{"title":59,"description":64,"link":65},"The most comprehensive AI-powered DevSecOps Platform",{"text":66,"config":67},"Explore our Platform",{"href":68,"dataGaName":61,"dataGaLocation":41},"/platform/",{"title":70,"description":71,"link":72},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":73,"config":74},"Meet GitLab Duo",{"href":75,"dataGaName":76,"dataGaLocation":41},"/gitlab-duo/","gitlab duo ai",{"title":78,"description":79,"link":80},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":81,"config":82},"Learn more",{"href":83,"dataGaName":84,"dataGaLocation":41},"/why-gitlab/","why gitlab",{"title":86,"items":87},"Get started with",[88,93,98],{"text":89,"config":90},"Platform Engineering",{"href":91,"dataGaName":92,"dataGaLocation":41},"/solutions/platform-engineering/","platform engineering",{"text":94,"config":95},"Developer Experience",{"href":96,"dataGaName":97,"dataGaLocation":41},"/developer-experience/","Developer experience",{"text":99,"config":100},"MLOps",{"href":101,"dataGaName":99,"dataGaLocation":41},"/topics/devops/the-role-of-ai-in-devops/",{"text":103,"left":104,"config":105,"link":107,"lists":111,"footer":181},"Product",true,{"dataNavLevelOne":106},"solutions",{"text":108,"config":109},"View all Solutions",{"href":110,"dataGaName":106,"dataGaLocation":41},"/solutions/",[112,137,160],{"title":113,"description":114,"link":115,"items":120},"Automation","CI/CD and automation to accelerate deployment",{"config":116},{"icon":117,"href":118,"dataGaName":119,"dataGaLocation":41},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[121,125,129,133],{"text":122,"config":123},"CI/CD",{"href":124,"dataGaLocation":41,"dataGaName":122},"/solutions/continuous-integration/",{"text":126,"config":127},"AI-Assisted Development",{"href":75,"dataGaLocation":41,"dataGaName":128},"AI assisted development",{"text":130,"config":131},"Source Code Management",{"href":132,"dataGaLocation":41,"dataGaName":130},"/solutions/source-code-management/",{"text":134,"config":135},"Automated Software Delivery",{"href":118,"dataGaLocation":41,"dataGaName":136},"Automated software delivery",{"title":138,"description":139,"link":140,"items":145},"Security","Deliver code faster without compromising security",{"config":141},{"href":142,"dataGaName":143,"dataGaLocation":41,"icon":144},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[146,150,155],{"text":147,"config":148},"Application Security Testing",{"href":142,"dataGaName":149,"dataGaLocation":41},"Application security testing",{"text":151,"config":152},"Software Supply Chain Security",{"href":153,"dataGaLocation":41,"dataGaName":154},"/solutions/supply-chain/","Software supply chain security",{"text":156,"config":157},"Software Compliance",{"href":158,"dataGaName":159,"dataGaLocation":41},"/solutions/software-compliance/","software compliance",{"title":161,"link":162,"items":167},"Measurement",{"config":163},{"icon":164,"href":165,"dataGaName":166,"dataGaLocation":41},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[168,172,176],{"text":169,"config":170},"Visibility & Measurement",{"href":165,"dataGaLocation":41,"dataGaName":171},"Visibility and Measurement",{"text":173,"config":174},"Value Stream Management",{"href":175,"dataGaLocation":41,"dataGaName":173},"/solutions/value-stream-management/",{"text":177,"config":178},"Analytics & Insights",{"href":179,"dataGaLocation":41,"dataGaName":180},"/solutions/analytics-and-insights/","Analytics and insights",{"title":182,"items":183},"GitLab for",[184,189,194],{"text":185,"config":186},"Enterprise",{"href":187,"dataGaLocation":41,"dataGaName":188},"/enterprise/","enterprise",{"text":190,"config":191},"Small Business",{"href":192,"dataGaLocation":41,"dataGaName":193},"/small-business/","small business",{"text":195,"config":196},"Public Sector",{"href":197,"dataGaLocation":41,"dataGaName":198},"/solutions/public-sector/","public sector",{"text":200,"config":201},"Pricing",{"href":202,"dataGaName":203,"dataGaLocation":41,"dataNavLevelOne":203},"/pricing/","pricing",{"text":205,"config":206,"link":208,"lists":212,"feature":296},"Resources",{"dataNavLevelOne":207},"resources",{"text":209,"config":210},"View all resources",{"href":211,"dataGaName":207,"dataGaLocation":41},"/resources/",[213,246,268],{"title":214,"items":215},"Getting started",[216,221,226,231,236,241],{"text":217,"config":218},"Install",{"href":219,"dataGaName":220,"dataGaLocation":41},"/install/","install",{"text":222,"config":223},"Quick start guides",{"href":224,"dataGaName":225,"dataGaLocation":41},"/get-started/","quick setup checklists",{"text":227,"config":228},"Learn",{"href":229,"dataGaLocation":41,"dataGaName":230},"https://university.gitlab.com/","learn",{"text":232,"config":233},"Product documentation",{"href":234,"dataGaName":235,"dataGaLocation":41},"https://docs.gitlab.com/","product documentation",{"text":237,"config":238},"Best practice videos",{"href":239,"dataGaName":240,"dataGaLocation":41},"/getting-started-videos/","best practice videos",{"text":242,"config":243},"Integrations",{"href":244,"dataGaName":245,"dataGaLocation":41},"/integrations/","integrations",{"title":247,"items":248},"Discover",[249,254,258,263],{"text":250,"config":251},"Customer success stories",{"href":252,"dataGaName":253,"dataGaLocation":41},"/customers/","customer success stories",{"text":255,"config":256},"Blog",{"href":257,"dataGaName":5,"dataGaLocation":41},"/blog/",{"text":259,"config":260},"Remote",{"href":261,"dataGaName":262,"dataGaLocation":41},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":264,"config":265},"TeamOps",{"href":266,"dataGaName":267,"dataGaLocation":41},"/teamops/","teamops",{"title":269,"items":270},"Connect",[271,276,281,286,291],{"text":272,"config":273},"GitLab Services",{"href":274,"dataGaName":275,"dataGaLocation":41},"/services/","services",{"text":277,"config":278},"Community",{"href":279,"dataGaName":280,"dataGaLocation":41},"/community/","community",{"text":282,"config":283},"Forum",{"href":284,"dataGaName":285,"dataGaLocation":41},"https://forum.gitlab.com/","forum",{"text":287,"config":288},"Events",{"href":289,"dataGaName":290,"dataGaLocation":41},"/events/","events",{"text":292,"config":293},"Partners",{"href":294,"dataGaName":295,"dataGaLocation":41},"/partners/","partners",{"backgroundColor":297,"textColor":298,"text":299,"image":300,"link":304},"#2f2a6b","#fff","Insights for the future of software development",{"altText":301,"config":302},"the source promo card",{"src":303},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":305,"config":306},"Read the latest",{"href":307,"dataGaName":308,"dataGaLocation":41},"/the-source/","the source",{"text":310,"config":311,"lists":313},"Company",{"dataNavLevelOne":312},"company",[314],{"items":315},[316,321,327,329,334,339,344,349,354,359,364],{"text":317,"config":318},"About",{"href":319,"dataGaName":320,"dataGaLocation":41},"/company/","about",{"text":322,"config":323,"footerGa":326},"Jobs",{"href":324,"dataGaName":325,"dataGaLocation":41},"/jobs/","jobs",{"dataGaName":325},{"text":287,"config":328},{"href":289,"dataGaName":290,"dataGaLocation":41},{"text":330,"config":331},"Leadership",{"href":332,"dataGaName":333,"dataGaLocation":41},"/company/team/e-group/","leadership",{"text":335,"config":336},"Team",{"href":337,"dataGaName":338,"dataGaLocation":41},"/company/team/","team",{"text":340,"config":341},"Handbook",{"href":342,"dataGaName":343,"dataGaLocation":41},"https://handbook.gitlab.com/","handbook",{"text":345,"config":346},"Investor relations",{"href":347,"dataGaName":348,"dataGaLocation":41},"https://ir.gitlab.com/","investor relations",{"text":350,"config":351},"Trust Center",{"href":352,"dataGaName":353,"dataGaLocation":41},"/security/","trust center",{"text":355,"config":356},"AI Transparency Center",{"href":357,"dataGaName":358,"dataGaLocation":41},"/ai-transparency-center/","ai transparency center",{"text":360,"config":361},"Newsletter",{"href":362,"dataGaName":363,"dataGaLocation":41},"/company/contact/","newsletter",{"text":365,"config":366},"Press",{"href":367,"dataGaName":368,"dataGaLocation":41},"/press/","press",{"text":370,"config":371,"lists":372},"Contact us",{"dataNavLevelOne":312},[373],{"items":374},[375,378,383],{"text":48,"config":376},{"href":50,"dataGaName":377,"dataGaLocation":41},"talk to sales",{"text":379,"config":380},"Support portal",{"href":381,"dataGaName":382,"dataGaLocation":41},"https://support.gitlab.com","support portal",{"text":384,"config":385},"Customer portal",{"href":386,"dataGaName":387,"dataGaLocation":41},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":389,"login":390,"suggestions":397},"Close",{"text":391,"link":392},"To search repositories and projects, login to",{"text":393,"config":394},"gitlab.com",{"href":55,"dataGaName":395,"dataGaLocation":396},"search login","search",{"text":398,"default":399},"Suggestions",[400,402,406,408,412,416],{"text":70,"config":401},{"href":75,"dataGaName":70,"dataGaLocation":396},{"text":403,"config":404},"Code Suggestions (AI)",{"href":405,"dataGaName":403,"dataGaLocation":396},"/solutions/code-suggestions/",{"text":122,"config":407},{"href":124,"dataGaName":122,"dataGaLocation":396},{"text":409,"config":410},"GitLab on AWS",{"href":411,"dataGaName":409,"dataGaLocation":396},"/partners/technology-partners/aws/",{"text":413,"config":414},"GitLab on Google Cloud",{"href":415,"dataGaName":413,"dataGaLocation":396},"/partners/technology-partners/google-cloud-platform/",{"text":417,"config":418},"Why GitLab?",{"href":83,"dataGaName":417,"dataGaLocation":396},{"freeTrial":420,"mobileIcon":425,"desktopIcon":430,"secondaryButton":433},{"text":421,"config":422},"Start free trial",{"href":423,"dataGaName":46,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Gitlab Icon",{"src":428,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":434,"config":435},"Get Started",{"href":436,"dataGaName":437,"dataGaLocation":424},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":439,"mobileIcon":443,"desktopIcon":445},{"text":440,"config":441},"Learn more about GitLab Duo",{"href":75,"dataGaName":442,"dataGaLocation":424},"gitlab duo",{"altText":426,"config":444},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":446},{"src":432,"dataGaName":429,"dataGaLocation":424},{"freeTrial":448,"mobileIcon":453,"desktopIcon":455},{"text":449,"config":450},"Back to pricing",{"href":202,"dataGaName":451,"dataGaLocation":424,"icon":452},"back to pricing","GoBack",{"altText":426,"config":454},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":456},{"src":432,"dataGaName":429,"dataGaLocation":424},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":462,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"title":463,"button":464,"image":469,"config":473,"_id":475,"_type":27,"_source":29,"_file":476,"_stem":477,"_extension":32},"/shared/en-us/banner","is now in public beta!",{"text":465,"config":466},"Try the Beta",{"href":467,"dataGaName":468,"dataGaLocation":41},"/gitlab-duo/agent-platform/","duo banner",{"altText":470,"config":471},"GitLab Duo Agent Platform",{"src":472},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":474},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":479,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"data":480,"_id":719,"_type":27,"title":720,"_source":29,"_file":721,"_stem":722,"_extension":32},"/shared/en-us/main-footer",{"text":481,"source":482,"edit":488,"contribute":493,"config":498,"items":503,"minimal":711},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":483,"config":484},"View page source",{"href":485,"dataGaName":486,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":489,"config":490},"Edit this page",{"href":491,"dataGaName":492,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":494,"config":495},"Please contribute",{"href":496,"dataGaName":497,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":499,"facebook":500,"youtube":501,"linkedin":502},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[504,551,604,648,677],{"title":200,"links":505,"subMenu":520},[506,510,515],{"text":507,"config":508},"View plans",{"href":202,"dataGaName":509,"dataGaLocation":487},"view plans",{"text":511,"config":512},"Why Premium?",{"href":513,"dataGaName":514,"dataGaLocation":487},"/pricing/premium/","why premium",{"text":516,"config":517},"Why Ultimate?",{"href":518,"dataGaName":519,"dataGaLocation":487},"/pricing/ultimate/","why ultimate",[521],{"title":522,"links":523},"Contact Us",[524,527,529,531,536,541,546],{"text":525,"config":526},"Contact sales",{"href":50,"dataGaName":51,"dataGaLocation":487},{"text":379,"config":528},{"href":381,"dataGaName":382,"dataGaLocation":487},{"text":384,"config":530},{"href":386,"dataGaName":387,"dataGaLocation":487},{"text":532,"config":533},"Status",{"href":534,"dataGaName":535,"dataGaLocation":487},"https://status.gitlab.com/","status",{"text":537,"config":538},"Terms of use",{"href":539,"dataGaName":540,"dataGaLocation":487},"/terms/","terms of use",{"text":542,"config":543},"Privacy statement",{"href":544,"dataGaName":545,"dataGaLocation":487},"/privacy/","privacy statement",{"text":547,"config":548},"Cookie preferences",{"dataGaName":549,"dataGaLocation":487,"id":550,"isOneTrustButton":104},"cookie preferences","ot-sdk-btn",{"title":103,"links":552,"subMenu":560},[553,557],{"text":554,"config":555},"DevSecOps platform",{"href":68,"dataGaName":556,"dataGaLocation":487},"devsecops platform",{"text":126,"config":558},{"href":75,"dataGaName":559,"dataGaLocation":487},"ai-assisted development",[561],{"title":562,"links":563},"Topics",[564,569,574,579,584,589,594,599],{"text":565,"config":566},"CICD",{"href":567,"dataGaName":568,"dataGaLocation":487},"/topics/ci-cd/","cicd",{"text":570,"config":571},"GitOps",{"href":572,"dataGaName":573,"dataGaLocation":487},"/topics/gitops/","gitops",{"text":575,"config":576},"DevOps",{"href":577,"dataGaName":578,"dataGaLocation":487},"/topics/devops/","devops",{"text":580,"config":581},"Version Control",{"href":582,"dataGaName":583,"dataGaLocation":487},"/topics/version-control/","version control",{"text":585,"config":586},"DevSecOps",{"href":587,"dataGaName":588,"dataGaLocation":487},"/topics/devsecops/","devsecops",{"text":590,"config":591},"Cloud Native",{"href":592,"dataGaName":593,"dataGaLocation":487},"/topics/cloud-native/","cloud native",{"text":595,"config":596},"AI for Coding",{"href":597,"dataGaName":598,"dataGaLocation":487},"/topics/devops/ai-for-coding/","ai for coding",{"text":600,"config":601},"Agentic AI",{"href":602,"dataGaName":603,"dataGaLocation":487},"/topics/agentic-ai/","agentic ai",{"title":605,"links":606},"Solutions",[607,609,611,616,620,623,627,630,632,635,638,643],{"text":147,"config":608},{"href":142,"dataGaName":147,"dataGaLocation":487},{"text":136,"config":610},{"href":118,"dataGaName":119,"dataGaLocation":487},{"text":612,"config":613},"Agile development",{"href":614,"dataGaName":615,"dataGaLocation":487},"/solutions/agile-delivery/","agile delivery",{"text":617,"config":618},"SCM",{"href":132,"dataGaName":619,"dataGaLocation":487},"source code management",{"text":565,"config":621},{"href":124,"dataGaName":622,"dataGaLocation":487},"continuous integration & delivery",{"text":624,"config":625},"Value stream management",{"href":175,"dataGaName":626,"dataGaLocation":487},"value stream management",{"text":570,"config":628},{"href":629,"dataGaName":573,"dataGaLocation":487},"/solutions/gitops/",{"text":185,"config":631},{"href":187,"dataGaName":188,"dataGaLocation":487},{"text":633,"config":634},"Small business",{"href":192,"dataGaName":193,"dataGaLocation":487},{"text":636,"config":637},"Public sector",{"href":197,"dataGaName":198,"dataGaLocation":487},{"text":639,"config":640},"Education",{"href":641,"dataGaName":642,"dataGaLocation":487},"/solutions/education/","education",{"text":644,"config":645},"Financial services",{"href":646,"dataGaName":647,"dataGaLocation":487},"/solutions/finance/","financial services",{"title":205,"links":649},[650,652,654,656,659,661,663,665,667,669,671,673,675],{"text":217,"config":651},{"href":219,"dataGaName":220,"dataGaLocation":487},{"text":222,"config":653},{"href":224,"dataGaName":225,"dataGaLocation":487},{"text":227,"config":655},{"href":229,"dataGaName":230,"dataGaLocation":487},{"text":232,"config":657},{"href":234,"dataGaName":658,"dataGaLocation":487},"docs",{"text":255,"config":660},{"href":257,"dataGaName":5,"dataGaLocation":487},{"text":250,"config":662},{"href":252,"dataGaName":253,"dataGaLocation":487},{"text":259,"config":664},{"href":261,"dataGaName":262,"dataGaLocation":487},{"text":272,"config":666},{"href":274,"dataGaName":275,"dataGaLocation":487},{"text":264,"config":668},{"href":266,"dataGaName":267,"dataGaLocation":487},{"text":277,"config":670},{"href":279,"dataGaName":280,"dataGaLocation":487},{"text":282,"config":672},{"href":284,"dataGaName":285,"dataGaLocation":487},{"text":287,"config":674},{"href":289,"dataGaName":290,"dataGaLocation":487},{"text":292,"config":676},{"href":294,"dataGaName":295,"dataGaLocation":487},{"title":310,"links":678},[679,681,683,685,687,689,691,695,700,702,704,706],{"text":317,"config":680},{"href":319,"dataGaName":312,"dataGaLocation":487},{"text":322,"config":682},{"href":324,"dataGaName":325,"dataGaLocation":487},{"text":330,"config":684},{"href":332,"dataGaName":333,"dataGaLocation":487},{"text":335,"config":686},{"href":337,"dataGaName":338,"dataGaLocation":487},{"text":340,"config":688},{"href":342,"dataGaName":343,"dataGaLocation":487},{"text":345,"config":690},{"href":347,"dataGaName":348,"dataGaLocation":487},{"text":692,"config":693},"Sustainability",{"href":694,"dataGaName":692,"dataGaLocation":487},"/sustainability/",{"text":696,"config":697},"Diversity, inclusion and belonging (DIB)",{"href":698,"dataGaName":699,"dataGaLocation":487},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":350,"config":701},{"href":352,"dataGaName":353,"dataGaLocation":487},{"text":360,"config":703},{"href":362,"dataGaName":363,"dataGaLocation":487},{"text":365,"config":705},{"href":367,"dataGaName":368,"dataGaLocation":487},{"text":707,"config":708},"Modern Slavery Transparency Statement",{"href":709,"dataGaName":710,"dataGaLocation":487},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":712},[713,715,717],{"text":537,"config":714},{"href":539,"dataGaName":540,"dataGaLocation":487},{"text":542,"config":716},{"href":544,"dataGaName":545,"dataGaLocation":487},{"text":547,"config":718},{"dataGaName":549,"dataGaLocation":487,"id":550,"isOneTrustButton":104},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[724],{"_path":725,"_dir":726,"_draft":6,"_partial":6,"_locale":7,"content":727,"config":731,"_id":733,"_type":27,"title":18,"_source":29,"_file":734,"_stem":735,"_extension":32},"/en-us/blog/authors/vitor-meireles-de-sousa","authors",{"name":18,"config":728},{"headshot":729,"ctfId":730},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682001/Blog/Author%20Headshots/vdesousa-headshot.png","vdesousa",{"template":732},"BlogAuthor","content:en-us:blog:authors:vitor-meireles-de-sousa.yml","en-us/blog/authors/vitor-meireles-de-sousa.yml","en-us/blog/authors/vitor-meireles-de-sousa",{"_path":737,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"header":738,"eyebrow":739,"blurb":740,"button":741,"secondaryButton":745,"_id":747,"_type":27,"title":748,"_source":29,"_file":749,"_stem":750,"_extension":32},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":43,"config":742},{"href":743,"dataGaName":46,"dataGaLocation":744},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":48,"config":746},{"href":50,"dataGaName":51,"dataGaLocation":744},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":752,"content":753,"config":756,"_id":26,"_type":27,"title":28,"_source":29,"_file":30,"_stem":31,"_extension":32},{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},{"title":9,"description":10,"authors":754,"heroImage":11,"date":19,"body":20,"category":21,"tags":755},[18],[21],{"slug":24,"featured":6,"template":25},1761814428734]