Published on: March 4, 2026

10 min read

How GitLab built a security control framework from scratch

GitLab's Security Compliance team created a custom control framework to scale across multiple certifications and products — here's why and how you can, too.

GitLab's Security Compliance team discovered that existing security control frameworks lacked the customization to fit the platform's multi-product, cloud-native environment.

So we built our own.

Here's what we learned and why creating your own custom security control framework might be the right move for your compliance program.

The journey through frameworks

When I joined GitLab's Security Compliance team in November 2022, we were using the Secure Controls Framework to manage controls across our external certifications and internal compliance needs. But as our requirements grew, we realized we needed something more comprehensive.

With FedRAMP authorization on our roadmap, we chose to adopt NIST SP 800-53 next. NIST SP 800-53 includes more than 1,000 controls, but its comprehensiveness isn’t perfectly suited to GitLab’s environment.

We didn't need to implement every NIST control, only those applicable to our specific requirements. Our focus was on the quality of controls rather than quantity. Implementing unnecessary controls doesn't improve security; in fact, too many can make an environment less secure as individuals find ways to circumvent overly restrictive or irrelevant controls.

Some controls also lacked the necessary granularity for our needs. For example, NIST’s AC-2 “Account Management” control covers account creation and provisioning, account modification and disabling, account removal and termination, shared and group account management, and account monitoring and reviews.

In practice, these are at least six distinct controls with different owners, testing procedures, and risks. For attestations like SOC 2, each activity is tested as a separate control because they have different evidence requirements and operational contexts. NIST's all-encompassing AC-2 didn't match how we actually operate controls or how auditors actually assess us, and we needed controls granular enough to reflect our operational environment.

We found ourselves constantly customizing, adding, and adapting NIST controls to fit our environment. At some point, we realized we weren't really using NIST SP 800-53 anymore, we were building our own framework on top of it. We decided a custom control framework, one tailored to GitLab’s environment, would best accommodate our multi-product offering and each product’s unique compliance needs.

Building the GitLab Control Framework

Through five methodical steps, we built our own common controls framework: the GitLab Control Framework (GCF).

1. Analyze what we need

We reviewed our existing controls and mapped every requirement from external certifications we already maintained, certifications on our roadmap, and our internal compliance program:

External certifications:

  • SOC 2 Type II
  • ISO 27001, ISO 27017, ISO 27018, ISO 42001
  • PCI DSS
  • TISAX
  • Cyber Essentials
  • FedRAMP

Internal compliance needs:

  • Controls for mission-critical systems that are not in-scope for external certifications
  • Controls for systems with access to sensitive data

This gave us the baseline: what controls must exist to meet our compliance obligations.

2. Learn from industry frameworks

Next, we compared our requirements against industry-recognized frameworks:

  • NIST SP 800-53
  • NIST Cybersecurity Framework (CSF)
  • Secure Controls Framework (SCF)
  • Adobe and Cisco Common Controls Framework (CCF)

Having adopted frameworks in the past, we wanted to learn from their structure and ensure we weren't missing critical security domains, controls, or best practices.

3. Create custom control domains

Through this analysis, we created 18 custom control domains tailored to GitLab's environment:

AbbreviationDomainScope of controls
AAMAudit & Accountability ManagementLogging, monitoring, and maintaining audit trails of system activities
AIMArtificial Intelligence ManagementSpecific to AI system development, deployment, and governance
ASMAsset ManagementIdentifying, tracking, and managing organizational assets
BCABackups, Contingency, and Availability ManagementBusiness continuity, disaster recovery, and system availability
CHMChange ManagementManaging changes to systems, applications, and infrastructure
CSRCustomer Security Relationship ManagementCustomer communication, transparency, and security commitments
DPMData Protection ManagementProtecting data confidentiality, integrity, and privacy
EPMEndpoint ManagementSecuring end-user devices and workstations
GPMGovernance & Program ManagementSecurity governance, policies, and program oversight
IAMIdentity, Authentication, and Access ManagementUser identity, authentication mechanisms, and access control
INCIncident ManagementDetecting, responding to, and recovering from security incidents
ISMInfrastructure Security ManagementNetwork, server, and foundational infrastructure security
PASProduct and Application Security ManagementSecurity capabilities built into the GitLab product that are dogfooded to secure GitLab's own development, such as branch protection & code security scanning
PSMPeople Security ManagementPersonnel security, training, and awareness
SDLSoftware Development & Acquisition Life Cycle ManagementSecure SDLC practices and third-party software acquisition
SRMSecurity Risk ManagementRisk assessment, treatment, and management
TPRThird Party Risk ManagementManaging security risks from vendors and suppliers
TVMThreat & Vulnerability ManagementIdentifying and remediating security vulnerabilities



Each domain groups related controls into logical families that align with how GitLab's security program is actually organized and operated. This structure provides a methodical approach for adding, updating, or removing controls as our needs evolve.

4. Add context and data

With our domains defined, we needed to address two critical challenges: how to represent controls across multiple products without duplicating the framework, and how to capture meaningful implementation context to actually operate and audit at scale.

Scaling across multiple products

GitLab provides multiple product offerings: GitLab.com (multi-tenant SaaS on GCP), GitLab Dedicated (single-tenant SaaS on AWS), and GitLab Dedicated for Government (GitLab’s single-tenant FedRAMP offering on AWS). Each offering has different infrastructure, compliance scopes, and audit requirements. We needed to support product-specific audits without creating entirely separate frameworks.

