Repository: sigstore/fulcio
Pull request #1279 (2023-07-17 12:48:09)

Add "Source Repository Visibility At Signing" ext
#### Summary
<!--
 Explain the **motivation** for making this change. What existing problem does the pull request solve? How can reviewers test this PR?
-->

Adding a new Fulcio cert extension: "Source Repository Visibility At Signing"

Includes the source visibility at the time of signing/creating the certificate for GitHub Actions (backed by the `repository_visibility` clam in the GHA ID token) and GitLab (backed by the [upcoming `project_visibility` claim](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125787/diffs)).

TL'DR
- Attesting to source visibility in the certificate means we can verify wether a provenance attestation came from a public/private source repository without performing a network request to the source repository at the time of signing
- If you want to verify source visibility some time after signing you will need to make a unauthenticated network request to the source repository uri
- npm will verify this extension value (if it's set) at the time of publishing a package to the registry and rejecting any public packages with provenance that come from a private source repository
  - npm will also perform a just-in-time reachability checks to the source repository/commit when viewing a public package on npmjs.com
- "Source Repository Visibility At Signing" extension will be optional in Fulcio to allow CI systems to omit it if they don't have access to this info

See full discussion here / closes:
https://github.com/sigstore/fulcio/issues/1263

#### Release Note

Add certificate extension `1.3.6.1.4.1.57264.1.22` for "Source Repository Visibility At Signing"


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/sigstore/fulcio/pull/1279?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) Report
> Merging [#1279](https://app.codecov.io/gh/sigstore/fulcio/pull/1279?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) (6237781) into [main](https://app.codecov.io/gh/sigstore/fulcio/commit/cbe09108410c65ea0292835fc5997259b96653f3?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) (cbe0910) will **increase** coverage by `0.06%`.
> The diff coverage is `90.76%`.

```diff
@@            Coverage Diff             @@
##             main    #1279      +/-   ##
==========================================
+ Coverage   58.29%   58.36%   +0.06%     
==========================================
  Files          50       50              
  Lines        3031     3050      +19     
==========================================
+ Hits         1767     1780      +13     
- Misses       1108     1112       +4     
- Partials      156      158       +2     
```


| [Impacted Files](https://app.codecov.io/gh/sigstore/fulcio/pull/1279?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) | Coverage Δ | |
|---|---|---|
| [pkg/certificate/extensions.go](https://app.codecov.io/gh/sigstore/fulcio/pull/1279?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL2NlcnRpZmljYXRlL2V4dGVuc2lvbnMuZ28=) | `63.33% <53.84%> (-0.48%)` | :arrow_down: |
| [pkg/identity/github/principal.go](https://app.codecov.io/gh/sigstore/fulcio/pull/1279?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL2lkZW50aXR5L2dpdGh1Yi9wcmluY2lwYWwuZ28=) | `95.38% <100.00%> (+0.22%)` | :arrow_up: |



Patch:
diff --git a/docs/oid-info.md b/docs/oid-info.md
index 57bf58d..7d99545 100644
--- a/docs/oid-info.md
+++ b/docs/oid-info.md
@@ -37,6 +37,7 @@ Nice-to-haves:
 - MAY include claim to support: `Build Config Digest`
 - MAY include claim to support: `Build Trigger`
 - MAY include claim to support: `Run Invocation URI`
+- MAY include claim to support: `Source Repository Visibility At Signing`
 
 ## Terminology
 
@@ -177,6 +178,10 @@ Event or action that initiated the build. For example: `push`.
 
 Run Invocation URL to uniquely identify the build execution. SHOULD be fully qualified. For example: `https://github.com/example/repository/actions/runs/1536140711/attempts/1`.
 
+### 1.3.6.1.4.1.57264.1.22 | Source Repository Visibility At Signing
+
+Source repository visibility at the time of signing the certificate. MAY be empty if there is no Source Repository Visibility information available. For example: `private` or `public`.
+
 ## 1.3.6.1.4.1.57264.2 | Policy OID for Sigstore Timestamp Authority
 
 Not used by Fulcio. This specifies the policy OID for the [timestamp authority](https://github.com/sigstore/timestamp-authority)
@@ -204,6 +209,7 @@ that Sigstore operates.
 | workflow_sha       |  ci_config_sha ([WIP][gitlab-wip-cliams]) | ??       | ??        | Build Config Digest          | An immutable reference to the specific version of the top-level build instructions. Should include the digest type followed by the digest, e.g. `sha1:abc123`.                         |
 | event_name         | pipeline_source | ??       | ??        | Build Trigger                | The event or action that triggered the build.                                                                                                                                          |
 | server_url + repository + "/actions/runs/" + run_id + "/attempts/" + run_attempt | server_url + project_path + /-/jobs/ + job_id | ??       | ??        | Run Invocation URI           | An immutable identifier that can uniquely identify the build execution     |
+| repository_visibility | project_visibility | ??       | ??        | Source Repository Visibility At Signing | Source repository visibility at the time of signing the certificate |
 
 [github-oidc-doc]: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token
 [oid-link]: http://oid-info.com/get/1.3.6.1.4.1.57264
diff --git a/go.mod b/go.mod
index c773f30..caf8bab 100644
--- a/go.mod
+++ b/go.mod
@@ -35,8 +35,8 @@ require (
 	github.com/spiffe/go-spiffe/v2 v2.1.6
 	go.step.sm/crypto v0.32.4
 	go.uber.org/zap v1.24.0
-	google.golang.org/api v0.131.0
-	google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529
+	google.golang.org/api v0.132.0
+	google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130
 	google.golang.org/grpc v1.56.2
 	google.golang.org/protobuf v1.31.0
 	gopkg.in/square/go-jose.v2 v2.6.0
@@ -45,12 +45,12 @@ require (
 )
 
 require (
-	cloud.google.com/go v0.110.2 // indirect
+	cloud.google.com/go v0.110.4 // indirect
 	cloud.google.com/go/compute v1.20.1 // indirect
 	cloud.google.com/go/compute/metadata v0.2.3 // indirect
 	cloud.google.com/go/iam v1.1.0 // indirect
 	cloud.google.com/go/kms v1.13.0 // indirect
-	cloud.google.com/go/longrunning v0.5.0 // indirect
+	cloud.google.com/go/longrunning v0.5.1 // indirect
 	filippo.io/edwards25519 v1.0.0 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 // indirect
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
@@ -149,8 +149,8 @@ require (
 	golang.org/x/text v0.11.0 // indirect
 	golang.org/x/time v0.3.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230629202037-9506855d4529 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect
+	google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index b2a372d..03412b3 100644
--- a/go.sum
+++ b/go.sum
@@ -19,8 +19,8 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
 cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
 cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
 cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
-cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA=
-cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
+cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
+cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
 cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -37,8 +37,8 @@ cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
 cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
 cloud.google.com/go/kms v1.13.0 h1:s+sRhcowXwuLsa2Z8g3Tmh5l0HWNBf//HogCgiuDs/0=
 cloud.google.com/go/kms v1.13.0/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
-cloud.google.com/go/longrunning v0.5.0 h1:DK8BH0+hS+DIvc9a2TPnteUievsTCH4ORMAASSb7JcQ=
-cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc=
+cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI=
+cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
 cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
 cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -753,8 +753,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
 google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
 google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.131.0 h1:AcgWS2edQ4chVEt/SxgDKubVu/9/idCJy00tBGuGB4M=
-google.golang.org/api v0.131.0/go.mod h1:7vtkbKv2REjJbxmHSkBTBQ5LUGvPdAqjjvt84XAfhpA=
+google.golang.org/api v0.132.0 h1:8t2/+qZ26kAOGSmOiHwVycqVaDg7q3JDILrNi/Z6rvc=
+google.golang.org/api v0.132.0/go.mod h1:AeTBC6GpJnJSRJjktDcPX0QwtS8pGYZOV6MSuSCusw0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -801,12 +801,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20230629202037-9506855d4529 h1:9JucMWR7sPvCxUFd6UsOUNmA5kCcWOfORaT3tpAsKQs=
-google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
-google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 h1:s5YSX+ZH5b5vS9rnpGymvIyMpLRJizowqDlOuyjXnTk=
-google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 h1:2FZP5XuJY9zQyGM5N0rtovnoXjiMUEIUMvw0m9wlpLc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
 google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
diff --git a/pkg/certificate/extensions.go b/pkg/certificate/extensions.go
index 53d4d66..d38d707 100644
--- a/pkg/certificate/extensions.go
+++ b/pkg/certificate/extensions.go
@@ -39,19 +39,20 @@ var (
 	OIDIssuerV2  = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}
 
 	// CI extensions
-	OIDBuildSignerURI                  = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}
-	OIDBuildSignerDigest               = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}
-	OIDRunnerEnvironment               = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}
-	OIDSourceRepositoryURI             = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}
-	OIDSourceRepositoryDigest          = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}
-	OIDSourceRepositoryRef             = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}
-	OIDSourceRepositoryIdentifier      = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}
-	OIDSourceRepositoryOwnerURI        = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}
-	OIDSourceRepositoryOwnerIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}
-	OIDBuildConfigURI                  = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}
-	OIDBuildConfigDigest               = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}
-	OIDBuildTrigger                    = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}
-	OIDRunInvocationURI                = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}
+	OIDBuildSignerURI                      = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}
+	OIDBuildSignerDigest                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}
+	OIDRunnerEnvironment                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}
+	OIDSourceRepositoryURI                 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}
+	OIDSourceRepositoryDigest              = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}
+	OIDSourceRepositoryRef                 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}
+	OIDSourceRepositoryIdentifier          = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}
+	OIDSourceRepositoryOwnerURI            = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}
+	OIDSourceRepositoryOwnerIdentifier     = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}
+	OIDBuildConfigURI                      = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}
+	OIDBuildConfigDigest                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}
+	OIDBuildTrigger                        = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}
+	OIDRunInvocationURI                    = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}
+	OIDSourceRepositoryVisibilityAtSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}
 )
 
 // Extensions contains all custom x509 extensions defined by Fulcio
