{"id":13542553,"url":"https://github.com/openpubkey/openpubkey","last_synced_at":"2026-03-05T21:32:56.656Z","repository":{"id":195648908,"uuid":"691805350","full_name":"openpubkey/openpubkey","owner":"openpubkey","description":"Reference implementation of OpenPubkey","archived":false,"fork":false,"pushed_at":"2026-02-06T21:31:04.000Z","size":18782,"stargazers_count":881,"open_issues_count":41,"forks_count":68,"subscribers_count":10,"default_branch":"main","last_synced_at":"2026-02-07T08:36:50.399Z","etag":null,"topics":["cryptography","identity","oauth2","openid-connect","software-supply-chain-security"],"latest_commit_sha":null,"homepage":"https://eprint.iacr.org/2023/296","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openpubkey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE-OF-CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-09-14T23:47:53.000Z","updated_at":"2026-02-06T21:31:09.000Z","dependencies_parsed_at":"2024-01-10T18:45:34.621Z","dependency_job_id":"fc928613-3f52-4c46-840d-a036bb309153","html_url":"https://github.com/openpubkey/openpubkey","commit_stats":null,"previous_names":["bastionzero/openpubkey","openpubkey/openpubkey"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/openpubkey/openpubkey","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openpubkey%2Fopenpubkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openpubkey%2Fopenpubkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openpubkey%2Fopenpubkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openpubkey%2Fopenpubkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openpubkey","download_url":"https://codeload.github.com/openpubkey/openpubkey/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openpubkey%2Fopenpubkey/sbom","scorecard":{"id":709949,"data":{"date":"2025-08-11","repo":{"name":"github.com/openpubkey/openpubkey","commit":"04ddde1d35a74f4068bca20cde61be3941bf7df5"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.4,"checks":[{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Code-Review","score":2,"reason":"Found 7/27 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":6,"reason":"7 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/go.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/go.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-drafter.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/release-drafter.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/staging.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/staging.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/staging.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/staging.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/staging.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/openpubkey/openpubkey/staging.yml/main?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-drafter.yml:15","Warn: no topLevel permission defined: .github/workflows/go.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/release-drafter.yml:10","Warn: topLevel 'contents' permission set to 'write': .github/workflows/staging.yml:8"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":2,"reason":"SAST tool is not run on all commits -- score normalized to 2","details":["Warn: 6 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T07:50:08.575Z","repository_id":195648908,"created_at":"2025-08-22T07:50:08.575Z","updated_at":"2025-08-22T07:50:08.575Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30150457,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T21:15:50.531Z","status":"ssl_error","status_checked_at":"2026-03-05T21:15:11.173Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","identity","oauth2","openid-connect","software-supply-chain-security"],"created_at":"2024-08-01T10:01:10.531Z","updated_at":"2026-03-05T21:32:56.620Z","avatar_url":"https://github.com/openpubkey.png","language":"Go","funding_links":[],"categories":["Go","others","cryptography","🛠️ 开发与脚手架"],"sub_categories":[],"readme":"# OpenPubkey\n\n[![Go Coverage](https://github.com/openpubkey/openpubkey/wiki/coverage.svg)](https://raw.githack.com/wiki/openpubkey/openpubkey/coverage.html)\n\n### OpenPubkey Mailing List\nFor updates and announcements join the [OpenPubkey mailing list](https://groups.google.com/g/openpubkey).\n\n## Overview\n\nOpenPubkey is a protocol for leveraging OpenID Providers (OPs) to bind identities to public keys. It adds user- or workload-generated public keys to [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/), enabling identities to sign messages or artifacts under their OIDC identity.\n\nWe represent this binding as a PK Token. This token proves control of the OIDC identity and the associated private key at a specific time, as long as a verifier trusts the OP. Put another way, the PK Token provides the same assurances as a certificate issued by a Certificate Authority (CA) but critically, does not require adding a CA. Instead, the OP fulfills the role of the CA. This token can be distributed alongside signatures in the same way as a certificate.\n\nOpenPubkey does not add any new trusted parties beyond what is required for OpenID Connect. It is fully compatible with existing OpenID Providers (Google, Azure/Microsoft, Okta, OneLogin, Keycloak) without any changes to the OpenID Provider.\n\nCompanies building on OpenPubkey include:\n\n* [Docker, Inc](https://www.docker.com/) is building a public container registry where [OpenPubkey is used to sign Docker Official Images](https://www.docker.com/blog/signing-docker-official-images-using-openpubkey/).\n\n* [BastionZero](https://www.bastionzero.com/) uses OpenPubkey to provide secure remote access to infrastructure.\n\nOpenPubkey is a Linux Foundation project. It is open source and licensed under the Apache 2.0 license. This project presently provides an OpenPubkey client and verifier for creating and verifying PK Tokens from Google’s OP (for users) and GitHub’s OP (for workloads).\n\n## Getting Started\n\nLet's walk through a simple message signing example. For conciseness we omit the error handling code. The full code for this example can be found in [./examples/simple/example.go](./examples/simple/example.go).\n\nWe start by configuring the OP (OpenID Provider) our client and verifier will use. In this example we use Google as our OP.\n\n```golang\nopOptions := providers.GetDefaultGoogleOpOptions()\nopOptions.GQSign = signGQ\nop := providers.NewGoogleOpWithOptions(opOptions)\n```\n\nNext we create the OpenPubkey client and call `opkClient.Auth`:\n\n```golang\nopkClient, err := client.New(op)\npkt, err := opkClient.Auth(context.Background())\n```\n\nThe function `opkClient.Auth` opens a browser window to the OP, Google in this case, which then prompts the user to authenticate their identity. If the user authenticates successfully the client will generate and return a PK Token, `pkt`.\n\nThe PK Token, `pkt`, along with the client's signing key can then be used to sign messages:\n\n```golang\nmsg := []byte(\"All is discovered - flee at once\")\nsignedMsg, err := pkt.NewSignedMessage(msg, opkClient.GetSigner())\n```\n\nTo verify a signed message, we first verify that the PK Token `pkt` is issued by the OP (Google). Then we use the PK Token to verify the signed message.\n\n```golang\npktVerifier, err := verifier.New(provider)\nerr = pktVerifier.VerifyPKToken(context.Background(), pkt)\nmsg, err := pkt.VerifySignedMessage(signedMsg)\n```\n\nTo run this example type: `go run .\\examples\\simple\\example.go`.\n\nThis will open a browser window to Google. If you authenticate to Google successfully, you should see: `Verification successful: anon.author.aardvark@gmail.com (https://accounts.google.com) signed the message 'All is discovered - flee at once'` where `anon.author.aardvark@gmail.com` is your gmail address.\n\n## How Does OpenPubkey Work?\n\nOpenPubkey supports both workload identities and user identities. Let's look at how this works for users and then show how to extend OpenPubkey to workloads.\n\n### OpenPubkey and User Identities\n\nIn OpenID Connect (OIDC) users authenticate to an OP (OpenID Provider), and the OP grants the user an ID Token. These ID Tokens are signed by the OP and contain claims made by the OP about the user such as the user's email address. Important to OpenPubkey is the `nonce` claim in the ID Token.\n\nThe `nonce` claim in the ID Token is a random value sent to the OP by the user's client during authentication with the OP. OpenPubkey follows the OpenID Connect authentication protocol with the OP, but it transmits a `nonce` value set to the cryptographic hash of both the user's public key and a random value so that the `nonce` is still cryptographically random, but any party that speaks OpenPubkey can check that ID Token contains the user's public key. From the perspective of the OP, the `nonce` looks just like a random value.\n\nLet's look at an example where a user, Alice, leverages OpenPubkey to get her OpenID Provider, `google.com`, to bind her OIDC identity, `alice@acme.co`, to her public key `alice-pubkey`. To do this, Alice invokes her OpenPubkey client.\n\n1. Alice's OpenPubkey client generates a fresh key pair for Alice, (`alice-pubkey`, `alice-signkey`), and a random value `rz`. The client then computes the `nonce=crypto.SHA3_256(upk=alice-pubkey, alg=ES256, rz=crypto.Rand())`. The value `alg` is set to the algorithm of Alice's key pair.\n2. Alice's OpenPubkey client then initiates OIDC authentication flow with the OP, `google.com`, and sends the `nonce` to the OP.\n3. The OP requests that Alice consents to issuing an ID Token and provides credentials (i.e., username and password) to authenticate to her OP (`Google`).\n4. If Alice successfully authenticates, the OP builds an ID Token containing claims about Alice. Critically, this ID Token contains the `nonce` claim generated by Alice's client to commit to Alice's public key. The OP then signs this ID Token under its signing key and sends the ID Token to Alice.\n\nThe ID Token is a JSON Web Signature (JWS) and follows the structure shown below:\n\n```\npayload: {\n  \"iss\": \"https://accounts.google.com\",\n  \"aud\": \"878305696756-6maur39hl2psmk23imilg8af815ih9oi.apps.googleusercontent.com\",\n  \"sub\": \"123456789010\",\n  \"email\": \"alice@acme.co\",\n  \"nonce\": 'crypto.SHA3_256(upk=alice-pubkey, alg=ES256, rz=crypto.Rand(), typ=\"CIC\")',\n  \"name\": \"Alice Example\",\n  ...\n} \nsignatures: [\n  {\"protected\": {\"alg\": \"RS256\", \"kid\": \"1234...\", \"typ\": \"JWT\"},\n  \"signature\": SIGN(google-signkey, (payload, signatures[0].protected))`\n  },\n]\n```\n\nAt this point, Alice has an ID Token, signed by `google.com` (the OP). Anyone can download the OP's (`google.com`) public keys from `google.com`'s well-known JSON Web Key Set (JWKS) URI )[www.googleapis.com/oauth2/v3/cert](https://www.googleapis.com/oauth2/v3/cert)) and verify that this ID Token committing to Alice's public key was actually signed by `google.com`. If Alice reveals the values of `alice-pubkey`, `alg`, and `rz`, anyone can verify that the `nonce` in the ID Token is the hash of  `upk=alice-pubkey, alg=ES256, rz=crypto.Rand()`. Thus, Alice now has a ID Token signed by Google that cryptography binding her identity, `alice@acme.co`, to her public key, `alice-pubkey`.\n\n### PK Tokens\n\nA PK Token is simply an extension of the ID Token that bundles together the ID Token with values committed to in the ID Token `nonce`. Because ID Tokens are JSON Web Signatures (JWS) and a JWS can have more than one signature, we extend the ID Token into a PK Token by appending a second signature/protected header.\n\nAlice simply sets the values she committed to in the `nonce` as a JWS protected header and signs the ID Token payload and this protected header under her signing key, `alice-signkey`. This signature acts as cryptographic proof that the user knows the secret signing key corresponding to the public key.\n\nNotice the additional signature entry in the PK Token example below (as compared to the ID Token example above):\n\n```\n\"payload\": {\n  \"iss\": \"https://accounts.google.com\",\n  \"aud\": \"878305696756-6maur39hl2psmk23imilg8af815ih9oi.apps.googleusercontent.com\",\n  \"sub\": \"123456789010\",\n  \"email\": \"alice@acme.co\",\n  \"nonce\": \u003ccrypto.SHA3_256(upk=alice-pubkey, alg=ES256, rz=crypto.Rand(), typ=\"CIC\")\u003e,\n  \"name\": \"Alice Example\",\n  ...\n}\n\"signatures\": [\n  {\"protected\": {\"alg\": \"RS256\", \"kid\": \"1234...\", \"typ\": \"JWT\"},\n  \"signature\": \u003cSIGN(google-signkey, (payload, signatures[0].protected))\u003e\n  },\n  {\"protected\": {\"upk\": alice-pubkey, \"alg\": \"EC256\", \"rz\": crypto.Rand(), \"typ\": \"CIC\"},\n  \"signature\": \u003cSIGN(alice-signkey, (payload, signatures[1].protected))\u003e\n  },\n]\n```\n\nThe PK Token can be presented to an OpenPubkey verifier, which uses OIDC to obtain the OP’s public key and verify the OP's signature in the ID Token. It then use the values in the protected header to extract the user's public key.\n\n### OpenPubkey and Workload Identities\n\nJust like OpenID Connect, OpenPubkey supports both user identities and workload identities.\n\nThe workload identity setting is very similar to the user identity setting with one major difference. Workload OpenID Providers, such as `github.com`, do not include a `nonce` claim in the ID Token. Unlike user identity providers, they allow the workload to specify an `aud`(audience) claim. Thus workload identity functions in a similar fashion as user identity but rather than commit to the public key in the `nonce`, we use the `aud` claim instead.\n\n### GQ Signatures To Prevent Replay Attacks\n\nAlthough not present in the original [OpenPubkey paper](https://eprint.iacr.org/2023/296), GQ signatures have now been integrated so that the OpenID Provider's (OP) signature can be stripped from the ID Token and a proof of the OP's signature published in its place. This prevents the ID Token within the PK Token from being used against any OIDC resource providers as the original signature has been removed without compromising any of the assurances that the original OP's signature provided.\n\nWe follow the approach specified in the following paper: [Reducing Trust in Automated Certificate Authorities via Proofs-of-Authentication](https://arxiv.org/abs/2307.08201).\n\nFor user-identity scenarios where the PK Token is not made public, GQ signatures are not required. GQ Signatures are required for all current workload-identity use cases.\n\n## How To Use OpenPubkey\n\nOpenPubkey is driven by its use cases. You can find all available use cases in the [examples folder](./examples/).\n\nWe expect this list to continue growing (and if you have an idea for an additional use case, please [file an issue](#file-an-issue), raise the idea in a [community meeting](#get-involved-with-our-community), or send a message in our [Slack channel](#join-our-slack)!\n\n## How To Develop With OpenPubkey\n\nAs we work to get this repository ready for `v 1.0`, you can check out the [examples folder](./examples/) for more information about OpenPubkey's different use cases. In the meantime, we would love for the community to contribute more use cases. See [below](#get-involved-with-our-community) for guidance on joining our community.\n\n## Governance and Contributing\n\n### File An Issue\n\nFor feature requests, bug reports, technical questions and requests, please open an issue. We ask that you review [existing issues](https://github.com/openpubkey/openpubkey/issues) before filing a new one to ensure your issue has not already been addressed.\n\nIf you have found what you believe to be a security vulnerability, *DO NOT file an issue*. Instead, please follow our [security disclosure policy](./SECURITY.md).\n\n### Code of Conduct\n\nBefore contributing to OpenPubkey, please review our [Code of Conduct](./CODE-OF-CONDUCT.md).\n\n### Contribute To OpenPubkey\n\nTo learn more about how to contribute, see [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n### Get Involved With Our Community\n\nTo get involved with our community, see our [community repo](https://github.com/openpubkey/community/). You’ll find details such as when the next community and technical steering committee meetings are.\n\n### Join Our Slack\n\nFind us over on the [OpenSSF Slack](https://openssf.org/getinvolved/) in the `#openpubkey` channel.\n\n### Report A Security Issue\n\nTo report a security issue, please follow our [security disclosure policy](./SECURITY.md).\n\n## FAQ\n\nSee the [FAQ](./docs/FAQ.md) for answers to Frequently Asked Questions about OpenPubkey.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenpubkey%2Fopenpubkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenpubkey%2Fopenpubkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenpubkey%2Fopenpubkey/lists"}