[{"data":1,"prerenderedAt":758},["ShallowReactive",2],{"/en-us/blog/monitor-web-attack-surface-with-gitlab":3,"navigation-en-us":34,"banner-en-us":462,"footer-en-us":479,"Chris Moberly":724,"next-steps-en-us":737,"footer-source-/en-us/blog/monitor-web-attack-surface-with-gitlab/":752},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":24,"_id":27,"_type":28,"title":29,"_source":30,"_file":31,"_stem":32,"_extension":33},"/en-us/blog/monitor-web-attack-surface-with-gitlab","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Monitor your web attack surface with GitLab CI/CD and GitLab Pages","Use this tutorial to build an automated web application screenshot report.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682233/Blog/Hero%20Images/aleks-dahlberg-glass-unsplash.jpg","https://about.gitlab.com/blog/monitor-web-attack-surface-with-gitlab","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Monitor your web attack surface with GitLab CI/CD and GitLab Pages\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chris Moberly\"}],\n        \"datePublished\": \"2023-01-11\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Chris Moberly","2023-01-11","_DISCLAIMER: We believe that understanding the tactics and techniques of\nboth attackers and defenders is key to keeping our organization secure. It's\nimportant to note that GitLab security blog posts are for informational\npurposes only, not to provide specific security advice._\n\n\nAttackers love insecure web applications. Lucky for them, these applications\nare everywhere! Test environments, development instances, default\ninstallations with hardcoded passwords - you name it, it's out there\nsomewhere waiting to be exploited.\n\n\nThe easier it becomes to deploy resources in the cloud, the more of these\ninsecure web applications end up exposed to hacking and/or unintended\naccess. You can get ahead of potential threats by proactively identifying\nand reviewing your own web application attack surface.\n\n\nIn this tutorial, we'll explain how you can monitor the web applications in\nyour environment by generating a screenshot report using GitLab CI/CD,\nGitLab Pages, and a handful of free and open source security tools. You'll\nend up with a fully automated solution that can:\n\n\n- Identify web services on a list of addresses you own.\n\n- Capture screenshots of these web services.\n\n- Build an authenticated web portal for you to visually see each site that\nwas discovered.\n\n\n## Building the solution\n\n\n### Start with a project\n\n\nInside the GitLab web interface, [create a blank\nproject](https://gitlab.com/projects/new#blank_project). The default\nsettings should be fine, but you should review to confirm that the default\nsettings are appropriate. Pay particular attention to the \"Visibility Level\"\n- you may want to set this to private.\n\n\n![Creating a GitLab\nproject](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-project.png){:\n.shadow.medium.center}\n\n\n\n\n### Write the automation scripts\n\n\nWe'll use three scripts in this project:\n\n\n-  `setup.sh`: Install the required tooling.\n\n- `discover-services.sh`: Identify web services using\n[httpx](https://github.com/projectdiscovery/httpx).\n\n- `take-screenshots.sh`: Use\n[gowitness](https://github.com/sensepost/gowitness) to generate a static\nwebsite containing screenshots of each identified web service.\n\n\nThe HTML generated by gowitness will be placed into the `public` folder,\nwhich is used by [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) to generate\na website you can click through to review the findings.\n\n\nEach script will generate output files which may be useful for additional\nanalysis. These will be made available as GitLab [job\nartifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html), so\nthat you can download and review them at will.\n\n\nTo complete this step, first create a new folder in your project called\n`scripts`. Then, add the following files into that folder:\n\n\n#### setup.sh\n\n\n```bash\n\n#!/bin/bash\n\n\n# create folder for downloaded binaries\n\nmkdir bin\n\n\n# install general pre-reqs\n\napt -qq update > /dev/null\n\napt -qq install -y wget unzip > /dev/null\n\n\n# install pre-reqs for gowitness\n\napt -qq install -y chromium > /dev/null\n\n\n# download tools\n\nwget -q\nhttps://github.com/projectdiscovery/httpx/releases/download/v1.2.5/httpx_1.2.5_linux_amd64.zip\n\nwget -q\nhttps://github.com/sensepost/gowitness/releases/download/2.4.2/gowitness-2.4.2-linux-amd64\n\n\n# unzip / move all relases to bin folder\n\nunzip httpx_1.2.5_linux_amd64.zip -d bin/\n\nmv gowitness-2.4.2-linux-amd64 bin/gowitness\n\nchmod u+x bin/gowitness\n\n```\n\n\n#### discover-services.sh\n\n\n```bash\n\n#!/bin/bash\n\n\n# You may want to dynamically generate a target file with each run.\n\n# For this demo, we are using a list defined inside project CI variables.\n\nTARGETS=$TARGET_FILE\n\n\n# create output directory\n\nmkdir ./targets\n\n\n# Identify web services\n\necho \"Identifying web services across $(cat \"$TARGETS\" | wc -l) targets...\"\n\ncat \"$TARGETS\" | bin/httpx -o targets/web-services.txt -p 80,443\n\n\necho \"Discovered $(cat targets/web-services.txt | wc -l) web services.\"\n\n```\n\n\n#### take-screenshots.sh\n\n\n```bash\n\n#!/bin/bash\n\n\n# Run gowitness\n\nbin/gowitness file -f targets/web-services.txt\n\nbin/gowitness report export -f report.zip\n\n\n# Move the report to pages outdir\n\nunzip report.zip\n\nmv gowitness public\n\n```\n\n\n\n\n### Set up the pipeline\n\n\nNext, we need to create the `.gitlab-ci.yml` file where we configure all of\nthese scripts to run inside a\n[pipeline](https://docs.gitlab.com/ee/ci/pipelines/). Create this file in\nthe root of the project with the following contents:\n\n\n```yaml\n\nstages:\n  - scan\n  - deploy\n\nscanner:\n  image: debian:bullseye\n  stage: scan\n  script:\n  - bash ./scripts/setup.sh\n  - bash ./scripts/discover-services.sh\n  - bash ./scripts/take-screenshots.sh\n  only:\n  - schedules\n  - web\n  artifacts:\n    paths:\n    - targets\n    - public\n\npages:\n  stage: deploy\n  script:\n  - echo \"\" # do nothing\n  only:\n  - schedules\n  - web\n  artifacts:\n    paths:\n    - public\n```\n\n\nThis file defines a pipeline with two stages:\n\n\n- The first stage (`scan`) runs all three scripts we created. This will\ngenerate a static website inside a folder called `public`.\n\n- The second stage (`deploy`) is required for GitLab Pages to work - this is\nwhere the static site is published on a publicly-accessible URL that can be\nconfigured to require GitLab authentication.\n\n\nYou can see we've added an `only` condition to both of these stages. This\nensures that the tool doesn't run every time you make a change to the code -\nit runs only on a defined schedule or when you manually choose to run it via\nthe web UI.\n\n\n### Define your targets\n\n\nYou may have noticed the `TARGETS_FILE` variable inside the\n`discover-services.sh` script from earlier. That's a [file\nvariable](https://docs.gitlab.com/ee/ci/variables/#cicd-variable-types) that\nwill contain the targets you wish to scan. Defining this as a variable\nallows us to create a generic, portable project that can be forked and\ncloned without containing any specific targets.\n\n\nTo add some targets to your project, go to \"Settings -> CI/CD -> Variables\"\nand click the \"Add variable\" button. Enter `TARGET_FILE` for the \"Key\" and\nfill in one host name or IP address per line in the \"Value\" section. Make\nsure to add a blank line to the end of the list - this is required for the\nscripts to run correctly.\n\n\n![Creating a CI environment\nvariable](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-variable.png){:\n.shadow.center}\n\n\n\nWe run a similar version of this screenshot tool internally, and we generate\nthis file dynamically by exporting all of our public addresses from our\nvarious cloud environments. If you decide to implement something like that,\nwe'd recommend adding an additional stage to your `.gitlab-ci.yaml` file.\n\n\n### Schedule and run the pipeline\n\n\nGitLab projects have a built-in\n[scheduler](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) that\nlets you automatically run pipelines at specific dates/times. You can access\nthis inside your project at \"CI/CD -> Schedules\". Here, we'll create a new\nschedule to run once a week on Monday mornings.\n\n\n![Creating a CI\nschedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-schedule.png){:\n.shadow.center}\n\n\n\nAfter saving the schedule, you can also choose to manually run the pipeline\nby clicking the play button shown below. If you are following along, go\nahead and do this now.\n\n\n![Running a CI\nschedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-play.png){:\n.shadow.center}\n\n\n\nYou can follow the progress of your pipeline by navigating to \"CI/CD ->\nPipelines\". Click on the status of the most recent pipeline. Here, you'll\nsee the stages we configured earlier.  If all goes well, you'll see green\ncheck marks on each stage. You can click on an individual stage to watch the\nconsole logs and perform any necessary troubleshooting.\n\n\n![CI pipeline success\nicons](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-success.png){:\n.shadow.center}\n\n\n\n### Enable notifications\n\n\nOnce you've set up a schedule, you might want to be alerted whenever a new\nreport is ready. Luckily, GitLab has you covered here!\n\n\nInside your project, go to \"Settings -> Integrations -> Pipeline Status\nEmails\". Put your email address into the \"Recipients\" field and uncheck the\nbox \"Notify only broken pipelines\". This will send you an email each time a\npipeline completes and a new screenshot report has been published to your\nGitLab Pages site.\n\n\nGitLab offers a slew of other notifcation options as well, including things\nlike Slack and Teams. If you prefer one of those, you can [read more in the\ndocs](https://docs.gitlab.com/ee/integration/).\n\n\n![Create pipeline\nnotifications](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-notifications.png){:\n.shadow.center}\n\n\n\n### View your GitLab Pages site\n\n\nOnce the pipeline has completed successfully, your site should be available.\nYou can obtain the site's public address by going to \"Settings -> Pages\".\n\n\nIf you set your project to be private, then by default only project members\nwho are authenticated to the GitLab server can view the site. You can modify\nthese settings under \"Settings -> General -> Visibility, project features,\npermissions -> Pages\".\n\n\n![Screenshot of gowitness\ninterface](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-gowitness.png){:\n.shadow.center}\n\n\n\n## Summary\n\n\nWeb applications are everywhere. Often, they are deployed with vulnerable\nconfigurations and are left forgotten - unmonitored and awaiting\nexploitation. You can build a monitoring solution using GitLab and free,\nopen-source tools that gives you a visual overview of the web apps running\nin your own environment.\n\n\nThis blog walked you through manually setting this up yourself. You can view\nour example project\n[here](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/webapp-screenshots),\nwhich was created exactly as decribed above. Feel free to fork or clone that\nproject as a shortcut to setting it up from scratch yourself.\n\n\nWe love to find creative uses for GitLab, and this is one we use ourselves\ninternally. If you've come up with some of your own interesting use cases,\nwe would love to hear about them! Or, if there is anything else you'd like\nour security team to write about, please do let us know! You can share your\nthoughts in the comments below or via issues and merge requests on any of\nour projects.\n\n\nThanks for reading!\n","security",[21,23],"open source",{"slug":25,"featured":6,"template":26},"monitor-web-attack-surface-with-gitlab","BlogPost","content:en-us:blog:monitor-web-attack-surface-with-gitlab.yml","yaml","Monitor Web Attack Surface With Gitlab","content","en-us/blog/monitor-web-attack-surface-with-gitlab.yml","en-us/blog/monitor-web-attack-surface-with-gitlab","yml",{"_path":35,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"data":37,"_id":458,"_type":28,"title":459,"_source":30,"_file":460,"_stem":461,"_extension":33},"/shared/en-us/main-navigation","en-us",{"logo":38,"freeTrial":43,"sales":48,"login":53,"items":58,"search":389,"minimal":420,"duo":439,"pricingDeployment":448},{"config":39},{"href":40,"dataGaName":41,"dataGaLocation":42},"/","gitlab logo","header",{"text":44,"config":45},"Get free trial",{"href":46,"dataGaName":47,"dataGaLocation":42},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":49,"config":50},"Talk to sales",{"href":51,"dataGaName":52,"dataGaLocation":42},"/sales/","sales",{"text":54,"config":55},"Sign in",{"href":56,"dataGaName":57,"dataGaLocation":42},"https://gitlab.com/users/sign_in/","sign in",[59,103,200,205,310,370],{"text":60,"config":61,"cards":63,"footer":86},"Platform",{"dataNavLevelOne":62},"platform",[64,70,78],{"title":60,"description":65,"link":66},"The most comprehensive AI-powered DevSecOps Platform",{"text":67,"config":68},"Explore our Platform",{"href":69,"dataGaName":62,"dataGaLocation":42},"/platform/",{"title":71,"description":72,"link":73},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":74,"config":75},"Meet GitLab Duo",{"href":76,"dataGaName":77,"dataGaLocation":42},"/gitlab-duo/","gitlab duo ai",{"title":79,"description":80,"link":81},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":82,"config":83},"Learn more",{"href":84,"dataGaName":85,"dataGaLocation":42},"/why-gitlab/","why gitlab",{"title":87,"items":88},"Get started with",[89,94,99],{"text":90,"config":91},"Platform Engineering",{"href":92,"dataGaName":93,"dataGaLocation":42},"/solutions/platform-engineering/","platform engineering",{"text":95,"config":96},"Developer Experience",{"href":97,"dataGaName":98,"dataGaLocation":42},"/developer-experience/","Developer experience",{"text":100,"config":101},"MLOps",{"href":102,"dataGaName":100,"dataGaLocation":42},"/topics/devops/the-role-of-ai-in-devops/",{"text":104,"left":105,"config":106,"link":108,"lists":112,"footer":182},"Product",true,{"dataNavLevelOne":107},"solutions",{"text":109,"config":110},"View all Solutions",{"href":111,"dataGaName":107,"dataGaLocation":42},"/solutions/",[113,138,161],{"title":114,"description":115,"link":116,"items":121},"Automation","CI/CD and automation to accelerate deployment",{"config":117},{"icon":118,"href":119,"dataGaName":120,"dataGaLocation":42},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[122,126,130,134],{"text":123,"config":124},"CI/CD",{"href":125,"dataGaLocation":42,"dataGaName":123},"/solutions/continuous-integration/",{"text":127,"config":128},"AI-Assisted Development",{"href":76,"dataGaLocation":42,"dataGaName":129},"AI assisted development",{"text":131,"config":132},"Source Code Management",{"href":133,"dataGaLocation":42,"dataGaName":131},"/solutions/source-code-management/",{"text":135,"config":136},"Automated Software Delivery",{"href":119,"dataGaLocation":42,"dataGaName":137},"Automated software delivery",{"title":139,"description":140,"link":141,"items":146},"Security","Deliver code faster without compromising security",{"config":142},{"href":143,"dataGaName":144,"dataGaLocation":42,"icon":145},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[147,151,156],{"text":148,"config":149},"Application Security Testing",{"href":143,"dataGaName":150,"dataGaLocation":42},"Application security testing",{"text":152,"config":153},"Software Supply Chain Security",{"href":154,"dataGaLocation":42,"dataGaName":155},"/solutions/supply-chain/","Software supply chain security",{"text":157,"config":158},"Software Compliance",{"href":159,"dataGaName":160,"dataGaLocation":42},"/solutions/software-compliance/","software compliance",{"title":162,"link":163,"items":168},"Measurement",{"config":164},{"icon":165,"href":166,"dataGaName":167,"dataGaLocation":42},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[169,173,177],{"text":170,"config":171},"Visibility & Measurement",{"href":166,"dataGaLocation":42,"dataGaName":172},"Visibility and Measurement",{"text":174,"config":175},"Value Stream Management",{"href":176,"dataGaLocation":42,"dataGaName":174},"/solutions/value-stream-management/",{"text":178,"config":179},"Analytics & Insights",{"href":180,"dataGaLocation":42,"dataGaName":181},"/solutions/analytics-and-insights/","Analytics and insights",{"title":183,"items":184},"GitLab for",[185,190,195],{"text":186,"config":187},"Enterprise",{"href":188,"dataGaLocation":42,"dataGaName":189},"/enterprise/","enterprise",{"text":191,"config":192},"Small Business",{"href":193,"dataGaLocation":42,"dataGaName":194},"/small-business/","small business",{"text":196,"config":197},"Public Sector",{"href":198,"dataGaLocation":42,"dataGaName":199},"/solutions/public-sector/","public sector",{"text":201,"config":202},"Pricing",{"href":203,"dataGaName":204,"dataGaLocation":42,"dataNavLevelOne":204},"/pricing/","pricing",{"text":206,"config":207,"link":209,"lists":213,"feature":297},"Resources",{"dataNavLevelOne":208},"resources",{"text":210,"config":211},"View all resources",{"href":212,"dataGaName":208,"dataGaLocation":42},"/resources/",[214,247,269],{"title":215,"items":216},"Getting started",[217,222,227,232,237,242],{"text":218,"config":219},"Install",{"href":220,"dataGaName":221,"dataGaLocation":42},"/install/","install",{"text":223,"config":224},"Quick start guides",{"href":225,"dataGaName":226,"dataGaLocation":42},"/get-started/","quick setup checklists",{"text":228,"config":229},"Learn",{"href":230,"dataGaLocation":42,"dataGaName":231},"https://university.gitlab.com/","learn",{"text":233,"config":234},"Product documentation",{"href":235,"dataGaName":236,"dataGaLocation":42},"https://docs.gitlab.com/","product documentation",{"text":238,"config":239},"Best practice videos",{"href":240,"dataGaName":241,"dataGaLocation":42},"/getting-started-videos/","best practice videos",{"text":243,"config":244},"Integrations",{"href":245,"dataGaName":246,"dataGaLocation":42},"/integrations/","integrations",{"title":248,"items":249},"Discover",[250,255,259,264],{"text":251,"config":252},"Customer success stories",{"href":253,"dataGaName":254,"dataGaLocation":42},"/customers/","customer success stories",{"text":256,"config":257},"Blog",{"href":258,"dataGaName":5,"dataGaLocation":42},"/blog/",{"text":260,"config":261},"Remote",{"href":262,"dataGaName":263,"dataGaLocation":42},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":265,"config":266},"TeamOps",{"href":267,"dataGaName":268,"dataGaLocation":42},"/teamops/","teamops",{"title":270,"items":271},"Connect",[272,277,282,287,292],{"text":273,"config":274},"GitLab Services",{"href":275,"dataGaName":276,"dataGaLocation":42},"/services/","services",{"text":278,"config":279},"Community",{"href":280,"dataGaName":281,"dataGaLocation":42},"/community/","community",{"text":283,"config":284},"Forum",{"href":285,"dataGaName":286,"dataGaLocation":42},"https://forum.gitlab.com/","forum",{"text":288,"config":289},"Events",{"href":290,"dataGaName":291,"dataGaLocation":42},"/events/","events",{"text":293,"config":294},"Partners",{"href":295,"dataGaName":296,"dataGaLocation":42},"/partners/","partners",{"backgroundColor":298,"textColor":299,"text":300,"image":301,"link":305},"#2f2a6b","#fff","Insights for the future of software development",{"altText":302,"config":303},"the source promo card",{"src":304},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":306,"config":307},"Read the latest",{"href":308,"dataGaName":309,"dataGaLocation":42},"/the-source/","the source",{"text":311,"config":312,"lists":314},"Company",{"dataNavLevelOne":313},"company",[315],{"items":316},[317,322,328,330,335,340,345,350,355,360,365],{"text":318,"config":319},"About",{"href":320,"dataGaName":321,"dataGaLocation":42},"/company/","about",{"text":323,"config":324,"footerGa":327},"Jobs",{"href":325,"dataGaName":326,"dataGaLocation":42},"/jobs/","jobs",{"dataGaName":326},{"text":288,"config":329},{"href":290,"dataGaName":291,"dataGaLocation":42},{"text":331,"config":332},"Leadership",{"href":333,"dataGaName":334,"dataGaLocation":42},"/company/team/e-group/","leadership",{"text":336,"config":337},"Team",{"href":338,"dataGaName":339,"dataGaLocation":42},"/company/team/","team",{"text":341,"config":342},"Handbook",{"href":343,"dataGaName":344,"dataGaLocation":42},"https://handbook.gitlab.com/","handbook",{"text":346,"config":347},"Investor relations",{"href":348,"dataGaName":349,"dataGaLocation":42},"https://ir.gitlab.com/","investor relations",{"text":351,"config":352},"Trust Center",{"href":353,"dataGaName":354,"dataGaLocation":42},"/security/","trust center",{"text":356,"config":357},"AI Transparency Center",{"href":358,"dataGaName":359,"dataGaLocation":42},"/ai-transparency-center/","ai transparency center",{"text":361,"config":362},"Newsletter",{"href":363,"dataGaName":364,"dataGaLocation":42},"/company/contact/","newsletter",{"text":366,"config":367},"Press",{"href":368,"dataGaName":369,"dataGaLocation":42},"/press/","press",{"text":371,"config":372,"lists":373},"Contact us",{"dataNavLevelOne":313},[374],{"items":375},[376,379,384],{"text":49,"config":377},{"href":51,"dataGaName":378,"dataGaLocation":42},"talk to sales",{"text":380,"config":381},"Support portal",{"href":382,"dataGaName":383,"dataGaLocation":42},"https://support.gitlab.com","support portal",{"text":385,"config":386},"Customer portal",{"href":387,"dataGaName":388,"dataGaLocation":42},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":390,"login":391,"suggestions":398},"Close",{"text":392,"link":393},"To search repositories and projects, login to",{"text":394,"config":395},"gitlab.com",{"href":56,"dataGaName":396,"dataGaLocation":397},"search login","search",{"text":399,"default":400},"Suggestions",[401,403,407,409,413,417],{"text":71,"config":402},{"href":76,"dataGaName":71,"dataGaLocation":397},{"text":404,"config":405},"Code Suggestions (AI)",{"href":406,"dataGaName":404,"dataGaLocation":397},"/solutions/code-suggestions/",{"text":123,"config":408},{"href":125,"dataGaName":123,"dataGaLocation":397},{"text":410,"config":411},"GitLab on AWS",{"href":412,"dataGaName":410,"dataGaLocation":397},"/partners/technology-partners/aws/",{"text":414,"config":415},"GitLab on Google Cloud",{"href":416,"dataGaName":414,"dataGaLocation":397},"/partners/technology-partners/google-cloud-platform/",{"text":418,"config":419},"Why GitLab?",{"href":84,"dataGaName":418,"dataGaLocation":397},{"freeTrial":421,"mobileIcon":426,"desktopIcon":431,"secondaryButton":434},{"text":422,"config":423},"Start free trial",{"href":424,"dataGaName":47,"dataGaLocation":425},"https://gitlab.com/-/trials/new/","nav",{"altText":427,"config":428},"Gitlab Icon",{"src":429,"dataGaName":430,"dataGaLocation":425},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":427,"config":432},{"src":433,"dataGaName":430,"dataGaLocation":425},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":435,"config":436},"Get Started",{"href":437,"dataGaName":438,"dataGaLocation":425},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":440,"mobileIcon":444,"desktopIcon":446},{"text":441,"config":442},"Learn more about GitLab Duo",{"href":76,"dataGaName":443,"dataGaLocation":425},"gitlab duo",{"altText":427,"config":445},{"src":429,"dataGaName":430,"dataGaLocation":425},{"altText":427,"config":447},{"src":433,"dataGaName":430,"dataGaLocation":425},{"freeTrial":449,"mobileIcon":454,"desktopIcon":456},{"text":450,"config":451},"Back to pricing",{"href":203,"dataGaName":452,"dataGaLocation":425,"icon":453},"back to pricing","GoBack",{"altText":427,"config":455},{"src":429,"dataGaName":430,"dataGaLocation":425},{"altText":427,"config":457},{"src":433,"dataGaName":430,"dataGaLocation":425},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":463,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"title":464,"button":465,"image":470,"config":474,"_id":476,"_type":28,"_source":30,"_file":477,"_stem":478,"_extension":33},"/shared/en-us/banner","is now in public beta!",{"text":466,"config":467},"Try the Beta",{"href":468,"dataGaName":469,"dataGaLocation":42},"/gitlab-duo/agent-platform/","duo banner",{"altText":471,"config":472},"GitLab Duo Agent Platform",{"src":473},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":475},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":480,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"data":481,"_id":720,"_type":28,"title":721,"_source":30,"_file":722,"_stem":723,"_extension":33},"/shared/en-us/main-footer",{"text":482,"source":483,"edit":489,"contribute":494,"config":499,"items":504,"minimal":712},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":484,"config":485},"View page source",{"href":486,"dataGaName":487,"dataGaLocation":488},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":490,"config":491},"Edit this page",{"href":492,"dataGaName":493,"dataGaLocation":488},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":495,"config":496},"Please contribute",{"href":497,"dataGaName":498,"dataGaLocation":488},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":500,"facebook":501,"youtube":502,"linkedin":503},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[505,552,605,649,678],{"title":201,"links":506,"subMenu":521},[507,511,516],{"text":508,"config":509},"View plans",{"href":203,"dataGaName":510,"dataGaLocation":488},"view plans",{"text":512,"config":513},"Why Premium?",{"href":514,"dataGaName":515,"dataGaLocation":488},"/pricing/premium/","why premium",{"text":517,"config":518},"Why Ultimate?",{"href":519,"dataGaName":520,"dataGaLocation":488},"/pricing/ultimate/","why ultimate",[522],{"title":523,"links":524},"Contact Us",[525,528,530,532,537,542,547],{"text":526,"config":527},"Contact sales",{"href":51,"dataGaName":52,"dataGaLocation":488},{"text":380,"config":529},{"href":382,"dataGaName":383,"dataGaLocation":488},{"text":385,"config":531},{"href":387,"dataGaName":388,"dataGaLocation":488},{"text":533,"config":534},"Status",{"href":535,"dataGaName":536,"dataGaLocation":488},"https://status.gitlab.com/","status",{"text":538,"config":539},"Terms of use",{"href":540,"dataGaName":541,"dataGaLocation":488},"/terms/","terms of use",{"text":543,"config":544},"Privacy statement",{"href":545,"dataGaName":546,"dataGaLocation":488},"/privacy/","privacy statement",{"text":548,"config":549},"Cookie preferences",{"dataGaName":550,"dataGaLocation":488,"id":551,"isOneTrustButton":105},"cookie preferences","ot-sdk-btn",{"title":104,"links":553,"subMenu":561},[554,558],{"text":555,"config":556},"DevSecOps platform",{"href":69,"dataGaName":557,"dataGaLocation":488},"devsecops platform",{"text":127,"config":559},{"href":76,"dataGaName":560,"dataGaLocation":488},"ai-assisted development",[562],{"title":563,"links":564},"Topics",[565,570,575,580,585,590,595,600],{"text":566,"config":567},"CICD",{"href":568,"dataGaName":569,"dataGaLocation":488},"/topics/ci-cd/","cicd",{"text":571,"config":572},"GitOps",{"href":573,"dataGaName":574,"dataGaLocation":488},"/topics/gitops/","gitops",{"text":576,"config":577},"DevOps",{"href":578,"dataGaName":579,"dataGaLocation":488},"/topics/devops/","devops",{"text":581,"config":582},"Version Control",{"href":583,"dataGaName":584,"dataGaLocation":488},"/topics/version-control/","version control",{"text":586,"config":587},"DevSecOps",{"href":588,"dataGaName":589,"dataGaLocation":488},"/topics/devsecops/","devsecops",{"text":591,"config":592},"Cloud Native",{"href":593,"dataGaName":594,"dataGaLocation":488},"/topics/cloud-native/","cloud native",{"text":596,"config":597},"AI for Coding",{"href":598,"dataGaName":599,"dataGaLocation":488},"/topics/devops/ai-for-coding/","ai for coding",{"text":601,"config":602},"Agentic AI",{"href":603,"dataGaName":604,"dataGaLocation":488},"/topics/agentic-ai/","agentic ai",{"title":606,"links":607},"Solutions",[608,610,612,617,621,624,628,631,633,636,639,644],{"text":148,"config":609},{"href":143,"dataGaName":148,"dataGaLocation":488},{"text":137,"config":611},{"href":119,"dataGaName":120,"dataGaLocation":488},{"text":613,"config":614},"Agile development",{"href":615,"dataGaName":616,"dataGaLocation":488},"/solutions/agile-delivery/","agile delivery",{"text":618,"config":619},"SCM",{"href":133,"dataGaName":620,"dataGaLocation":488},"source code management",{"text":566,"config":622},{"href":125,"dataGaName":623,"dataGaLocation":488},"continuous integration & delivery",{"text":625,"config":626},"Value stream management",{"href":176,"dataGaName":627,"dataGaLocation":488},"value stream management",{"text":571,"config":629},{"href":630,"dataGaName":574,"dataGaLocation":488},"/solutions/gitops/",{"text":186,"config":632},{"href":188,"dataGaName":189,"dataGaLocation":488},{"text":634,"config":635},"Small business",{"href":193,"dataGaName":194,"dataGaLocation":488},{"text":637,"config":638},"Public sector",{"href":198,"dataGaName":199,"dataGaLocation":488},{"text":640,"config":641},"Education",{"href":642,"dataGaName":643,"dataGaLocation":488},"/solutions/education/","education",{"text":645,"config":646},"Financial services",{"href":647,"dataGaName":648,"dataGaLocation":488},"/solutions/finance/","financial services",{"title":206,"links":650},[651,653,655,657,660,662,664,666,668,670,672,674,676],{"text":218,"config":652},{"href":220,"dataGaName":221,"dataGaLocation":488},{"text":223,"config":654},{"href":225,"dataGaName":226,"dataGaLocation":488},{"text":228,"config":656},{"href":230,"dataGaName":231,"dataGaLocation":488},{"text":233,"config":658},{"href":235,"dataGaName":659,"dataGaLocation":488},"docs",{"text":256,"config":661},{"href":258,"dataGaName":5,"dataGaLocation":488},{"text":251,"config":663},{"href":253,"dataGaName":254,"dataGaLocation":488},{"text":260,"config":665},{"href":262,"dataGaName":263,"dataGaLocation":488},{"text":273,"config":667},{"href":275,"dataGaName":276,"dataGaLocation":488},{"text":265,"config":669},{"href":267,"dataGaName":268,"dataGaLocation":488},{"text":278,"config":671},{"href":280,"dataGaName":281,"dataGaLocation":488},{"text":283,"config":673},{"href":285,"dataGaName":286,"dataGaLocation":488},{"text":288,"config":675},{"href":290,"dataGaName":291,"dataGaLocation":488},{"text":293,"config":677},{"href":295,"dataGaName":296,"dataGaLocation":488},{"title":311,"links":679},[680,682,684,686,688,690,692,696,701,703,705,707],{"text":318,"config":681},{"href":320,"dataGaName":313,"dataGaLocation":488},{"text":323,"config":683},{"href":325,"dataGaName":326,"dataGaLocation":488},{"text":331,"config":685},{"href":333,"dataGaName":334,"dataGaLocation":488},{"text":336,"config":687},{"href":338,"dataGaName":339,"dataGaLocation":488},{"text":341,"config":689},{"href":343,"dataGaName":344,"dataGaLocation":488},{"text":346,"config":691},{"href":348,"dataGaName":349,"dataGaLocation":488},{"text":693,"config":694},"Sustainability",{"href":695,"dataGaName":693,"dataGaLocation":488},"/sustainability/",{"text":697,"config":698},"Diversity, inclusion and belonging (DIB)",{"href":699,"dataGaName":700,"dataGaLocation":488},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":351,"config":702},{"href":353,"dataGaName":354,"dataGaLocation":488},{"text":361,"config":704},{"href":363,"dataGaName":364,"dataGaLocation":488},{"text":366,"config":706},{"href":368,"dataGaName":369,"dataGaLocation":488},{"text":708,"config":709},"Modern Slavery Transparency Statement",{"href":710,"dataGaName":711,"dataGaLocation":488},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":713},[714,716,718],{"text":538,"config":715},{"href":540,"dataGaName":541,"dataGaLocation":488},{"text":543,"config":717},{"href":545,"dataGaName":546,"dataGaLocation":488},{"text":548,"config":719},{"dataGaName":550,"dataGaLocation":488,"id":551,"isOneTrustButton":105},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[725],{"_path":726,"_dir":727,"_draft":6,"_partial":6,"_locale":7,"content":728,"config":732,"_id":734,"_type":28,"title":18,"_source":30,"_file":735,"_stem":736,"_extension":33},"/en-us/blog/authors/chris-moberly","authors",{"name":18,"config":729},{"headshot":730,"ctfId":731},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664235/Blog/Author%20Headshots/cmoberly-headshot.jpg","cmoberly",{"template":733},"BlogAuthor","content:en-us:blog:authors:chris-moberly.yml","en-us/blog/authors/chris-moberly.yml","en-us/blog/authors/chris-moberly",{"_path":738,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"header":739,"eyebrow":740,"blurb":741,"button":742,"secondaryButton":746,"_id":748,"_type":28,"title":749,"_source":30,"_file":750,"_stem":751,"_extension":33},"/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":44,"config":743},{"href":744,"dataGaName":47,"dataGaLocation":745},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":49,"config":747},{"href":51,"dataGaName":52,"dataGaLocation":745},"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":753,"content":754,"config":757,"_id":27,"_type":28,"title":29,"_source":30,"_file":31,"_stem":32,"_extension":33},{"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":755,"heroImage":11,"date":19,"body":20,"category":21,"tags":756},[18],[21,23],{"slug":25,"featured":6,"template":26},1761814433762]