@@ -128,6 +129,9 @@ type Extensions struct {
 
 	// Run Invocation URL to uniquely identify the build execution.
 	RunInvocationURI string // 1.3.6.1.4.1.57264.1.21
+
+	// Source repository visibility at the time of signing the certificate.
+	SourceRepositoryVisibilityAtSigning string // 1.3.6.1.4.1.57264.1.22
 }
 
 func (e Extensions) Render() ([]pkix.Extension, error) {
@@ -320,6 +324,16 @@ func (e Extensions) Render() ([]pkix.Extension, error) {
 			Value: val,
 		})
 	}
+	if e.SourceRepositoryVisibilityAtSigning != "" {
+		val, err := asn1.MarshalWithParams(e.SourceRepositoryVisibilityAtSigning, "utf8")
+		if err != nil {
+			return nil, err
+		}
+		exts = append(exts, pkix.Extension{
+			Id:    OIDSourceRepositoryVisibilityAtSigning,
+			Value: val,
+		})
+	}
 
 	return exts, nil
 }
@@ -399,6 +413,10 @@ func parseExtensions(ext []pkix.Extension) (Extensions, error) {
 			if err := ParseDERString(e.Value, &out.RunInvocationURI); err != nil {
 				return Extensions{}, err
 			}
+		case e.Id.Equal(OIDSourceRepositoryVisibilityAtSigning):
+			if err := ParseDERString(e.Value, &out.SourceRepositoryVisibilityAtSigning); err != nil {
+				return Extensions{}, err
+			}
 		}
 	}
 
