# SCM, CI/ CD and Container Registry tokens

### Why are these tokens required? <a href="#why_are_these_tokens_required" id="why_are_these_tokens_required"></a>

Our scanner performs checks against your SCM, CI/ CD systems and container registries to recover information about your repository and organization, as part of the scanning process to validate if there are misconfigurations affecting them.

For image scanning, authentication with the container registry for pulling the image may require credentials, often in the form of access tokens.

For that, it is important to provide tokens with the permissions allowing the scanner to collect the data needed for analyses.

### Required token permissions <a href="#required_token_permissions" id="required_token_permissions"></a>

{% tabs %}
{% tab title="GitHub" %}
For GitHub <img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FU1c5GDS2VsrUVkFZfZxE%2Fimage.png?alt=media&#x26;token=0fed249c-8d74-4111-803b-3a536157a63e" alt="" data-size="line">, these are the required token permissions/ scopes:

* enterprise: read
* org: admin
* packages: read
* project: read
* repo: full
* repo\_hook: read
* user: read

See [Creating a GH PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) if you have doubts about setting up a Personal Access Token.
{% endtab %}

{% tab title="Azure DevOps   " %}
For Azure Devops <img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FZjrmzy8V5HjNiYGnvl3f%2Fimage.png?alt=media&#x26;token=9a1311e5-5f65-4bdf-89b1-ad8d72095a58" alt="" data-size="line">, these are the required token permissions/ scopes:

* Build: Read
* Code: Read, Status
* Extensions: Read
* Graph: Read
* Identity: Read
* Packaging: Read
* Project and Team: Read
* Release: Read
* Security: Manage

See [Creating a PAT](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops\&tabs=Windows) if you have doubts about setting up a Personal Access Token.

See [Create a token with repository-scoped permissions](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-repository-scoped-permissions) for further information about permissions for pulling images under a repository, if you need to scan private images pushed into Azure CR registry.
{% endtab %}

{% tab title="BitBucket" %}
For Bitbucket <img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FDbwJ8PSR31jZLMBctoUS%2Fimage.png?alt=media&#x26;token=fda81857-c191-4d0f-9ca5-0cf3e767b42f" alt="" data-size="line">, these are the required token permissions/ scopes:

* Account: Read
* Pipelines: Read
* Projects: Read
* Pull Requests: Read
* Repositories: Admin
* Runners: Read
* Webhooks: Read and Write
* Workspace membership: Read

