[{"data":1,"prerenderedAt":702},["ShallowReactive",2],{"/en-us/blog/monitor-web-attack-surface-with-gitlab/":3,"navigation-en-us":34,"banner-en-us":451,"footer-en-us":463,"Chris Moberly":674,"next-steps-en-us":687},{"_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","\n\n_DISCLAIMER: We believe that understanding the tactics and techniques of both attackers and defenders is key to keeping our organization secure. It's important to note that GitLab security blog posts are for informational purposes only, not to provide specific security advice._\n\nAttackers love insecure web applications. Lucky for them, these applications are everywhere! Test environments, development instances, default installations with hardcoded passwords - you name it, it's out there somewhere waiting to be exploited.\n\nThe easier it becomes to deploy resources in the cloud, the more of these insecure web applications end up exposed to hacking and/or unintended access. You can get ahead of potential threats by proactively identifying and reviewing your own web application attack surface.\n\nIn this tutorial, we'll explain how you can monitor the web applications in your environment by generating a screenshot report using GitLab CI/CD, GitLab Pages, and a handful of free and open source security tools. You'll end up with a fully automated solution that can:\n\n- Identify web services on a list of addresses you own.\n- Capture screenshots of these web services.\n- Build an authenticated web portal for you to visually see each site that was discovered.\n\n## Building the solution\n\n### Start with a project\n\nInside the GitLab web interface, [create a blank project](https://gitlab.com/projects/new#blank_project). The default settings should be fine, but you should review to confirm that the default settings are appropriate. Pay particular attention to the \"Visibility Level\" - you may want to set this to private.\n\n![Creating a GitLab project](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-project.png){: .shadow.medium.center}\n\n\n\n### Write the automation scripts\n\nWe'll use three scripts in this project:\n\n-  `setup.sh`: Install the required tooling.\n- `discover-services.sh`: Identify web services using [httpx](https://github.com/projectdiscovery/httpx).\n- `take-screenshots.sh`: Use [gowitness](https://github.com/sensepost/gowitness) to generate a static website containing screenshots of each identified web service.\n\nThe HTML generated by gowitness will be placed into the `public` folder, which is used by [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/) to generate a website you can click through to review the findings.\n\nEach script will generate output files which may be useful for additional analysis. These will be made available as GitLab [job artifacts](https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html), so that you can download and review them at will.\n\nTo complete this step, first create a new folder in your project called `scripts`. Then, add the following files into that folder:\n\n#### setup.sh\n\n```bash\n#!/bin/bash\n\n# create folder for downloaded binaries\nmkdir bin\n\n# install general pre-reqs\napt -qq update > /dev/null\napt -qq install -y wget unzip > /dev/null\n\n# install pre-reqs for gowitness\napt -qq install -y chromium > /dev/null\n\n# download tools\nwget -q https://github.com/projectdiscovery/httpx/releases/download/v1.2.5/httpx_1.2.5_linux_amd64.zip\nwget -q https://github.com/sensepost/gowitness/releases/download/2.4.2/gowitness-2.4.2-linux-amd64\n\n# unzip / move all relases to bin folder\nunzip httpx_1.2.5_linux_amd64.zip -d bin/\nmv gowitness-2.4.2-linux-amd64 bin/gowitness\nchmod u+x bin/gowitness\n```\n\n#### discover-services.sh\n\n```bash\n#!/bin/bash\n\n# You may want to dynamically generate a target file with each run.\n# For this demo, we are using a list defined inside project CI variables.\nTARGETS=$TARGET_FILE\n\n# create output directory\nmkdir ./targets\n\n# Identify web services\necho \"Identifying web services across $(cat \"$TARGETS\" | wc -l) targets...\"\ncat \"$TARGETS\" | bin/httpx -o targets/web-services.txt -p 80,443\n\necho \"Discovered $(cat targets/web-services.txt | wc -l) web services.\"\n```\n\n#### take-screenshots.sh\n\n```bash\n#!/bin/bash\n\n# Run gowitness\nbin/gowitness file -f targets/web-services.txt\nbin/gowitness report export -f report.zip\n\n# Move the report to pages outdir\nunzip report.zip\nmv gowitness public\n```\n\n\n\n### Set up the pipeline\n\nNext, we need to create the `.gitlab-ci.yml` file where we configure all of these scripts to run inside a [pipeline](https://docs.gitlab.com/ee/ci/pipelines/). Create this file in the root of the project with the following contents:\n\n```yaml\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\nThis file defines a pipeline with two stages:\n\n- The first stage (`scan`) runs all three scripts we created. This will generate a static website inside a folder called `public`.\n- The second stage (`deploy`) is required for GitLab Pages to work - this is where the static site is published on a publicly-accessible URL that can be configured to require GitLab authentication.\n\nYou can see we've added an `only` condition to both of these stages. This ensures that the tool doesn't run every time you make a change to the code - it runs only on a defined schedule or when you manually choose to run it via the web UI.\n\n### Define your targets\n\nYou may have noticed the `TARGETS_FILE` variable inside the `discover-services.sh` script from earlier. That's a [file variable](https://docs.gitlab.com/ee/ci/variables/#cicd-variable-types) that will contain the targets you wish to scan. Defining this as a variable allows us to create a generic, portable project that can be forked and cloned without containing any specific targets.\n\nTo add some targets to your project, go to \"Settings -> CI/CD -> Variables\" and click the \"Add variable\" button. Enter `TARGET_FILE` for the \"Key\" and fill in one host name or IP address per line in the \"Value\" section. Make sure to add a blank line to the end of the list - this is required for the scripts to run correctly.\n\n![Creating a CI environment variable](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-create-variable.png){: .shadow.center}\n\n\nWe run a similar version of this screenshot tool internally, and we generate this file dynamically by exporting all of our public addresses from our various cloud environments. If you decide to implement something like that, we'd recommend adding an additional stage to your `.gitlab-ci.yaml` file.\n\n### Schedule and run the pipeline\n\nGitLab projects have a built-in [scheduler](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) that lets you automatically run pipelines at specific dates/times. You can access this inside your project at \"CI/CD -> Schedules\". Here, we'll create a new schedule to run once a week on Monday mornings.\n\n![Creating a CI schedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-schedule.png){: .shadow.center}\n\n\nAfter saving the schedule, you can also choose to manually run the pipeline by clicking the play button shown below. If you are following along, go ahead and do this now.\n\n![Running a CI schedule](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-play.png){: .shadow.center}\n\n\nYou can follow the progress of your pipeline by navigating to \"CI/CD -> Pipelines\". Click on the status of the most recent pipeline. Here, you'll see the stages we configured earlier.  If all goes well, you'll see green check marks on each stage. You can click on an individual stage to watch the console logs and perform any necessary troubleshooting.\n\n![CI pipeline success icons](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-success.png){: .shadow.center}\n\n\n### Enable notifications\n\nOnce you've set up a schedule, you might want to be alerted whenever a new report is ready. Luckily, GitLab has you covered here!\n\nInside your project, go to \"Settings -> Integrations -> Pipeline Status Emails\". Put your email address into the \"Recipients\" field and uncheck the box \"Notify only broken pipelines\". This will send you an email each time a pipeline completes and a new screenshot report has been published to your GitLab Pages site.\n\nGitLab offers a slew of other notifcation options as well, including things like Slack and Teams. If you prefer one of those, you can [read more in the docs](https://docs.gitlab.com/ee/integration/).\n\n![Create pipeline notifications](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-notifications.png){: .shadow.center}\n\n\n### View your GitLab Pages site\n\nOnce the pipeline has completed successfully, your site should be available. You can obtain the site's public address by going to \"Settings -> Pages\".\n\nIf you set your project to be private, then by default only project members who are authenticated to the GitLab server can view the site. You can modify these settings under \"Settings -> General -> Visibility, project features, permissions -> Pages\".\n\n![Screenshot of gowitness interface](https://about.gitlab.com/images/blogimages/2023-01-17-monitor-web-attack-surface-with-gitlab/screenshot-gowitness.png){: .shadow.center}\n\n\n## Summary\n\nWeb applications are everywhere. Often, they are deployed with vulnerable configurations and are left forgotten - unmonitored and awaiting exploitation. You can build a monitoring solution using GitLab and free, open-source tools that gives you a visual overview of the web apps running in your own environment.\n\nThis blog walked you through manually setting this up yourself. You can view our example project [here](https://gitlab.com/gitlab-com/gl-security/threatmanagement/redteam/redteam-public/webapp-screenshots), which was created exactly as decribed above. Feel free to fork or clone that project as a shortcut to setting it up from scratch yourself.\n\nWe love to find creative uses for GitLab, and this is one we use ourselves internally. If you've come up with some of your own interesting use cases, we would love to hear about them! Or, if there is anything else you'd like our security team to write about, please do let us know! You can share your thoughts in the comments below or via issues and merge requests on any of our projects.\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":447,"_type":28,"title":448,"_source":30,"_file":449,"_stem":450,"_extension":33},"/shared/en-us/main-navigation","en-us",{"logo":38,"freeTrial":43,"sales":48,"login":53,"items":58,"search":388,"minimal":419,"duo":438},{"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,199,204,309,369],{"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":181},"Product",true,{"dataNavLevelOne":107},"solutions",{"text":109,"config":110},"View all Solutions",{"href":111,"dataGaName":107,"dataGaLocation":42},"/solutions/",[113,138,160],{"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/security-compliance/","security and compliance","ShieldCheckLight",[147,150,155],{"text":148,"config":149},"Security & Compliance",{"href":143,"dataGaLocation":42,"dataGaName":148},{"text":151,"config":152},"Software Supply Chain Security",{"href":153,"dataGaLocation":42,"dataGaName":154},"/solutions/supply-chain/","Software supply chain security",{"text":156,"config":157},"Compliance & Governance",{"href":158,"dataGaLocation":42,"dataGaName":159},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":161,"link":162,"items":167},"Measurement",{"config":163},{"icon":164,"href":165,"dataGaName":166,"dataGaLocation":42},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[168,172,176],{"text":169,"config":170},"Visibility & Measurement",{"href":165,"dataGaLocation":42,"dataGaName":171},"Visibility and Measurement",{"text":173,"config":174},"Value Stream Management",{"href":175,"dataGaLocation":42,"dataGaName":173},"/solutions/value-stream-management/",{"text":177,"config":178},"Analytics & Insights",{"href":179,"dataGaLocation":42,"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":42,"dataGaName":188},"/enterprise/","enterprise",{"text":190,"config":191},"Small Business",{"href":192,"dataGaLocation":42,"dataGaName":193},"/small-business/","small business",{"text":195,"config":196},"Public Sector",{"href":197,"dataGaLocation":42,"dataGaName":198},"/solutions/public-sector/","public sector",{"text":200,"config":201},"Pricing",{"href":202,"dataGaName":203,"dataGaLocation":42,"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":42},"/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":42},"/install/","install",{"text":222,"config":223},"Quick start guides",{"href":224,"dataGaName":225,"dataGaLocation":42},"/get-started/","quick setup checklists",{"text":227,"config":228},"Learn",{"href":229,"dataGaLocation":42,"dataGaName":230},"https://university.gitlab.com/","learn",{"text":232,"config":233},"Product documentation",{"href":234,"dataGaName":235,"dataGaLocation":42},"https://docs.gitlab.com/","product documentation",{"text":237,"config":238},"Best practice videos",{"href":239,"dataGaName":240,"dataGaLocation":42},"/getting-started-videos/","best practice videos",{"text":242,"config":243},"Integrations",{"href":244,"dataGaName":245,"dataGaLocation":42},"/integrations/","integrations",{"title":247,"items":248},"Discover",[249,254,258,263],{"text":250,"config":251},"Customer success stories",{"href":252,"dataGaName":253,"dataGaLocation":42},"/customers/","customer success stories",{"text":255,"config":256},"Blog",{"href":257,"dataGaName":5,"dataGaLocation":42},"/blog/",{"text":259,"config":260},"Remote",{"href":261,"dataGaName":262,"dataGaLocation":42},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":264,"config":265},"TeamOps",{"href":266,"dataGaName":267,"dataGaLocation":42},"/teamops/","teamops",{"title":269,"items":270},"Connect",[271,276,281,286,291],{"text":272,"config":273},"GitLab Services",{"href":274,"dataGaName":275,"dataGaLocation":42},"/services/","services",{"text":277,"config":278},"Community",{"href":279,"dataGaName":280,"dataGaLocation":42},"/community/","community",{"text":282,"config":283},"Forum",{"href":284,"dataGaName":285,"dataGaLocation":42},"https://forum.gitlab.com/","forum",{"text":287,"config":288},"Events",{"href":289,"dataGaName":290,"dataGaLocation":42},"/events/","events",{"text":292,"config":293},"Partners",{"href":294,"dataGaName":295,"dataGaLocation":42},"/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},"/images/navigation/the-source-promo-card.svg",{"text":305,"config":306},"Read the latest",{"href":307,"dataGaName":308,"dataGaLocation":42},"/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":42},"/company/","about",{"text":322,"config":323,"footerGa":326},"Jobs",{"href":324,"dataGaName":325,"dataGaLocation":42},"/jobs/","jobs",{"dataGaName":325},{"text":287,"config":328},{"href":289,"dataGaName":290,"dataGaLocation":42},{"text":330,"config":331},"Leadership",{"href":332,"dataGaName":333,"dataGaLocation":42},"/company/team/e-group/","leadership",{"text":335,"config":336},"Team",{"href":337,"dataGaName":338,"dataGaLocation":42},"/company/team/","team",{"text":340,"config":341},"Handbook",{"href":342,"dataGaName":343,"dataGaLocation":42},"https://handbook.gitlab.com/","handbook",{"text":345,"config":346},"Investor relations",{"href":347,"dataGaName":348,"dataGaLocation":42},"https://ir.gitlab.com/","investor relations",{"text":350,"config":351},"Trust Center",{"href":352,"dataGaName":353,"dataGaLocation":42},"/security/","trust center",{"text":355,"config":356},"AI Transparency Center",{"href":357,"dataGaName":358,"dataGaLocation":42},"/ai-transparency-center/","ai transparency center",{"text":360,"config":361},"Newsletter",{"href":362,"dataGaName":363,"dataGaLocation":42},"/company/contact/","newsletter",{"text":365,"config":366},"Press",{"href":367,"dataGaName":368,"dataGaLocation":42},"/press/","press",{"text":370,"config":371,"lists":372},"Contact us",{"dataNavLevelOne":312},[373],{"items":374},[375,378,383],{"text":49,"config":376},{"href":51,"dataGaName":377,"dataGaLocation":42},"talk to sales",{"text":379,"config":380},"Get help",{"href":381,"dataGaName":382,"dataGaLocation":42},"/support/","get help",{"text":384,"config":385},"Customer portal",{"href":386,"dataGaName":387,"dataGaLocation":42},"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":56,"dataGaName":395,"dataGaLocation":396},"search login","search",{"text":398,"default":399},"Suggestions",[400,402,406,408,412,416],{"text":71,"config":401},{"href":76,"dataGaName":71,"dataGaLocation":396},{"text":403,"config":404},"Code Suggestions (AI)",{"href":405,"dataGaName":403,"dataGaLocation":396},"/solutions/code-suggestions/",{"text":123,"config":407},{"href":125,"dataGaName":123,"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":84,"dataGaName":417,"dataGaLocation":396},{"freeTrial":420,"mobileIcon":425,"desktopIcon":430,"secondaryButton":433},{"text":421,"config":422},"Start free trial",{"href":423,"dataGaName":47,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Gitlab Icon",{"src":428,"dataGaName":429,"dataGaLocation":424},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"/images/brand/gitlab-logo-type.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":76,"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},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":452,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"title":453,"button":454,"config":458,"_id":460,"_type":28,"_source":30,"_file":461,"_stem":462,"_extension":33},"/shared/en-us/banner","GitLab Duo Agent Platform is now in public beta!",{"text":82,"config":455},{"href":456,"dataGaName":457,"dataGaLocation":42},"/gitlab-duo/agent-platform/","duo banner",{"layout":459},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":464,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"data":465,"_id":670,"_type":28,"title":671,"_source":30,"_file":672,"_stem":673,"_extension":33},"/shared/en-us/main-footer",{"text":466,"source":467,"edit":473,"contribute":478,"config":483,"items":488,"minimal":662},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":468,"config":469},"View page source",{"href":470,"dataGaName":471,"dataGaLocation":472},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":474,"config":475},"Edit this page",{"href":476,"dataGaName":477,"dataGaLocation":472},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":479,"config":480},"Please contribute",{"href":481,"dataGaName":482,"dataGaLocation":472},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":484,"facebook":485,"youtube":486,"linkedin":487},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[489,512,569,598,632],{"title":60,"links":490,"subMenu":495},[491],{"text":492,"config":493},"DevSecOps platform",{"href":69,"dataGaName":494,"dataGaLocation":472},"devsecops platform",[496],{"title":200,"links":497},[498,502,507],{"text":499,"config":500},"View plans",{"href":202,"dataGaName":501,"dataGaLocation":472},"view plans",{"text":503,"config":504},"Why Premium?",{"href":505,"dataGaName":506,"dataGaLocation":472},"/pricing/premium/","why premium",{"text":508,"config":509},"Why Ultimate?",{"href":510,"dataGaName":511,"dataGaLocation":472},"/pricing/ultimate/","why ultimate",{"title":513,"links":514},"Solutions",[515,520,523,525,530,535,539,542,546,551,553,556,559,564],{"text":516,"config":517},"Digital transformation",{"href":518,"dataGaName":519,"dataGaLocation":472},"/topics/digital-transformation/","digital transformation",{"text":148,"config":521},{"href":143,"dataGaName":522,"dataGaLocation":472},"security & compliance",{"text":137,"config":524},{"href":119,"dataGaName":120,"dataGaLocation":472},{"text":526,"config":527},"Agile development",{"href":528,"dataGaName":529,"dataGaLocation":472},"/solutions/agile-delivery/","agile delivery",{"text":531,"config":532},"Cloud transformation",{"href":533,"dataGaName":534,"dataGaLocation":472},"/topics/cloud-native/","cloud transformation",{"text":536,"config":537},"SCM",{"href":133,"dataGaName":538,"dataGaLocation":472},"source code management",{"text":123,"config":540},{"href":125,"dataGaName":541,"dataGaLocation":472},"continuous integration & delivery",{"text":543,"config":544},"Value stream management",{"href":175,"dataGaName":545,"dataGaLocation":472},"value stream management",{"text":547,"config":548},"GitOps",{"href":549,"dataGaName":550,"dataGaLocation":472},"/solutions/gitops/","gitops",{"text":185,"config":552},{"href":187,"dataGaName":188,"dataGaLocation":472},{"text":554,"config":555},"Small business",{"href":192,"dataGaName":193,"dataGaLocation":472},{"text":557,"config":558},"Public sector",{"href":197,"dataGaName":198,"dataGaLocation":472},{"text":560,"config":561},"Education",{"href":562,"dataGaName":563,"dataGaLocation":472},"/solutions/education/","education",{"text":565,"config":566},"Financial services",{"href":567,"dataGaName":568,"dataGaLocation":472},"/solutions/finance/","financial services",{"title":205,"links":570},[571,573,575,577,580,582,584,586,588,590,592,594,596],{"text":217,"config":572},{"href":219,"dataGaName":220,"dataGaLocation":472},{"text":222,"config":574},{"href":224,"dataGaName":225,"dataGaLocation":472},{"text":227,"config":576},{"href":229,"dataGaName":230,"dataGaLocation":472},{"text":232,"config":578},{"href":234,"dataGaName":579,"dataGaLocation":472},"docs",{"text":255,"config":581},{"href":257,"dataGaName":5,"dataGaLocation":472},{"text":250,"config":583},{"href":252,"dataGaName":253,"dataGaLocation":472},{"text":259,"config":585},{"href":261,"dataGaName":262,"dataGaLocation":472},{"text":272,"config":587},{"href":274,"dataGaName":275,"dataGaLocation":472},{"text":264,"config":589},{"href":266,"dataGaName":267,"dataGaLocation":472},{"text":277,"config":591},{"href":279,"dataGaName":280,"dataGaLocation":472},{"text":282,"config":593},{"href":284,"dataGaName":285,"dataGaLocation":472},{"text":287,"config":595},{"href":289,"dataGaName":290,"dataGaLocation":472},{"text":292,"config":597},{"href":294,"dataGaName":295,"dataGaLocation":472},{"title":310,"links":599},[600,602,604,606,608,610,612,616,621,623,625,627],{"text":317,"config":601},{"href":319,"dataGaName":312,"dataGaLocation":472},{"text":322,"config":603},{"href":324,"dataGaName":325,"dataGaLocation":472},{"text":330,"config":605},{"href":332,"dataGaName":333,"dataGaLocation":472},{"text":335,"config":607},{"href":337,"dataGaName":338,"dataGaLocation":472},{"text":340,"config":609},{"href":342,"dataGaName":343,"dataGaLocation":472},{"text":345,"config":611},{"href":347,"dataGaName":348,"dataGaLocation":472},{"text":613,"config":614},"Sustainability",{"href":615,"dataGaName":613,"dataGaLocation":472},"/sustainability/",{"text":617,"config":618},"Diversity, inclusion and belonging (DIB)",{"href":619,"dataGaName":620,"dataGaLocation":472},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":350,"config":622},{"href":352,"dataGaName":353,"dataGaLocation":472},{"text":360,"config":624},{"href":362,"dataGaName":363,"dataGaLocation":472},{"text":365,"config":626},{"href":367,"dataGaName":368,"dataGaLocation":472},{"text":628,"config":629},"Modern Slavery Transparency Statement",{"href":630,"dataGaName":631,"dataGaLocation":472},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":633,"links":634},"Contact Us",[635,638,640,642,647,652,657],{"text":636,"config":637},"Contact an expert",{"href":51,"dataGaName":52,"dataGaLocation":472},{"text":379,"config":639},{"href":381,"dataGaName":382,"dataGaLocation":472},{"text":384,"config":641},{"href":386,"dataGaName":387,"dataGaLocation":472},{"text":643,"config":644},"Status",{"href":645,"dataGaName":646,"dataGaLocation":472},"https://status.gitlab.com/","status",{"text":648,"config":649},"Terms of use",{"href":650,"dataGaName":651,"dataGaLocation":472},"/terms/","terms of use",{"text":653,"config":654},"Privacy statement",{"href":655,"dataGaName":656,"dataGaLocation":472},"/privacy/","privacy statement",{"text":658,"config":659},"Cookie preferences",{"dataGaName":660,"dataGaLocation":472,"id":661,"isOneTrustButton":105},"cookie preferences","ot-sdk-btn",{"items":663},[664,666,668],{"text":648,"config":665},{"href":650,"dataGaName":651,"dataGaLocation":472},{"text":653,"config":667},{"href":655,"dataGaName":656,"dataGaLocation":472},{"text":658,"config":669},{"dataGaName":660,"dataGaLocation":472,"id":661,"isOneTrustButton":105},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[675],{"_path":676,"_dir":677,"_draft":6,"_partial":6,"_locale":7,"content":678,"config":682,"_id":684,"_type":28,"title":18,"_source":30,"_file":685,"_stem":686,"_extension":33},"/en-us/blog/authors/chris-moberly","authors",{"name":18,"config":679},{"headshot":680,"ctfId":681},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664235/Blog/Author%20Headshots/cmoberly-headshot.jpg","cmoberly",{"template":683},"BlogAuthor","content:en-us:blog:authors:chris-moberly.yml","en-us/blog/authors/chris-moberly.yml","en-us/blog/authors/chris-moberly",{"_path":688,"_dir":36,"_draft":6,"_partial":6,"_locale":7,"header":689,"eyebrow":690,"blurb":691,"button":692,"secondaryButton":696,"_id":698,"_type":28,"title":699,"_source":30,"_file":700,"_stem":701,"_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":693},{"href":694,"dataGaName":47,"dataGaLocation":695},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":49,"config":697},{"href":51,"dataGaName":52,"dataGaLocation":695},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753475342737]