diff --git a/pkg/identity/github/principal.go b/pkg/identity/github/principal.go
index 5601d9f..5eaa74a 100644
--- a/pkg/identity/github/principal.go
+++ b/pkg/identity/github/principal.go
@@ -71,6 +71,9 @@ type workflowPrincipal struct {
 	// ID of the source repo
 	repositoryOwnerID string
 
+	// Visibility of the source repo
+	repositoryVisibility string
+
 	// Ref of top-level workflow that is running
 	workflowRef string
 
@@ -86,21 +89,22 @@ type workflowPrincipal struct {
 
 func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) {
 	var claims struct {
-		JobWorkflowRef    string `json:"job_workflow_ref"`
-		Sha               string `json:"sha"`
-		EventName         string `json:"event_name"`
-		Repository        string `json:"repository"`
-		Workflow          string `json:"workflow"`
-		Ref               string `json:"ref"`
-		JobWorkflowSha    string `json:"job_workflow_sha"`
-		RunnerEnvironment string `json:"runner_environment"`
-		RepositoryID      string `json:"repository_id"`
-		RepositoryOwner   string `json:"repository_owner"`
-		RepositoryOwnerID string `json:"repository_owner_id"`
-		WorkflowRef       string `json:"workflow_ref"`
-		WorkflowSha       string `json:"workflow_sha"`
-		RunID             string `json:"run_id"`
-		RunAttempt        string `json:"run_attempt"`
+		JobWorkflowRef       string `json:"job_workflow_ref"`
+		Sha                  string `json:"sha"`
+		EventName            string `json:"event_name"`
+		Repository           string `json:"repository"`
+		Workflow             string `json:"workflow"`
+		Ref                  string `json:"ref"`
+		JobWorkflowSha       string `json:"job_workflow_sha"`
+		RunnerEnvironment    string `json:"runner_environment"`
+		RepositoryID         string `json:"repository_id"`
+		RepositoryOwner      string `json:"repository_owner"`
+		RepositoryOwnerID    string `json:"repository_owner_id"`
+		RepositoryVisibility string `json:"repository_visibility"`
+		WorkflowRef          string `json:"workflow_ref"`
+		WorkflowSha          string `json:"workflow_sha"`
+		RunID                string `json:"run_id"`
+		RunAttempt           string `json:"run_attempt"`
 	}
 	if err := token.Claims(&claims); err != nil {
 		return nil, err
@@ -139,6 +143,9 @@ func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (ident
 	if claims.RepositoryOwnerID == "" {
 		return nil, errors.New("missing repository_owner_id claim in ID token")
 	}
+	if claims.RepositoryVisibility == "" {
+		return nil, errors.New("missing repository_visibility claim in ID token")
+	}
 	if claims.WorkflowRef == "" {
 		return nil, errors.New("missing workflow_ref claim in ID token")
 	}
@@ -153,24 +160,25 @@ func WorkflowPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (ident
 	}
 
 	return &workflowPrincipal{
-		subject:           token.Subject,
-		issuer:            token.Issuer,
-		url:               `https://github.com/`,
-		sha:               claims.Sha,
-		eventName:         claims.EventName,
-		repository:        claims.Repository,
-		workflow:          claims.Workflow,
-		ref:               claims.Ref,
-		jobWorkflowRef:    claims.JobWorkflowRef,
-		jobWorkflowSha:    claims.JobWorkflowSha,
-		runnerEnvironment: claims.RunnerEnvironment,
-		repositoryID:      claims.RepositoryID,
-		repositoryOwner:   claims.RepositoryOwner,
-		repositoryOwnerID: claims.RepositoryOwnerID,
-		workflowRef:       claims.WorkflowRef,
-		workflowSha:       claims.WorkflowSha,
-		runID:             claims.RunID,
-		runAttempt:        claims.RunAttempt,
+		subject:              token.Subject,
+		issuer:               token.Issuer,
+		url:                  `https://github.com/`,
+		sha:                  claims.Sha,
+		eventName:            claims.EventName,
+		repository:           claims.Repository,
+		workflow:             claims.Workflow,
+		ref:                  claims.Ref,
+		jobWorkflowRef:       claims.JobWorkflowRef,
+		jobWorkflowSha:       claims.JobWorkflowSha,
+		runnerEnvironment:    claims.RunnerEnvironment,
+		repositoryID:         claims.RepositoryID,
+		repositoryOwner:      claims.RepositoryOwner,
+		repositoryOwnerID:    claims.RepositoryOwnerID,
+		repositoryVisibility: claims.RepositoryVisibility,
+		workflowRef:          claims.WorkflowRef,
+		workflowSha:          claims.WorkflowSha,
+		runID:                claims.RunID,
+		runAttempt:           claims.RunAttempt,
 	}, nil
 }
 
@@ -198,19 +206,20 @@ func (w workflowPrincipal) Embed(_ context.Context, cert *x509.Certificate) erro
 		GithubWorkflowRef:        w.ref,
 		// END: Deprecated
 
-		BuildSignerURI:                  baseURL.JoinPath(w.jobWorkflowRef).String(),
-		BuildSignerDigest:               w.jobWorkflowSha,
-		RunnerEnvironment:               w.runnerEnvironment,
-		SourceRepositoryURI:             baseURL.JoinPath(w.repository).String(),
-		SourceRepositoryDigest:          w.sha,
-		SourceRepositoryRef:             w.ref,
-		SourceRepositoryIdentifier:      w.repositoryID,
-		SourceRepositoryOwnerURI:        baseURL.JoinPath(w.repositoryOwner).String(),
-		SourceRepositoryOwnerIdentifier: w.repositoryOwnerID,
-		BuildConfigURI:                  baseURL.JoinPath(w.workflowRef).String(),
-		BuildConfigDigest:               w.workflowSha,
-		BuildTrigger:                    w.eventName,
-		RunInvocationURI:                baseURL.JoinPath(w.repository, "actions/runs", w.runID, "attempts", w.runAttempt).String(),
+		BuildSignerURI:                      baseURL.JoinPath(w.jobWorkflowRef).String(),
+		BuildSignerDigest:                   w.jobWorkflowSha,
+		RunnerEnvironment:                   w.runnerEnvironment,
+		SourceRepositoryURI:                 baseURL.JoinPath(w.repository).String(),
+		SourceRepositoryDigest:              w.sha,
+		SourceRepositoryRef:                 w.ref,
+		SourceRepositoryIdentifier:          w.repositoryID,
+		SourceRepositoryOwnerURI:            baseURL.JoinPath(w.repositoryOwner).String(),
+		SourceRepositoryOwnerIdentifier:     w.repositoryOwnerID,
+		BuildConfigURI:                      baseURL.JoinPath(w.workflowRef).String(),
+		BuildConfigDigest:                   w.workflowSha,
+		BuildTrigger:                        w.eventName,
+		RunInvocationURI:                    baseURL.JoinPath(w.repository, "actions/runs", w.runID, "attempts", w.runAttempt).String(),
+		SourceRepositoryVisibilityAtSigning: w.repositoryVisibility,
 	}.Render()
 	if err != nil {
 		return err
diff --git a/pkg/identity/gitlabcom/principal.go b/pkg/identity/gitlabcom/principal.go
index f3debe4..1558f9d 100644
--- a/pkg/identity/gitlabcom/principal.go
+++ b/pkg/identity/gitlabcom/principal.go
@@ -77,6 +77,9 @@ type jobPrincipal struct {
 
 	// The type of runner used by the job. May be one of gitlab-hosted or self-hosted.
 	runnerEnvironment string
+
+	// Visibility of the source project
+	projectVisibility string
 }
 
 func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.Principal, error) {
@@ -95,6 +98,7 @@ func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.P
 		Sha               string `json:"sha"`
 		RunnerEnvironment string `json:"runner_environment"`
 		RunnerID          int64  `json:"runner_id"`
+		ProjectVisibility string `json:"project_visibility"`
 	}
 
 	if err := token.Claims(&claims); err != nil {
@@ -180,6 +184,7 @@ func JobPrincipalFromIDToken(_ context.Context, token *oidc.IDToken) (identity.P
 		sha:               claims.Sha,
 		runnerID:          claims.RunnerID,
 		runnerEnvironment: claims.RunnerEnvironment,
+		projectVisibility: claims.ProjectVisibility,
 	}, nil
 }
 
@@ -212,20 +217,21 @@ func (p jobPrincipal) Embed(_ context.Context, cert *x509.Certificate) error {
 
 	// Embed additional information into custom extensions
 	cert.ExtraExtensions, err = certificate.Extensions{
-		Issuer:                          p.issuer,
-		BuildConfigURI:                  ciConfigRefURL.String(),
-		BuildConfigDigest:               p.ciConfigSha,
-		BuildSignerURI:                  ciConfigRefURL.String(),
-		BuildSignerDigest:               p.ciConfigSha,
-		RunnerEnvironment:               p.runnerEnvironment,
-		SourceRepositoryURI:             baseURL.JoinPath(p.repository).String(),
-		SourceRepositoryDigest:          p.sha,
-		SourceRepositoryRef:             p.ref,
-		SourceRepositoryIdentifier:      p.repositoryID,
-		SourceRepositoryOwnerURI:        baseURL.JoinPath(p.repositoryOwner).String(),
-		SourceRepositoryOwnerIdentifier: p.repositoryOwnerID,
-		BuildTrigger:                    p.eventName,
-		RunInvocationURI:                baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID).String(),
+		Issuer:                              p.issuer,
+		BuildConfigURI:                      ciConfigRefURL.String(),
+		BuildConfigDigest:                   p.ciConfigSha,
+		BuildSignerURI:                      ciConfigRefURL.String(),
+		BuildSignerDigest:                   p.ciConfigSha,
+		RunnerEnvironment:                   p.runnerEnvironment,
+		SourceRepositoryURI:                 baseURL.JoinPath(p.repository).String(),
+		SourceRepositoryDigest:              p.sha,
+		SourceRepositoryRef:                 p.ref,
+		SourceRepositoryIdentifier:          p.repositoryID,
+		SourceRepositoryOwnerURI:            baseURL.JoinPath(p.repositoryOwner).String(),
+		SourceRepositoryOwnerIdentifier:     p.repositoryOwnerID,
+		BuildTrigger:                        p.eventName,
+		RunInvocationURI:                    baseURL.JoinPath(p.repository, "/-/jobs/", p.jobID).String(),
+		SourceRepositoryVisibilityAtSigning: p.projectVisibility,
 	}.Render()
 	if err != nil {
 		return err


Test patch:
diff --git a/pkg/certificate/extensions_test.go b/pkg/certificate/extensions_test.go
index 7700d81..7bf4ea6 100644
--- a/pkg/certificate/extensions_test.go
+++ b/pkg/certificate/extensions_test.go
@@ -37,25 +37,26 @@ func TestExtensions(t *testing.T) {
 		},
 		`complete extensions list should create all extensions with correct OIDs`: {
 			Extensions: Extensions{
-				Issuer:                          "issuer", // OID 1.3.6.1.4.1.57264.1.1 and 1.3.6.1.4.1.57264.1.8
-				GithubWorkflowTrigger:           "2",      // OID 1.3.6.1.4.1.57264.1.2
-				GithubWorkflowSHA:               "3",      // OID 1.3.6.1.4.1.57264.1.3
-				GithubWorkflowName:              "4",      // OID 1.3.6.1.4.1.57264.1.4
-				GithubWorkflowRepository:        "5",      // OID 1.3.6.1.4.1.57264.1.5
-				GithubWorkflowRef:               "6",      // 1.3.6.1.4.1.57264.1.6
-				BuildSignerURI:                  "9",      // 1.3.6.1.4.1.57264.1.9
-				BuildSignerDigest:               "10",     // 1.3.6.1.4.1.57264.1.10
-				RunnerEnvironment:               "11",     // 1.3.6.1.4.1.57264.1.11
-				SourceRepositoryURI:             "12",     // 1.3.6.1.4.1.57264.1.12
-				SourceRepositoryDigest:          "13",     // 1.3.6.1.4.1.57264.1.13
-				SourceRepositoryRef:             "14",     // 1.3.6.1.4.1.57264.1.14
-				SourceRepositoryIdentifier:      "15",     // 1.3.6.1.4.1.57264.1.15
-				SourceRepositoryOwnerURI:        "16",     // 1.3.6.1.4.1.57264.1.16
-				SourceRepositoryOwnerIdentifier: "17",     // 1.3.6.1.4.1.57264.1.17
-				BuildConfigURI:                  "18",     // 1.3.6.1.4.1.57264.1.18
-				BuildConfigDigest:               "19",     // 1.3.6.1.4.1.57264.1.19
-				BuildTrigger:                    "20",     // 1.3.6.1.4.1.57264.1.20
-				RunInvocationURI:                "21",     // 1.3.6.1.4.1.57264.1.21
+				Issuer:                              "issuer", // OID 1.3.6.1.4.1.57264.1.1 and 1.3.6.1.4.1.57264.1.8
+				GithubWorkflowTrigger:               "2",      // OID 1.3.6.1.4.1.57264.1.2
+				GithubWorkflowSHA:                   "3",      // OID 1.3.6.1.4.1.57264.1.3
+				GithubWorkflowName:                  "4",      // OID 1.3.6.1.4.1.57264.1.4
+				GithubWorkflowRepository:            "5",      // OID 1.3.6.1.4.1.57264.1.5
+				GithubWorkflowRef:                   "6",      // 1.3.6.1.4.1.57264.1.6
+				BuildSignerURI:                      "9",      // 1.3.6.1.4.1.57264.1.9
+				BuildSignerDigest:                   "10",     // 1.3.6.1.4.1.57264.1.10
+				RunnerEnvironment:                   "11",     // 1.3.6.1.4.1.57264.1.11
+				SourceRepositoryURI:                 "12",     // 1.3.6.1.4.1.57264.1.12
+				SourceRepositoryDigest:              "13",     // 1.3.6.1.4.1.57264.1.13
+				SourceRepositoryRef:                 "14",     // 1.3.6.1.4.1.57264.1.14
+				SourceRepositoryIdentifier:          "15",     // 1.3.6.1.4.1.57264.1.15
+				SourceRepositoryOwnerURI:            "16",     // 1.3.6.1.4.1.57264.1.16
+				SourceRepositoryOwnerIdentifier:     "17",     // 1.3.6.1.4.1.57264.1.17
+				BuildConfigURI:                      "18",     // 1.3.6.1.4.1.57264.1.18
+				BuildConfigDigest:                   "19",     // 1.3.6.1.4.1.57264.1.19
+				BuildTrigger:                        "20",     // 1.3.6.1.4.1.57264.1.20
+				RunInvocationURI:                    "21",     // 1.3.6.1.4.1.57264.1.21
+				SourceRepositoryVisibilityAtSigning: "22",     // 1.3.6.1.4.1.57264.1.22
 			},
 			Expect: []pkix.Extension{
 				{
@@ -138,6 +139,10 @@ func TestExtensions(t *testing.T) {
 					Id:    OIDRunInvocationURI,
 					Value: marshalDERString(t, "21"),
 				},
+				{
+					Id:    OIDSourceRepositoryVisibilityAtSigning,
+					Value: marshalDERString(t, "22"),
+				},
 			},
 			WantErr: false,
 		},
diff --git a/pkg/identity/github/issuer_test.go b/pkg/identity/github/issuer_test.go
index 6307313..8ba6ec3 100644
--- a/pkg/identity/github/issuer_test.go
+++ b/pkg/identity/github/issuer_test.go
@@ -45,25 +45,26 @@ func TestIssuer(t *testing.T) {
 			Subject: "repo:sigstore/fulcio:ref:refs/heads/main",
 		}
 		claims, err := json.Marshal(map[string]interface{}{
-			"aud":                 "sigstore",
-			"event_name":          "push",
-			"exp":                 0,
-			"iss":                 "https://token.actions.githubusercontent.com",
-			"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-			"job_workflow_sha":    "example-sha",
-			"ref":                 "refs/heads/main",
-			"repository":          "sigstore/fulcio",
-			"repository_id":       "12345",
-			"repository_owner":    "username",
-			"repository_owner_id": "345",
-			"run_attempt":         "1",
-			"run_id":              "42",
-			"runner_environment":  "cloud-hosted",
-			"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-			"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-			"workflow":            "foo",
-			"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-			"workflow_sha":        "example-sha-other",
+			"aud":                   "sigstore",
+			"event_name":            "push",
+			"exp":                   0,
+			"iss":                   "https://token.actions.githubusercontent.com",
+			"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+			"job_workflow_sha":      "example-sha",
+			"ref":                   "refs/heads/main",
+			"repository":            "sigstore/fulcio",
+			"repository_id":         "12345",
+			"repository_owner":      "username",
+			"repository_owner_id":   "345",
+			"repository_visibility": "public",
+			"run_attempt":           "1",
+			"run_id":                "42",
+			"runner_environment":    "cloud-hosted",
+			"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+			"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+			"workflow":              "foo",
+			"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+			"workflow_sha":          "example-sha-other",
 		})
 		if err != nil {
 			t.Fatal(err)
diff --git a/pkg/identity/github/principal_test.go b/pkg/identity/github/principal_test.go
index 6ec3d6f..3b1d01b 100644
--- a/pkg/identity/github/principal_test.go
+++ b/pkg/identity/github/principal_test.go
@@ -40,385 +40,426 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) {
 	}{
 		`Valid token authenticates with correct claims`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			ExpectPrincipal: workflowPrincipal{
-				issuer:            "https://token.actions.githubusercontent.com",
-				subject:           "repo:sigstore/fulcio:ref:refs/heads/main",
-				url:               "https://github.com/",
-				jobWorkflowRef:    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				sha:               "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				eventName:         "push",
-				repository:        "sigstore/fulcio",
-				workflow:          "foo",
-				ref:               "refs/heads/main",
-				jobWorkflowSha:    "example-sha",
-				runnerEnvironment: "cloud-hosted",
-				repositoryID:      "12345",
-				repositoryOwner:   "username",
-				repositoryOwnerID: "345",
-				workflowRef:       "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				workflowSha:       "example-sha-other",
-				runID:             "42",
-				runAttempt:        "1",
+				issuer:               "https://token.actions.githubusercontent.com",
+				subject:              "repo:sigstore/fulcio:ref:refs/heads/main",
+				url:                  "https://github.com/",
+				jobWorkflowRef:       "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				sha:                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				eventName:            "push",
+				repository:           "sigstore/fulcio",
+				workflow:             "foo",
+				ref:                  "refs/heads/main",
+				jobWorkflowSha:       "example-sha",
+				runnerEnvironment:    "cloud-hosted",
+				repositoryID:         "12345",
+				repositoryOwner:      "username",
+				repositoryOwnerID:    "345",
+				repositoryVisibility: "public",
+				workflowRef:          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				workflowSha:          "example-sha-other",
+				runID:                "42",
+				runAttempt:           "1",
 			},
 			WantErr: false,
 		},
 		`Token missing job_workflow_ref claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "job_workflow_ref",
 		},
 		`Token missing sha should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "sha",
 		},
 		`Token missing event_name claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "event_name",
 		},
 		`Token missing repository claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "repository",
 		},
 		`Token missing workflow claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "workflow",
 		},
 		`Token missing ref claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "ref",
 		},
 		`Token missing job_workflow_sha claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "job_workflow_sha",
 		},
 		`Token missing runner_environment claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "runner_environment",
 		},
 		`Token missing repository_id claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "repository_id",
 		},
 		`Token missing repository_owner claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "repository_owner",
 		},
 		`Token missing repository_owner_id claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                "sigstore",
-				"event_name":         "push",
-				"exp":                0,
-				"iss":                "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":   "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":   "example-sha",
-				"ref":                "refs/heads/main",
-				"repository":         "sigstore/fulcio",
-				"repository_id":      "12345",
-				"repository_owner":   "username",
-				"run_attempt":        "1",
-				"run_id":             "42",
-				"runner_environment": "cloud-hosted",
-				"sha":                "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":           "foo",
-				"workflow_ref":       "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":       "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "repository_owner_id",
 		},
 		`Token missing workflow_ref claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "workflow_ref",
 		},
 		`Token missing workflow_sha claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
 			},
 			WantErr:     true,
 			ErrContains: "workflow_sha",
 		},
 		`Token missing run_id claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			WantErr:     true,
 			ErrContains: "run_id",
 		},
 		`Token missing run_attempt claim should be rejected`: {
+			Claims: map[string]interface{}{
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
+			},
+			WantErr:     true,
+			ErrContains: "run_attempt",
+		},
+		`Token missing repository_visibility claim should be rejected`: {
 			Claims: map[string]interface{}{
 				"aud":                 "sigstore",
 				"event_name":          "push",
@@ -440,7 +481,7 @@ func TestWorkflowPrincipalFromIDToken(t *testing.T) {
 				"workflow_sha":        "example-sha-other",
 			},
 			WantErr:     true,
-			ErrContains: "run_attempt",
+			ErrContains: "repository_visibility",
 		},
 	}
 