We designed a control hierarchy where Level 1 controls are the framework, defining what should be implemented at the organizational level. Level 2 controls are the implementation, capturing the product-specific details of how each requirement is actually fulfilled.

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TD
    accTitle: Control Hierarchy
    accDescr: Level 1 requirements cascade to Level 2 implementations.
    
    L1["Level 1: Framework<br/>What must be implemented"];
    L2A["Level 2: GitLab.com<br/>How it's implemented"];
    L2B["Level 2: Dedicated<br/>How it's implemented"];
    L2C["Level 2: Dedicated for Gov<br/>How it's implemented"];
    L2D["Level 2: Entity<br/>(inherited by all)"];
    
    L1-->L2A;
    L1-->L2B;
    L1-->L2C;
    L1-->L2D;



This separation allows us to maintain one framework with product-specific implementations, rather than managing duplicate frameworks for each offering. Entity controls apply organization-wide and are inherited by GitLab.com, GitLab Dedicated, and GitLab Dedicated for Government.

Adding context to controls

Traditional control frameworks track minimal information: a control ID, description, and owner. The GCF takes a different approach and its superpower is the extensive metadata we track for each control. Beyond just stating the control description or implementation statement, we capture:

  • Control owner: Who is accountable for the control and its risk?
  • Environment: Does this apply organization-wide (Entity, inherited by all product offerings), to GitLab.com, or to Dedicated?
  • Assets: What specific systems does this control cover?
  • Frequency: How often is the control performed or tested?
  • Nature: Is it manual, semi-automated, or fully automated?
  • Classification: Is this for external certifications or internal risk?
  • Testing details: How do we assess it? What evidence do we collect?

This context transforms the GCF from a simple control list into an operationalized control inventory.

With this structure, we can answer questions like:

  • Which controls apply to GitLab.com for our SOC 2 audit vs. GitLab Dedicated? → Filter by environment: GitLab.com
  • What controls does the Infrastructure team own? → Filter by owner
  • Which controls can we automate? → Filter by nature: Manual

5. Iterate, mature, and scale

The GCF isn't static and was designed to evolve with our business and compliance landscape.

Pursuing new certifications

Because we've operationalized context into the GCF, we can quickly determine the scope and gaps when pursuing new certifications (ISMAP, IRAP, C5, etc.):

  1. Determine scope: Which product has the business need (GitLab.com, GitLab Dedicated, or both)?
  2. Map requirements: Do existing controls already cover the new certification requirements?
  3. Identify gaps: What new controls need to be created?
  4. Update mappings: Link existing controls to the new certification requirements.

Adapting to new regulations

When new regulations emerge or existing requirements change:

  • Review existing controls: Does an existing control already cover the new requirement?
  • Update or create: Either update existing control language or create a new control.
  • Apply the most stringent: When multiple certifications have similar requirements, we implement the most stringent version — secure once, comply with many.
  • Map across certifications: Link the control to all relevant certification requirements.

Managing control lifecycle

The framework adapts to various changes:

  • Requirement changes: When certifications update their requirements, we review impacted controls and update descriptions or mappings.
  • Deprecated controls: If a requirement is removed or a control is no longer needed, we mark it as deprecated and remove it from our monitoring schedule.
  • New risks identified: Risk assessments may identify gaps requiring new internal controls.

The power of common controls: One control, multiple requirements

Securing once and complying with many isn't just a principle, it has tangible benefits across how we prepare for audits, support control owners, and pursue new certifications. Here's what that looks like in practice, both qualitatively and in the numbers.

Qualitative results

Since implementing the GCF, we've seen significant improvements in how we manage compliance:

Integrated audit approach

The GCF enables us to maintain one framework with controls mapped to multiple certification requirements, instead of managing separate control sets for each audit. One control can satisfy SOC 2, ISO 27001, and PCI DSS requirements simultaneously.

Faster audit preparation

Through the GCF, we maintain one consolidated request list instead of separate lists for each audit. Because we've defined controls with specific context, our request lists say "Okta user list" instead of generic "production user list," eliminating ambiguity and interpretation. We're not collecting “N/A” evidence or leaving it up to auditors to interpret what "production" means in our environment. Everything is already scoped to our actual systems.

Reduced stakeholder burden

This integration directly reduces burden on our stakeholders. Control owners provide evidence once instead of responding to separate requests from SOC 2, ISO, and PCI auditors. When we collect evidence for access controls, it satisfies SOC 2, ISO 27001, and PCI DSS requirements simultaneously. One control, one test, one piece of evidence with multiple certifications and requirements satisfied.

Efficient gap assessments

When pursuing new certifications or launching new features, the operationalized context enables more efficient gap analysis. We can determine which controls already exist, what's missing, and what implementation is required.

Quantifiable results

Control efficiency:

  • Reduced SOC controls by 58% (200 controls → 84) for GitLab.com and 55% (181 → 82) for GitLab Dedicated
  • One framework now supports 8+ certifications

Audit efficiency:

  • Consolidated 4 audit request lists into 1, reducing requests by 44% (415 → 231)
  • 95% evidence acceptance rate before fieldwork for recent PCI audits

Framework scale:

  • 220+ active controls across 18 custom domains
  • Mapped to 1,300+ certification requirements
  • Supports multiple product offerings

The path forward

The GCF continues to evolve as we add security and AI controls, pursue new certifications, and refine our approach.

For security compliance practitioners: Don't be afraid to build your own framework if industry standards don't fit. The upfront investment pays dividends in scalability, efficiency, and controls that actually make sense for your environment. Sometimes the best framework is the one you design yourself.

If you found this helpful, check out our complete GitLab Control Framework documentation, where we detail our framework methodology, control domains, and field structures.

We want to hear from you

Enjoyed reading this blog post or have questions or feedback? Share your thoughts by creating a new topic in the GitLab community forum.

Share your feedback

Start building faster today

See what your team can do with the intelligent orchestration platform for DevSecOps.