See [Using Workspace Access Tokens](https://support.atlassian.com/bitbucket-cloud/docs/using-workspace-access-tokens) and [App Passwords](https://support.atlassian.com/bitbucket-cloud/docs/app-passwords) if you have doubts about setting up a Bitbucket token.
{% endtab %}

{% tab title="GitLab" %}
For GitLab <img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FRYW1gHKEvi6fkfYHJOWL%2Fimage.png?alt=media&#x26;token=b4df5e8d-6077-45e5-9dcd-536329d54923" alt="" data-size="line">, these are the required token permissions/ scopes:

* api
* read\_api
* read\_user
* read\_repository
* read\_registry

See [Creating a GitLab PAT](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) if you have doubts about setting up a Personal Access Token.
{% endtab %}

{% tab title="Gitea" %}
For Gitea <img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FhwEebElZJnJPRWppztml%2Fgitea.svg?alt=media&#x26;token=a66a22b5-50e0-4d07-b6e3-8ac58f8e3768" alt="" data-size="line"> , these are the required token permissions:

* Organization: Read
* Package: Read
* Repository: Read
* User: Read
  {% endtab %}
  {% endtabs %}

### Providing the token

Navigate to your scanner folder and look at the file `conf/xygeni.yml`. Under the `scm`, `cicd` and `containerRegistry` elements you are going to discover the currently available systems and how to provide their tokens to the scanner. This is done in entries under `tokenSources`. Each token source is tested until a valid token is found. Token sources could be an environment variable, a local file, or a hardcoded value (not recommended).

{% hint style="info" %}
Usually, the preferred option is to pass the token in an `environment variable` (like GITHUB\_TOKEN or GITLAB\_TOKEN).
{% endhint %}

For example, in the case of GitHub, you can make the GitHub PAT available for Xygeni Scanner either by setting `GITHUB_TOKEN` or `GITHUB_PAT` environment variables, or storing it into a file named `${user.home}/.github.token` or `${XYGENI_DIR}/conf/.github.token` (in this latter case, `XYGENI_DIR` env var should be set)

```yaml
kind: github
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITHUB_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITHUB_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITHUB_TOKEN}
      - ${GITHUB_PAT}
      - file:${user.home}/.github.token
      - file:${XYGENI_DIR}/conf/.github.token
```

You can find a full reference of `conf/xygeni.yml` [here](#full-reference-of-conf-xygeni.yml)

{% hint style="info" %}
In the case of **Jenkins**, you must set some additional env variables:

* `JENKINS_URL` (your Jenkins base URL)
* `JENKINS_USER` (the Jenkins username to connect to the Jenkins API)
  {% endhint %}

### Full reference of `conf/xygeni.yml`

```yaml
# List of different Source Code Management (SCM) systems
# supporting projects for the organization
scm:
  # One of: github, azure_devops, bitbucket, gitlab.
  -
    kind: github
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITHUB_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITHUB_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITHUB_TOKEN}
      - ${GITHUB_PAT}
      - file:${user.home}/.github.token
      - file:${XYGENI_DIR}/conf/.github.token
  -
    kind: azure_devops
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${AZURE_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${AZURE_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${AZURE_TOKEN}
      - ${AZURE_PAT}
      - file:${user.home}/.azure.token
      - file:${XYGENI_DIR}/conf/.azure.token
  -
    kind: bitbucket
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${BITBUCKET_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${BITBUCKET_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${BITBUCKET_TOKEN}
      - ${BITBUCKET_PAT}
      - file:${user.home}/.bitbucket.token
      - file:${XYGENI_DIR}/conf/.bitbucket.token
  -
    kind: gitlab
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITLAB_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITLAB_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITLAB_TOKEN}
      - ${GITLAB_PAT}
      - file:${user.home}/.gitlab.token
      - file:${XYGENI_DIR}/conf/.gitlab.token
  -
    kind: github_enterprise
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITHUB_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITHUB_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITHUB_TOKEN}
      - ${GITHUB_PAT}
      - file:${user.home}/.github.token
      - file:${XYGENI_DIR}/conf/.github.token
    baseApiUrl: ${GITHUB_BASE_URL}
  -
    kind: bitbucket_server
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${BITBUCKET_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${BITBUCKET_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${BITBUCKET_TOKEN}
      - ${BITBUCKET_PAT}
      - file:${user.home}/.bitbucket.token
      - file:${XYGENI_DIR}/conf/.bitbucket.token
    baseApiUrl: ${BITBUCKET_BASE_URL}
  -
    kind: gitlab_enterprise
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITLAB_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITLAB_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITLAB_TOKEN}
      - ${GITLAB_PAT}
      - file:${user.home}/.gitlab.token
      - file:${XYGENI_DIR}/conf/.gitlab.token
    baseApiUrl: ${GITLAB_BASE_URL}
  -
    kind: gitea # For both Gitea Standard and Gitea Enterprise
    # Which projects are held in this SCM?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given scm kind)
    usedBy: ${GITEA_USED_BY}
    # The (optional) default username to connect to the SCM API.
    # If not given it could be extracted from the repository URL, when available.
    user: ${GITEA_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${GITEA_TOKEN}
      - ${GITEA_PAT}
      - file:${user.home}/.gitea.token
      - file:${XYGENI_DIR}/conf/.gitea.token
    baseApiUrl: ${GITEA_BASE_URL}
# CI/CD tools used, if you dont configure this, the system will assume that the SCM is used as CI/CD tool.
cicd:
  -
    kind: jenkins
    # Jenkins base URL
    url: ${JENKINS_URL}
    # Which projects use this CI/CD system?
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching any project for the given jenkins kind
    usedBy: ${JENKINS_USED_BY}
    # The username to connect to the CI/CD API.
    user: ${JENKINS_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${JENKINS_TOKEN}
      - file:${user.home}/.jenkins.token
      - file:${XYGENI_DIR}/conf/.jenkins.token
  -
    kind: circle_ci
    # CircleCI base URL
    url: '${CIRCLECI_URL:-https://circleci.com/api/}'
    tokenSources:
      - ${CIRCLECI_TOKEN}
      - file:${user.home}/.circleci.token


# Container (OCI) Registries
containerRegistry:
  -
    # Docker Hub
    # The hostname to match in the image name. This is the default when no hostname provided.
    hostname: '${DOCKER_HOST:-docker.io}'
    # Docker registry official URL
    url: '${DOCKER_URL:-https://registry-1.docker.io}'
    # Which projects use this registry? A hostname is often given in the image name.
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching by hostname.
    usedBy: ${DOCKER_USED_BY}
    # The username to connect to the registry api.
    user: ${DOCKER_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${DOCKER_TOKEN}
      - file:${user.home}/.docker.token
  -
    # The hostname to match in the image name. This is the default when no hostname provided.
    # For private registry, copy this using <aws_account>.dk.ecr.<region>.amazonaws.com as hostname,
    # or use wildcards like *.dk.ecr.*.amazonaws.com
    hostname: '${AWS_ECR_HOST:-public.ecr.aws}'
    # Docker registry official
    url: '${AWS_ECR_URL:-https://public.ecr.aws}'
    # Which projects use this registry? A hostname is often given in the image name.
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching by hostname.
    usedBy: ${AWS_ECR_USED_BY}
    # The username to connect to the registry api. ECR uses a fixed name.
    user: ${AWS_ECR_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${AWS_ECR_TOKEN}
      - file:${user.home}/.aws_ecr.token
  -
    # Azure CR
    # The hostname for public Microsoft Container Registry.
    # For Azure CR, replace with <org-registry>.azurecr.io with your own, or use wildcard *.azurecr.io
    hostname: '${AZURE_CR_HOST:-mcr.microsoft.com}' # mcr.microsoft.com
    # public CR. Leave blank to reuse private hostname
    url: '${AZURE_CR_URL:-https://mcr.microsoft.com}'
    # Which projects use this registry? A hostname is often given in the image name.
    # Use a regex pattern, like 'project1|project2|project3' or 'prefix_.*'
    # Leave empty for matching by hostname.
    usedBy: ${AZURE_CR_USED_BY}
    # The username to connect to the registry api.
    user: ${AZURE_CR_USER}
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${AZURE_CR_TOKEN}
      - file:${user.home}/.azure_cr.token
  -
    # Google CR (GCR)
    # Transitioning to pkg.dev. You may need to change for the hostname of your private repository
    # google-containers and distroless are popular public repositories
    hostname: ${GCR_HOST:-gcr.io}' # gcr.io
    url: '${GCR_URL:-https://gcr.io}'
    usedBy: ${GCR_USED_BY}
    user: ${GCR_USER}
    tokenSources:
      - ${GCR_TOKEN}
      - file:${user.home}/.gcr.token
  -
    # GitHub CR
    # ghcr.io is the hostname for GitHub container registry
    hostname: '${GITHUB_CR:-ghcr.io}'
    url: '${GITHUB_CR_URL:-https://ghcr.io}'
    usedBy: ${GITHUB_CR_USED_BY}
    user: ${GITHUB_CR_USER}
    tokenSources:
      # Tokens specific to GitHub CR
      - ${GITHUB_CR_TOKEN}
      - file:${user.home}/.github_cr.pat
      # Generic GH token, it needs permissions for CR
      - ${GITHUB_TOKEN}
      - ${GITHUB_PAT}
      - file:${user.home}/.github.token
  -
    # GitLab CR
    # registry.gitlab.com is the hostname for GitLab CR
    hostname: '${GITLAB_CR:-registry.gitlab.com}'
    url: '${GITLAB_CR_URL:-https://registry.gitlab.com}'
    usedBy: ${GITLAB_CR_USED_BY}
    user: ${GITLAB_CR_USER}
    tokenSources:
      # Perhaps a restricted token with read_registry permissions could be used here
      - ${GITLAB_CR_TOKEN}
      - file:${user.home}/.gitlab_cr.token
      - ${GITLAB_TOKEN}
      - ${GITLAB_PAT}
      - file:${user.home}/.gitlab.token
  -
    # JFrog Artifactory. You may configure similarly Sonatype Nexus, etc.
    # The hostname for registries for on-cloud Artifactory, to match your own
    # You may write your own if needed, like docker.artifactory.your_domain, etc.
    hostname: '${JFROG_HOST:-*.jfrog.io}'
    url: '${JFROG_URL:-https://docker.jfrog.io}'
    usedBy: ${JFROG_USED_BY}
    user: ${JFROG_USER}
    tokenSources:
      # Perhaps a restricted token with read_registry permissions could be used here
      - ${JFROG_TOKEN}
      - file:${user.home}/.jfrog.token

tools:
#  name: # The name of the tool
#    hostname: '' # hostname (e.g. if the tool uses customer domain)
#    url: ''
#    usedBy: ''
#    user: null # optional username to use for connecting with the tool api
#    # How the access token should be fetched:
#    # From environment/system property (env:),
#    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
#    # or encode directly (use encryption to protect the token against casual readers)
#    tokenSources: #
#      - env:TOOL_TOKEN
#      - file:${user.home}/.tool.token
  cloudflare:
    hostname: ${CLOUDFLARE_HOST:-api.cloudflare.com}
    url: '${CLOUDFLARE_URL:-https://api.cloudflare.com/client/v4}'
    usedBy: ${CLOUDFLARE_USED_BY}
    #user: null
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    # or encode directly (use encryption to protect the token against casual readers)
    tokenSources:
      - ${CLOUDFLARE_TOKEN}
      - file:${user.home}/.cloudflare.token

  # DigitalOcean cloud provider
  digitalocean:
    hostname: ${DIGITALOCEAN_HOST:-api.digitalocean.com}
    url: '${DIGITALOCEAN_URL:-https://api.digitalocean.com}'
    usedBy: ${DIGITALOCEAN_USED_BY}
    #user: null
    # How the access token should be fetched:
    # From environment/system property (env:),
    # From file (use ${scanned.dir} for scanned directory, ${XYGENI_DIR} for scanner directory, ${user.home} for $HOME),
    tokenSources:
      - ${DIGITALOCEAN_TOKEN}
      - file:${user.home}/.digitalocean.token

applicativeCode:
  # List of patterns of filepaths that do not belong to the applicative code.
  # Applies to codetamper, iac, misconf, secrets. This also applies to third party uploaded reports.
  excludedPathPatterns:
    - '**/test*/**'
    - '**/Test*/**'
    - '**/*-test*/**'
    - '**/*-Test*/**'
    - '**/*.spec.ts'
    - '**/test.*'
    - '**/Test.*'
    - '**/*-test.*'
    - '**/*-Test.*'
    - '**/*-tests.*'
    - '**/*-Tests.*'
    - '**/*-TestCase.*'

  # List of component scopes that do not belong to the applicative code.
  # Applies to deps, suspectdeps.
  excludedScopes:
    generic:
      - 'dev'
      - 'devel'
      - 'development'
      - 'docs'
      - 'test'
      - 'testing'
    java: [ ]
    javascript: [ ]
    python: [ ]
    php: [ ]
    ruby: [ ]
    swift: ['*test*']
```