@@ -498,25 +539,26 @@ func TestName(t *testing.T) {
 	}{
 		`Valid token authenticates with correct claims`: {
 			Claims: map[string]interface{}{
-				"aud":                 "sigstore",
-				"event_name":          "push",
-				"exp":                 0,
-				"iss":                 "https://token.actions.githubusercontent.com",
-				"job_workflow_ref":    "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
-				"job_workflow_sha":    "example-sha",
-				"ref":                 "refs/heads/main",
-				"repository":          "sigstore/fulcio",
-				"repository_id":       "12345",
-				"repository_owner":    "username",
-				"repository_owner_id": "345",
-				"run_attempt":         "1",
-				"run_id":              "42",
-				"runner_environment":  "cloud-hosted",
-				"sha":                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-				"sub":                 "repo:sigstore/fulcio:ref:refs/heads/main",
-				"workflow":            "foo",
-				"workflow_ref":        "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-				"workflow_sha":        "example-sha-other",
+				"aud":                   "sigstore",
+				"event_name":            "push",
+				"exp":                   0,
+				"iss":                   "https://token.actions.githubusercontent.com",
+				"job_workflow_ref":      "sigstore/fulcio/.github/workflows/foo.yaml@refs/heads/main",
+				"job_workflow_sha":      "example-sha",
+				"ref":                   "refs/heads/main",
+				"repository":            "sigstore/fulcio",
+				"repository_id":         "12345",
+				"repository_owner":      "username",
+				"repository_owner_id":   "345",
+				"repository_visibility": "public",
+				"run_attempt":           "1",
+				"run_id":                "42",
+				"runner_environment":    "cloud-hosted",
+				"sha":                   "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+				"sub":                   "repo:sigstore/fulcio:ref:refs/heads/main",
+				"workflow":              "foo",
+				"workflow_ref":          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+				"workflow_sha":          "example-sha-other",
 			},
 			ExpectName: "repo:sigstore/fulcio:ref:refs/heads/main",
 		},
@@ -556,47 +598,49 @@ func TestEmbed(t *testing.T) {
 	}{
 		`Github workflow challenge should have all Github workflow extensions and issuer set`: {
 			Principal: &workflowPrincipal{
-				issuer:            "https://token.actions.githubusercontent.com",
-				subject:           "doesntmatter",
-				url:               `https://github.com/`,
-				sha:               "sha",
-				eventName:         "trigger",
-				workflow:          "workflowname",
-				repository:        "repository",
-				ref:               "ref",
-				jobWorkflowRef:    "jobWorkflowRef",
-				jobWorkflowSha:    "jobWorkflowSha",
-				runnerEnvironment: "runnerEnv",
-				repositoryID:      "repoID",
-				repositoryOwner:   "repoOwner",
-				repositoryOwnerID: "repoOwnerID",
-				workflowRef:       "workflowRef",
-				workflowSha:       "workflowSHA",
-				runID:             "runID",
-				runAttempt:        "runAttempt",
+				issuer:               "https://token.actions.githubusercontent.com",
+				subject:              "doesntmatter",
+				url:                  `https://github.com/`,
+				sha:                  "sha",
+				eventName:            "trigger",
+				workflow:             "workflowname",
+				repository:           "repository",
+				ref:                  "ref",
+				jobWorkflowRef:       "jobWorkflowRef",
+				jobWorkflowSha:       "jobWorkflowSha",
+				runnerEnvironment:    "runnerEnv",
+				repositoryID:         "repoID",
+				repositoryOwner:      "repoOwner",
+				repositoryOwnerID:    "repoOwnerID",
+				repositoryVisibility: "public",
+				workflowRef:          "workflowRef",
+				workflowSha:          "workflowSHA",
+				runID:                "runID",
+				runAttempt:           "runAttempt",
 			},
 			WantErr: false,
 			WantFacts: map[string]func(x509.Certificate) error{
-				`Certifificate should have correct issuer`:                factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"),
-				`Certificate has correct trigger extension`:               factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"),
-				`Certificate has correct SHA extension`:                   factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, "sha"),
-				`Certificate has correct workflow extension`:              factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, "workflowname"),
-				`Certificate has correct repository extension`:            factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, "repository"),
-				`Certificate has correct ref extension`:                   factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, "ref"),
-				`Certificate has correct issuer (v2) extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://token.actions.githubusercontent.com"),
-				`Certificate has correct builder signer URI extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://github.com/jobWorkflowRef"),
-				`Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "jobWorkflowSha"),
-				`Certificate has correct runner environment extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "runnerEnv"),
-				`Certificate has correct source repo URI extension`:       factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://github.com/repository"),
-				`Certificate has correct source repo digest extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
-				`Certificate has correct source repo ref extension`:       factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
-				`Certificate has correct source repo ID extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "repoID"),
-				`Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://github.com/repoOwner"),
-				`Certificate has correct source repo owner ID extension`:  factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "repoOwnerID"),
-				`Certificate has correct build config URI extension`:      factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://github.com/workflowRef"),
-				`Certificate has correct build config digest extension`:   factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "workflowSHA"),
-				`Certificate has correct build trigger extension`:         factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "trigger"),
-				`Certificate has correct run invocation ID extension`:     factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"),
+				`Certifificate should have correct issuer`:                       factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}, "https://token.actions.githubusercontent.com"),
+				`Certificate has correct trigger extension`:                      factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, "trigger"),
+				`Certificate has correct SHA extension`:                          factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, "sha"),
+				`Certificate has correct workflow extension`:                     factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, "workflowname"),
+				`Certificate has correct repository extension`:                   factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, "repository"),
+				`Certificate has correct ref extension`:                          factDeprecatedExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, "ref"),
+				`Certificate has correct issuer (v2) extension`:                  factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://token.actions.githubusercontent.com"),
+				`Certificate has correct builder signer URI extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://github.com/jobWorkflowRef"),
+				`Certificate has correct builder signer digest extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "jobWorkflowSha"),
+				`Certificate has correct runner environment extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "runnerEnv"),
+				`Certificate has correct source repo URI extension`:              factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://github.com/repository"),
+				`Certificate has correct source repo digest extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
+				`Certificate has correct source repo ref extension`:              factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
+				`Certificate has correct source repo ID extension`:               factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "repoID"),
+				`Certificate has correct source repo owner URI extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://github.com/repoOwner"),
+				`Certificate has correct source repo owner ID extension`:         factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "repoOwnerID"),
+				`Certificate has correct build config URI extension`:             factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://github.com/workflowRef"),
+				`Certificate has correct build config digest extension`:          factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "workflowSHA"),
+				`Certificate has correct build trigger extension`:                factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "trigger"),
+				`Certificate has correct run invocation ID extension`:            factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://github.com/repository/actions/runs/runID/attempts/runAttempt"),
+				`Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"),
 			},
 		},
 		`Github workflow value with bad URL fails`: {
diff --git a/pkg/identity/gitlabcom/issuer_test.go b/pkg/identity/gitlabcom/issuer_test.go
index 43fea19..87caa62 100644
--- a/pkg/identity/gitlabcom/issuer_test.go
+++ b/pkg/identity/gitlabcom/issuer_test.go
@@ -62,6 +62,7 @@ func TestIssuer(t *testing.T) {
 			"ref":                "main",
 			"ref_type":           "branch",
 			"ref_protected":      "true",
+			"project_visibility": "public",
 			"jti":                "914910cc-09f6-4217-8091-a1d3231a37db",
 			"iss":                "https://gitlab.com",
 			"iat":                1674658264,
diff --git a/pkg/identity/gitlabcom/principal_test.go b/pkg/identity/gitlabcom/principal_test.go
index 93a7a44..0ad4fb0 100644
--- a/pkg/identity/gitlabcom/principal_test.go
+++ b/pkg/identity/gitlabcom/principal_test.go
@@ -57,6 +57,7 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
 				"sha":                "714a629c0b401fdce83e847fc9589983fc6f46bc",
 				"runner_id":          1,
 				"runner_environment": "gitlab-hosted",
+				"project_visibility": "public",
 			},
 			ExpectPrincipal: jobPrincipal{
 				issuer:            "https://gitlab.com",
@@ -75,64 +76,68 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
 				runnerID:          1,
 				runnerEnvironment: "gitlab-hosted",
 				sha:               "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				projectVisibility: "public",
 			},
 			WantErr: false,
 		},
 		`Token missing pipeline_source claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":               "sigstore",
