{"id":22820776,"url":"https://github.com/github-community-projects/private-mirrors","last_synced_at":"2026-05-09T00:04:43.350Z","repository":{"id":306120268,"uuid":"728355005","full_name":"github-community-projects/private-mirrors","owner":"github-community-projects","description":"A GitHub App that allows you to contribute upstream using private mirrors of public projects","archived":false,"fork":false,"pushed_at":"2026-01-17T21:06:16.000Z","size":4923,"stargazers_count":176,"open_issues_count":34,"forks_count":35,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-18T07:13:29.562Z","etag":null,"topics":["contribution","fork","github-app","private-fork"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/github-community-projects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":"SUPPORT.md","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-12-06T19:04:34.000Z","updated_at":"2026-01-17T21:06:09.000Z","dependencies_parsed_at":"2025-07-29T11:15:24.325Z","dependency_job_id":"a627d0b9-14a0-41e2-bf07-eaeed0b876b7","html_url":"https://github.com/github-community-projects/private-mirrors","commit_stats":null,"previous_names":["github-community-projects/private-mirrors","github-community-projects/internal-contribution-forks"],"tags_count":45,"template":false,"template_full_name":null,"purl":"pkg:github/github-community-projects/private-mirrors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-community-projects%2Fprivate-mirrors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-community-projects%2Fprivate-mirrors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-community-projects%2Fprivate-mirrors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-community-projects%2Fprivate-mirrors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/github-community-projects","download_url":"https://codeload.github.com/github-community-projects/private-mirrors/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github-community-projects%2Fprivate-mirrors/sbom","scorecard":{"id":406100,"data":{"date":"2025-08-16T11:29:58Z","repo":{"name":"github.com/github-community-projects/private-mirrors","commit":"9250e0fbda8dc5b72f9b221690fcbb1f708f0762"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":7.4,"checks":[{"name":"Maintained","score":10,"reason":"12 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":6,"reason":"Found 4/6 approved changesets -- score normalized to 6","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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/auto-labeler.yml:15","Warn: jobLevel 'statuses' permission set to 'write': .github/workflows/pr-title.yml:21","Info: jobLevel 'contents' permission set to 'read': .github/workflows/pr-title.yml:19","Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/pr-title.yml:20","Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yml:29","Warn: jobLevel 'packages' permission set to 'write': .github/workflows/release.yml:30","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:18","Info: jobLevel 'pull-requests' permission set to 'read': .github/workflows/release.yml:19","Info: topLevel 'contents' permission set to 'read': .github/workflows/auto-labeler.yml:10","Info: topLevel 'contents' permission set to 'read': .github/workflows/build.yml:11","Info: topLevel 'contents' permission set to 'read': .github/workflows/docker-build.yml:11","Warn: topLevel 'packages' permission set to 'write': .github/workflows/docker-build.yml:12","Info: topLevel 'contents' permission set to 'read': .github/workflows/lint.yml:11","Info: topLevel 'contents' permission set to 'read': .github/workflows/pr-title.yml:14","Info: topLevel 'contents' permission set to 'read': .github/workflows/release.yml:13","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:16","Info: topLevel 'contents' permission set to 'read': .github/workflows/tests.yml:11"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":9,"reason":"dependency not pinned by hash detected -- score normalized to 9","details":["Warn: npmCommand not pinned by hash: Dockerfile:6","Info:  10 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   4 out of   4 third-party GitHubAction dependencies pinned","Info:   3 out of   3 containerImage dependencies pinned","Info:   3 out of   4 npmCommand 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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"SAST","score":9,"reason":"SAST tool is not run on all commits -- score normalized to 9","details":["Warn: 26 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/docker-build.yml:15"],"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"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/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/github-community-projects/.github/SECURITY.md:1","Info: Found linked content: github.com/github-community-projects/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/github-community-projects/.github/SECURITY.md:1","Info: Found text in security policy: github.com/github-community-projects/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Contributors","score":10,"reason":"project has 15 contributing companies or organizations","details":["Info: found contributions from: InnerSourceCommons, alamocoders, alltheavo, argoproj, capital one, capitalone, devsanantonio, figma, github, lostechies, meridth, onwardllc, ossf, privateerproj, super-linter"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}},{"name":"Branch-Protection","score":4,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Info: codeowner review is required on branch 'main'","Warn: 'last push approval' is disabled on branch 'main'","Warn: 'up-to-date branches' is disabled on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"CI-Tests","score":10,"reason":"15 out of 15 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-3h52-269p-cp9r"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T21:17:53.815Z","repository_id":306120268,"created_at":"2025-08-18T21:17:53.815Z","updated_at":"2025-08-18T21:17:53.815Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29181265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T23:15:33.022Z","status":"ssl_error","status_checked_at":"2026-02-06T23:15:09.128Z","response_time":59,"last_error":"SSL_read: 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":["contribution","fork","github-app","private-fork"],"created_at":"2024-12-12T15:27:10.523Z","updated_at":"2026-05-09T00:04:43.345Z","avatar_url":"https://github.com/github-community-projects.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"[![CodeQL](https://github.com/github-community-projects/private-mirrors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github-community-projects/private-mirrors/actions/workflows/github-code-scanning/codeql)\n[![Docker Build](https://github.com/github-community-projects/private-mirrors/actions/workflows/docker-build.yml/badge.svg)](https://github.com/github-community-projects/private-mirrors/actions/workflows/docker-build.yml)\n[![Lint](https://github.com/github-community-projects/private-mirrors/actions/workflows/lint.yml/badge.svg)](https://github.com/github-community-projects/private-mirrors/actions/workflows/lint.yml)\n[![Tests](https://github.com/github-community-projects/private-mirrors/actions/workflows/tests.yml/badge.svg)](https://github.com/github-community-projects/private-mirrors/actions/workflows/tests.yml)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github-community-projects/private-mirrors/badge)](https://scorecard.dev/viewer/?uri=github.com/github-community-projects/private-mirrors)\n\n\u003ch1 align=\"center\"\u003e\n  GitHub Private Mirrors App\n\u003c/h1\u003e\n\n\u003ch4 align=\"center\"\u003eA GitHub App that allows you to contribute upstream using private mirrors of public repositories\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#key-features\"\u003eKey Features\u003c/a\u003e •\n  \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e •\n  \u003ca href=\"#developing\"\u003eDeveloping\u003c/a\u003e •\n  \u003ca href=\"#background\"\u003eBackground\u003c/a\u003e •\n  \u003ca href=\"#license\"\u003eMIT License\u003c/a\u003e\n\u003c/p\u003e\n\nThe Private Mirrors App (PMA) is GitHub App that allows you to work on contributions to an upstream open source project using a private repository in your own organization. This is useful for developing and checking contributions internally before making any commits publicly visible.\n\nFor a video overview, check out [this short presentation and demo video](https://www.youtube.com/watch?v=pVhB0epW5ro?si=__QxE2aIS_OkQiDc).\n\n[![PMA YouTube Video Thumbnail](https://github.com/user-attachments/assets/183344dd-f04e-4dd0-bf1d-fcb6a8dc1fd5)](https://www.youtube.com/watch?v=pVhB0epW5ro?si=__QxE2aIS_OkQiDc)\n\n\u003e [!IMPORTANT]\n\u003e 📣 EMU support is now available! Check out the [hosting - GHEC](#integrating-the-app-into-ghec) section for more information.\n\u003e\n\u003e This app is still a work in progress and is pre-1.0 _public beta_. We are actively working on improving it with beta testers, and if you're interested in using it for your organization, [we'd love to hear from you](https://github.com/github-community-projects/private-mirrors/issues/new)!\n\n## Problem Statement\n\nEnterprises struggle with how to let their developers contribute to open source projects. Most are not opposed, in principle, to contributing back to the projects they rely upon. Many are enthusiastic about becoming better open source citizens, and understand the reputational and technical benefits that working in open source can accrue to the business. However, real and perceived security concerns make this process difficult at best and impossible at worst for companies.\n\nTo succeed, open source advocates and OSPOs need to address their stakeholders' concerns about:\n\n- Credential leaks\n- Intellectual property leaks\n- PII / PHI disclosure\n- Liability and/or reputational damage resulting from bad code\n\nAddressing these concerns creates opportunities for enterprise development teams to participate more deeply in open source and foster a collaborative relationship with the open source community.\n\n\u003e The Private Mirrors App (PMA) is a GitHub App paired with a UI that manages the lifecycle of private mirrors, as well as the synchronization of code between the public fork of an upstream project and the private mirrors where the enterprise teams are working.\n\n## Key Features\n\n- Piggybacks off native GitHub fork network functionality to allow you to contribute to an upstream project using a private repository in your own organization\n- No commit rewriting — keep commit history, author attributions, commit signing and other metadata intact\n- No datastore — no need to worry about storing your code on a third-party server\n- Reduces risk of making open source contributions to upstream projects because your work stays private until it passes approval\n- Adapt the app to your workflow to ensure approvals, checks, and other requirements are met before code is merged upstream\n- Works with GitHub Enterprise Managed Users (EMUs) and GitHub Enterprise Cloud (GHEC)\n\nHigh Level Flow:\n\n![Time-series diagram showing work starting upstream, moving into a public fork, and through PMA into a private mirror](https://github.com/user-attachments/assets/3bb12563-dd32-46cc-b5cb-e983e9edd089)\n\nThe app uses an intermediary public fork to merge the private mirror into, and then enables the normal OSS contributor workflow into the upstream repository. This allows users to keep the private repo private while still allowing us to contribute to the upstream repository. Check out this [application flow diagram](./docs/architecture.md) for a more detailed look at how the app works.\n\n## Hosting\n\nYou'll need to self-host the app. See the section on [Developing](docs/developing.md) for more information.\n\nThis app was created with the idea of self-hosting in mind and can be deployed to any hosting provider that supports Next.js/Docker.\n\nConfiguration is contained in a `.env` file which you'll need to customize for your environment. Use the `.env.example` in the root of this repository as a starting point. In particular, you'll need to set the following:\n\n- `PUBLIC_ORG` and `PRIVATE_ORG` environment variables if you want to keep your private mirrors in a different GitHub organization from the public forks\n- `ALLOWED_HANDLES` variable to a comma-separated list of GitHub user handles which ought to be allowed to access the app to create mirrors. If unset, all users who are members of the organization will be allowed to use the app.\n\n```sh\ndocker build -t private-mirrors .\ndocker run --env-file=.env -p 3000:3000 private-mirrors\n\n# alternatively, you can use docker compose\ndocker compose up\n```\n\nThis project supports Node.js LTS releases; the latest LTS version is preferred. See the `engines` field in [package.json](./package.json) for the exact supported range.\n\nOnce it's running, you'll need to create a GitHub App and configure it to point to your deployment. See the [Developing — GitHub App](docs/developing.md#github-app) section for more information.\n\n## Integrating the App into GHEC\n\nThe app can be integrated into GitHub Enterprise Cloud (GHEC) by following the same steps as GitHub.com. The app is designed to work with GHEC and GitHub Enterprise Managed Users (EMUs).\n\nThe only tradeoff is that a single app instance will only work between a single GitHub instance and a single GHEC instance. If you have multiple GitHub instances and GHEC instances, you will need to deploy multiple instances of the app.\n\nTo enable the app to work with GHEC, you will need to set the following environment variables in addition to installing the App on your GHEC organization instance.\n\n```sh\nPUBLIC_ORG=name-of-your-public-org    # Where your public forks will be created\nPRIVATE_ORG=name-of-your-ghec-org     # Where your private mirrors will be created\n```\n\nThe authentication of the UI will still need to be a user's github.com user, but the app will be able to create forks and mirrors in the GHEC instance.\n\n## Usage\n\nOnce the app is installed, follow this document on [Using the Private Mirrors App](docs/using-the-app.md) to get the repository fork and mirrors set up for work.\n\n## Further Reading\n\n- [Contributing with Confidence: Capital One's open source contribution workflows](https://www.youtube.com/watch?v=boWJs4lASfY) - Talk about PMA by @ahpook and @riley-kohler at GitHub Universe 2024\n- [Developing](docs/developing.md)\n- [Using the App](docs/using-the-app.md)\n- [Architecture](docs/architecture.md)\n- [Attribution Flow](docs/attribution-flow.md)\n\n## License\n\nThis project is licensed under the terms of the MIT open source license. Please refer to [MIT](./LICENSE.md) for the full terms.\n\n## Maintainers\n\nCheck out the [CODEOWNERS](./CODEOWNERS) file to see who to contact for code changes.\n\n## Support\n\nIf you need support using this project or have questions about it, please [open an issue in this repository](https://github.com/github-community-projects/private-mirrors/issues/new) and we'd be happy to help. Requests made directly to GitHub staff or the support team will be redirected here to open an issue. GitHub SLA's and support/services contracts do not apply to this repository.\n\n## More OSPO Tools\n\nLooking for more resources for your open source program office (OSPO)? Check out the [`github-ospo`](https://github.com/github/github-ospo) repo for a variety of tools designed to support your needs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub-community-projects%2Fprivate-mirrors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgithub-community-projects%2Fprivate-mirrors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub-community-projects%2Fprivate-mirrors/lists"}