docs(trust): add GitLab CI keyless signing integration#728
Conversation
Documents GitLab CI as a supported keyless signing provider alongside GitHub Actions. Adds the `build_signer_uri` publisher field (GitLab CI only), updates `issuer` and `repository` field descriptions to cover both providers, and includes verified branch/tag trust policy examples with a warning about over-broad wildcard allowlisting. Signed-off-by: Erran Carey <ecarey@gitlab.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| | `ref_pattern` | The git ref that triggered the workflow (e.g., `refs/heads/main`, `refs/tags/v1.0`). Use wildcards to trust a range of refs | Yes (`refs/tags/v*`) | | ||
| | `issuer` | The OIDC provider URL. GitHub Actions: `https://token.actions.githubusercontent.com`. GitLab: `https://gitlab.com` | No | | ||
| | `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the full project URL (e.g. `https://gitlab.com/org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`, `https://gitlab.com/org/*`) | | ||
| | `workflow` | Path to the CI config file that performed the signing, relative to the repo root (e.g. `.github/workflows/sign.yml`) | Yes (`*`) | |
There was a problem hiding this comment.
Supports CI_CONFIG_REF_URI after #706 which could be better than signer URL in some cases such as pipeline policies from security projects.
There was a problem hiding this comment.
Code Review
This pull request updates the documentation to include comprehensive instructions and examples for GitLab CI integration with keyless signing. It introduces the build_signer_uri field and provides example trust policies for both branch and tag references. The review feedback focuses on aligning the documentation with the underlying implementation: specifically, the repository field should use the project path (e.g., org/repo) rather than a full URL, and the build_signer_uri and workflow fields should not include the https:// scheme to ensure successful verification.
| | `workflow` | Path to the workflow file that performed the signing, relative to the repo root | Yes (`*`) | | ||
| | `ref_pattern` | The git ref that triggered the workflow (e.g., `refs/heads/main`, `refs/tags/v1.0`). Use wildcards to trust a range of refs | Yes (`refs/tags/v*`) | | ||
| | `issuer` | The OIDC provider URL. GitHub Actions: `https://token.actions.githubusercontent.com`. GitLab: `https://gitlab.com` | No | | ||
| | `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the full project URL (e.g. `https://gitlab.com/org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`, `https://gitlab.com/org/*`) | |
There was a problem hiding this comment.
The description for GitLab's repository field states it should be the "full project URL", but the implementation in gitlab_keyless_predicate (line 616 of trust_cmd.rs) uses CI_PROJECT_PATH, which is the namespace/project string. Using the full URL in the trust policy will cause verification to fail as it won't match the identity claim extracted from the OIDC token.
| `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the project path (e.g. `org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`) |
| | `ref_pattern` | The git ref that triggered the workflow (e.g., `refs/heads/main`, `refs/tags/v1.0`). Use wildcards to trust a range of refs | Yes (`refs/tags/v*`) | | ||
| | `issuer` | The OIDC provider URL. GitHub Actions: `https://token.actions.githubusercontent.com`. GitLab: `https://gitlab.com` | No | | ||
| | `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the full project URL (e.g. `https://gitlab.com/org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`, `https://gitlab.com/org/*`) | | ||
| | `workflow` | Path to the CI config file that performed the signing, relative to the repo root (e.g. `.github/workflows/sign.yml`) | Yes (`*`) | |
There was a problem hiding this comment.
For GitLab, the workflow field in the identity is set to the full URI (without scheme), not just the path relative to the repo root. The description should be updated to reflect this difference from GitHub's behavior.
| `workflow` | Path to the CI config file that performed the signing. GitHub: relative to repo root. GitLab: full URI (e.g. `gitlab.com/org/repo//.gitlab-ci.yml@refs/heads/main`) | Yes (`*`) |
| | `issuer` | The OIDC provider URL. GitHub Actions: `https://token.actions.githubusercontent.com`. GitLab: `https://gitlab.com` | No | | ||
| | `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the full project URL (e.g. `https://gitlab.com/org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`, `https://gitlab.com/org/*`) | | ||
| | `workflow` | Path to the CI config file that performed the signing, relative to the repo root (e.g. `.github/workflows/sign.yml`) | Yes (`*`) | | ||
| | `build_signer_uri` | GitLab CI only. Full URI of the CI configuration file and ref that performed the signing (e.g. `https://gitlab.com/org/repo//.gitlab-ci.yml@refs/heads/main`) | Yes (`*`) | |
There was a problem hiding this comment.
The example for build_signer_uri includes the https:// scheme, but the code in trust_cmd.rs (line 604) and GitLab's CI_CONFIG_REF_URI variable do not include it. Including the scheme in the policy will cause a mismatch during verification.
| `build_signer_uri` | GitLab CI only. Full URI of the CI configuration file and ref that performed the signing (e.g. `gitlab.com/org/repo//.gitlab-ci.yml@refs/heads/main`) | Yes (`*`) |
|
|
||
| ### Trust Policy for CI-Signed Files | ||
|
|
||
| GitLab uses `build_signer_uri` instead of `workflow` to identify the signing pipeline. The `repository` field takes the full project URL, and `issuer` is `https://gitlab.com`. |
There was a problem hiding this comment.
The repository field should be the project path (e.g., org/repo), not the full project URL, to match the CI_PROJECT_PATH used in the implementation.
GitLab uses `build_signer_uri` instead of `workflow` to identify the signing pipeline. The `repository` field takes the project path (e.g. `org/repo`), and `issuer` is `https://gitlab.com`.
| "build_signer_uri": "https://gitlab.com/erran/skills//.gitlab-ci.yml@refs/heads/main", | ||
| "repository": "https://gitlab.com/erran/skills", |
| "build_signer_uri": "https://gitlab.com/erran/skills//.gitlab-ci.yml@refs/tags/0.0.9", | ||
| "repository": "https://gitlab.com/erran/skills", |
| Note the double slash in the `build_signer_uri` path separator (`org/repo//.gitlab-ci.yml`). This is the format Fulcio embeds in the certificate — copy it exactly from `nono trust verify` output if you are unsure. | ||
|
|
||
| <Warning> | ||
| Wildcards in `build_signer_uri` and `repository` make it easy to over-trust. An entry with `issuer: https://gitlab.com` and `repository: https://gitlab.com/*` trusts any project on GitLab.com — including forks and unrelated projects. Scope `repository` to the specific project URL, and use `ref_pattern` to restrict to protected branches or release tags. |
There was a problem hiding this comment.
The warning example should use the project path format for consistency with the implementation.
Wildcards in `build_signer_uri` and `repository` make it easy to over-trust. An entry with `issuer: https://gitlab.com` and `repository: *` trusts any project on GitLab.com — including forks and unrelated projects. Scope `repository` to the specific project path, and use `ref_pattern` to restrict to protected branches or release tags.
| ```yaml | ||
| nono-cli-sign: | ||
| image: | ||
| name: ghcr.io/always-further/nono:0.36.0 |
There was a problem hiding this comment.
Outdated already 😬 In the GitLab docs we could refer to CI/CD component equivalent of the GitHub action for attestation.
We can point this entire GitLab signing section to GitLab docs if that makes sense. 👍🏽
There was a problem hiding this comment.
Additionally I’m playing around with having a Flow which can be enabled in GitLab.com projects which has nono and glab installed to download bundle from the latest pipeline from a default branch or tag.
|
Just let me know with a tag when you want eyes on this @erran |



Documents GitLab CI as a supported keyless signing provider alongside GitHub Actions. Adds the
build_signer_uripublisher field (GitLab CI only), updatesissuerandrepositoryfield descriptions to cover both providers, and includes verified branch/tag trust policy examples with a warning about over-broad wildcard allowlisting.