-				"exp":               0,
-				"iss":               "https://gitlab.com",
-				"sub":               "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
-				"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
-				"ci_config_sha":     "714a629c0b401fdce83e847fc9589983fc6f46bc",
-				"project_id":        "42831435",
-				"project_path":      "cpanato/testing-cosign",
-				"namespace_path":    "cpanato",
-				"namespace_id":      "1730270",
-				"pipeline_id":       "757451528",
-				"job_id":            "3659681386",
-				"ref":               "main",
-				"ref_type":          "branch",
+				"aud":                "sigstore",
+				"exp":                0,
+				"iss":                "https://gitlab.com",
+				"sub":                "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
+				"ci_config_ref_uri":  "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
+				"ci_config_sha":      "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				"project_id":         "42831435",
+				"project_path":       "cpanato/testing-cosign",
+				"namespace_path":     "cpanato",
+				"namespace_id":       "1730270",
+				"pipeline_id":        "757451528",
+				"job_id":             "3659681386",
+				"ref":                "main",
+				"ref_type":           "branch",
+				"project_visibility": "public",
 			},
 			WantErr:     true,
 			ErrContains: "pipeline_source",
 		},
 		`Token missing project_path claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":               "sigstore",
-				"exp":               0,
-				"iss":               "https://gitlab.com",
-				"sub":               "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
-				"ci_config_ref_uri": "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
-				"ci_config_sha":     "714a629c0b401fdce83e847fc9589983fc6f46bc",
-				"project_id":        "42831435",
-				"pipeline_id":       "757451528",
-				"namespace_id":      "1730270",
-				"pipeline_source":   "push",
-				"namespace_path":    "cpanato",
-				"job_id":            "3659681386",
-				"ref":               "main",
-				"ref_type":          "branch",
+				"aud":                "sigstore",
+				"exp":                0,
+				"iss":                "https://gitlab.com",
+				"sub":                "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
+				"ci_config_ref_uri":  "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
+				"ci_config_sha":      "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				"project_id":         "42831435",
+				"pipeline_id":        "757451528",
+				"namespace_id":       "1730270",
+				"pipeline_source":    "push",
+				"namespace_path":     "cpanato",
+				"job_id":             "3659681386",
+				"ref":                "main",
+				"ref_type":           "branch",
+				"project_visibility": "public",
 			},
 			WantErr:     true,
 			ErrContains: "project_path",
 		},
 		`Token missing ci_config_ref_uri claim should be rejected`: {
 			Claims: map[string]interface{}{
-				"aud":             "sigstore",
-				"exp":             0,
-				"iss":             "https://gitlab.com",
-				"sub":             "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
-				"project_id":      "42831435",
-				"project_path":    "cpanato/testing-cosign",
-				"pipeline_id":     "757451528",
-				"namespace_id":    "1730270",
-				"pipeline_source": "push",
-				"namespace_path":  "cpanato",
-				"job_id":          "3659681386",
-				"ref":             "main",
-				"ref_type":        "branch",
+				"aud":                "sigstore",
+				"exp":                0,
+				"iss":                "https://gitlab.com",
+				"sub":                "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
+				"project_id":         "42831435",
+				"project_path":       "cpanato/testing-cosign",
+				"pipeline_id":        "757451528",
+				"namespace_id":       "1730270",
+				"pipeline_source":    "push",
+				"namespace_path":     "cpanato",
+				"job_id":             "3659681386",
+				"ref":                "main",
+				"ref_type":           "branch",
+				"project_visibility": "public",
 			},
 			WantErr:     true,
 			ErrContains: "ci_config_ref_uri",
@@ -156,6 +161,7 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
 				"sha":                "714a629c0b401fdce83e847fc9589983fc6f46bc",
 				"runner_id":          1,
 				"runner_environment": "gitlab-hosted",
+				"project_visibility": "public",
 			},
 			ExpectPrincipal: jobPrincipal{
 				issuer:            "https://gitlab.com",
@@ -173,6 +179,48 @@ func TestJobPrincipalFromIDToken(t *testing.T) {
 				runnerID:          1,
 				runnerEnvironment: "gitlab-hosted",
 				sha:               "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				projectVisibility: "public",
+			},
+			WantErr: false,
+		},
+		`Token missing project_visibility is ok`: {
+			Claims: map[string]interface{}{
+				"aud":                "sigstore",
+				"exp":                0,
+				"iss":                "https://gitlab.com",
+				"sub":                "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
+				"project_id":         "42831435",
+				"project_path":       "cpanato/testing-cosign",
+				"namespace_path":     "cpanato",
+				"namespace_id":       "1730270",
+				"pipeline_id":        "757451528",
+				"pipeline_source":    "push",
+				"ci_config_ref_uri":  "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
+				"ci_config_sha":      "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				"job_id":             "3659681386",
+				"ref":                "main",
+				"ref_type":           "branch",
+				"sha":                "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				"runner_id":          1,
+				"runner_environment": "gitlab-hosted",
+			},
+			ExpectPrincipal: jobPrincipal{
+				issuer:            "https://gitlab.com",
+				subject:           "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
+				url:               "https://gitlab.com/",
+				eventName:         "push",
+				pipelineID:        "757451528",
+				ciConfigRefURI:    "gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main",
+				ciConfigSha:       "714a629c0b401fdce83e847fc9589983fc6f46bc",
+				repository:        "cpanato/testing-cosign",
+				repositoryID:      "42831435",
+				repositoryOwner:   "cpanato",
+				repositoryOwnerID: "1730270",
+				jobID:             "3659681386",
+				ref:               "refs/heads/main",
+				runnerID:          1,
+				runnerEnvironment: "gitlab-hosted",
+				sha:               "714a629c0b401fdce83e847fc9589983fc6f46bc",
 			},
 			WantErr: false,
 		},
@@ -249,6 +297,7 @@ func TestName(t *testing.T) {
 				"sha":                "714a629c0b401fdce83e847fc9589983fc6f46bc",
 				"runner_id":          1,
 				"runner_environment": "gitlab-hosted",
+				"project_visibility": "public",
 			},
 			ExpectName: "project_path:cpanato/testing-cosign:ref_type:branch:ref:main",
 		},
@@ -304,23 +353,25 @@ func TestEmbed(t *testing.T) {
 				runnerID:          1,
 				runnerEnvironment: "gitlab-hosted",
 				sha:               "sha",
+				projectVisibility: "public",
 			},
 			WantErr: false,
 			WantFacts: map[string]func(x509.Certificate) error{
-				`Certificate has correct issuer (v2) extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://gitlab.com"),
-				`Certificate has correct builder signer URI extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
-				`Certificate has correct builder signer digest extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
-				`Certificate has correct runner environment extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "gitlab-hosted"),
-				`Certificate has correct source repo URI extension`:       factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://gitlab.com/cpanato/testing-cosign"),
-				`Certificate has correct source repo digest extension`:    factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
-				`Certificate has correct source repo ref extension`:       factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
-				`Certificate has correct source repo ID extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "42831435"),
-				`Certificate has correct source repo owner URI extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://gitlab.com/cpanato"),
-				`Certificate has correct source repo owner ID extension`:  factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "1730270"),
-				`Certificate has correct build config URI extension`:      factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
-				`Certificate has correct build config digest extension`:   factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
-				`Certificate has correct build trigger extension`:         factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "push"),
-				`Certificate has correct run invocation ID extension`:     factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://gitlab.com/cpanato/testing-cosign/-/jobs/3659681386"),
+				`Certificate has correct issuer (v2) extension`:                  factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}, "https://gitlab.com"),
+				`Certificate has correct builder signer URI extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
+				`Certificate has correct builder signer digest extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
+				`Certificate has correct runner environment extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}, "gitlab-hosted"),
+				`Certificate has correct source repo URI extension`:              factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}, "https://gitlab.com/cpanato/testing-cosign"),
+				`Certificate has correct source repo digest extension`:           factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}, "sha"),
+				`Certificate has correct source repo ref extension`:              factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}, "ref"),
+				`Certificate has correct source repo ID extension`:               factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}, "42831435"),
+				`Certificate has correct source repo owner URI extension`:        factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}, "https://gitlab.com/cpanato"),
+				`Certificate has correct source repo owner ID extension`:         factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}, "1730270"),
+				`Certificate has correct build config URI extension`:             factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}, "https://gitlab.com/cpanto/testing-cosign//.gitlab-ci.yml@refs/head/main"),
+				`Certificate has correct build config digest extension`:          factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}, "714a629c0b401fdce83e847fc9589983fc6f46bc"),
+				`Certificate has correct build trigger extension`:                factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}, "push"),
+				`Certificate has correct run invocation ID extension`:            factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}, "https://gitlab.com/cpanato/testing-cosign/-/jobs/3659681386"),
+				`Certificate has correct source repository visibility extension`: factExtensionIs(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}, "public"),
 			},
 		},
 		`GitLab job principal with bad URL fails`: {
diff --git a/pkg/server/grpc_server_test.go b/pkg/server/grpc_server_test.go
index c906e47..4558277 100644
--- a/pkg/server/grpc_server_test.go
+++ b/pkg/server/grpc_server_test.go
@@ -786,21 +786,22 @@ func TestAPIWithBuildkite(t *testing.T) {
 
 // githubClaims holds the additional JWT claims for GitHub OIDC tokens
 type githubClaims struct {
-	JobWorkflowRef    string `json:"job_workflow_ref"`
-	Sha               string `json:"sha"`
-	EventName         string `json:"event_name"`
-	Repository        string `json:"repository"`
-	Workflow          string `json:"workflow"`
-	Ref               string `json:"ref"`
-	JobWorkflowSha    string `json:"job_workflow_sha"`
-	RunnerEnvironment string `json:"runner_environment"`
-	RepositoryID      string `json:"repository_id"`
-	RepositoryOwner   string `json:"repository_owner"`
-	RepositoryOwnerID string `json:"repository_owner_id"`
-	WorkflowRef       string `json:"workflow_ref"`
-	WorkflowSha       string `json:"workflow_sha"`
-	RunID             string `json:"run_id"`
-	RunAttempt        string `json:"run_attempt"`
+	JobWorkflowRef       string `json:"job_workflow_ref"`
+	Sha                  string `json:"sha"`
+	EventName            string `json:"event_name"`
+	Repository           string `json:"repository"`
+	Workflow             string `json:"workflow"`
+	Ref                  string `json:"ref"`
+	JobWorkflowSha       string `json:"job_workflow_sha"`
+	RunnerEnvironment    string `json:"runner_environment"`
+	RepositoryID         string `json:"repository_id"`
+	RepositoryOwner      string `json:"repository_owner"`
+	RepositoryOwnerID    string `json:"repository_owner_id"`
+	RepositoryVisibility string `json:"repository_visibility"`
+	WorkflowRef          string `json:"workflow_ref"`
+	WorkflowSha          string `json:"workflow_sha"`
+	RunID                string `json:"run_id"`
+	RunAttempt           string `json:"run_attempt"`
 }
 
 // Tests API for GitHub subject types
@@ -822,21 +823,22 @@ func TestAPIWithGitHub(t *testing.T) {
 	}
 
 	claims := githubClaims{
-		JobWorkflowRef:    "job/workflow/ref",
-		Sha:               "sha",
-		EventName:         "trigger",
-		Repository:        "sigstore/fulcio",
-		Workflow:          "workflow",
-		Ref:               "refs/heads/main",
-		JobWorkflowSha:    "example-sha",
-		RunnerEnvironment: "cloud-hosted",
-		RepositoryID:      "12345",
-		RepositoryOwner:   "username",
-		RepositoryOwnerID: "345",
-		WorkflowRef:       "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
-		WorkflowSha:       "example-sha-other",
-		RunID:             "42",
-		RunAttempt:        "1",
+		JobWorkflowRef:       "job/workflow/ref",
+		Sha:                  "sha",
+		EventName:            "trigger",
+		Repository:           "sigstore/fulcio",
+		Workflow:             "workflow",
+		Ref:                  "refs/heads/main",
+		JobWorkflowSha:       "example-sha",
+		RunnerEnvironment:    "cloud-hosted",
+		RepositoryID:         "12345",
+		RepositoryOwner:      "username",
+		RepositoryOwnerID:    "345",
+		RepositoryVisibility: "public",
+		WorkflowRef:          "sigstore/other/.github/workflows/foo.yaml@refs/heads/main",
+		WorkflowSha:          "example-sha-other",
+		RunID:                "42",
+		RunAttempt:           "1",
 	}
 	githubSubject := fmt.Sprintf("repo:%s:ref:%s", claims.Repository, claims.Ref)
 
@@ -930,6 +932,7 @@ func TestAPIWithGitHub(t *testing.T) {
 		19: claims.WorkflowSha,
 		20: claims.EventName,
 		21: url + claims.Repository + "/actions/runs/" + claims.RunID + "/attempts/" + claims.RunAttempt,
+		22: claims.RepositoryVisibility,
 	}
 	for o, value := range expectedExts {
 		ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o})
@@ -966,6 +969,7 @@ type gitlabClaims struct {
 	Sha               string `json:"sha"`
 	RunnerEnvironment string `json:"runner_environment"`
 	RunnerID          int64  `json:"runner_id"`
+	ProjectVisibility string `json:"project_visibility"`
 }
 
 // Tests API for GitLab subject types
@@ -1001,6 +1005,7 @@ func TestAPIWithGitLab(t *testing.T) {
 		Sha:               "714a629c0b401fdce83e847fc9589983fc6f46bc",
 		RunnerID:          1,
 		RunnerEnvironment: "gitlab-hosted",
+		ProjectVisibility: "public",
 	}
 
 	gitLabSubject := fmt.Sprintf("project_path:%s:ref_type:%s:ref:%s", claims.ProjectPath, claims.RefType, claims.Ref)
@@ -1078,6 +1083,7 @@ func TestAPIWithGitLab(t *testing.T) {
 		19: claims.CiConfigSha,
 		20: claims.PipelineSource,
 		21: baseURL + claims.ProjectPath + "/-/jobs/" + claims.JobID,
+		22: claims.ProjectVisibility,
 	}
 	for o, value := range expectedExts {
 		ext, found := findCustomExtension(leafCert, asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, o})
diff --git a/tools/loadtest/README.md b/tools/loadtest/README.md
index 3702ebd..0e2af99 100644
--- a/tools/loadtest/README.md
+++ b/tools/loadtest/README.md
@@ -43,7 +43,7 @@ From within the directory with `locustfile.py`, run the command `locust`. Open `
 From the browser, set the following:
 * Number of users. Each will run at a maximum QPS based on maximum QPS set below.
 * Spawn rate, how often users are created per second
-* Host, either `localhost:port` if you're running a local instance of Fulcio or `https://v1.fulcio.sigstore.dev`
+* Host, e.g. `localhost:port`. Please do not run against production or staging.
 * Token - The identity token from `gcloud auth`
 * Max QPS per user
 
@@ -51,4 +51,4 @@ Click 'Start Swarming', and monitor for errors.
 
 ## Results (12/14/21)
 
-https://github.com/sigstore/fulcio/issues/193#issuecomment-994247492
\ No newline at end of file
+https://github.com/sigstore/fulcio/issues/193#issuecomment-994247492