{"id":27137756,"url":"https://github.com/skagget77/recover-gh-secrets","last_synced_at":"2025-04-08T04:07:19.556Z","repository":{"id":64304077,"uuid":"400995447","full_name":"skagget77/recover-gh-secrets","owner":"skagget77","description":"Simple tool for recovering GitHub Actions Secrets from a GitHub repository","archived":false,"fork":false,"pushed_at":"2021-09-25T16:40:59.000Z","size":44,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-20T15:55:47.850Z","etag":null,"topics":["github","recover","secret","secrets"],"latest_commit_sha":null,"homepage":"","language":"Go","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/skagget77.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-29T08:58:49.000Z","updated_at":"2024-06-20T15:55:47.851Z","dependencies_parsed_at":"2023-01-15T10:15:24.907Z","dependency_job_id":null,"html_url":"https://github.com/skagget77/recover-gh-secrets","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skagget77%2Frecover-gh-secrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skagget77%2Frecover-gh-secrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skagget77%2Frecover-gh-secrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skagget77%2Frecover-gh-secrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skagget77","download_url":"https://codeload.github.com/skagget77/recover-gh-secrets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247773721,"owners_count":20993634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["github","recover","secret","secrets"],"created_at":"2025-04-08T04:07:18.699Z","updated_at":"2025-04-08T04:07:19.524Z","avatar_url":"https://github.com/skagget77.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Recover GitHub Secrets\nA simple tool for recovering GitHub Actions Secrets from a GitHub repository.\n\nThe tool can be run in three different ways, each with an increased level of security. The least secure way, and the easiest, is to have the client output the secrets directly to the log of the Action runner. Note that the secrets are always encrypted with AES-256 but if the key ever leaks the secrets would be compromised. One level up in security is to have the client send the secrets to another machine instead of writing them to the log. The top level is to have the connection between the client and the remote machine protected by TLS with a custom CA certificate preventing the client from connecting to the wrong machine.\n\n## How To Recover Secrets\n\n### 1. Pull Image\nThere are prebuild docker images for Linux/AMD64, Linux/ARM64v8 and Linux/ARM32v7. All images are hosted on GitHubs Container Registry and can be found [here](https://github.com/skagget77/recover-gh-secrets/pkgs/container/recover-gh-secrets).\n\nPull the lastest Linux/AMD64 image:\n```\n$ docker pull ghcr.io/skagget77/recover-gh-secrets:latest\nlatest: Pulling from skagget77/recover-gh-secrets\n\u003c...hash...\u003e: Pull complete\n\u003c...hash...\u003e: Pull complete\nDigest: sha256:\u003c...digest...\u003e\nStatus: Downloaded newer image for ghcr.io/skagget77/recover-gh-secrets:latest\nghcr.io/skagget77/recover-gh-secrets:latest\n```\n\n### 2. Generate Key\nThe key is used to protect the secrets outside of the repository. Because of this it's important that the key is kept secret.\n\nGenerate a new random key:\n```\n$ docker run --rm ghcr.io/skagget77/recover-gh-secrets genkey\nrgMXauXNOI8Ta4ewmoPJhA61CvwV5zpQKaPaNJ6Rymw=\n```\n\n### 3. Run Server\nThe server can run either with or without TLS. The default port of the server is 19771.\n\nStart the server with TLS:\n```\n$ docker run --rm --network=host ghcr.io/skagget77/recover-gh-secrets server -t\nThe server is listening on: 93.184.216.34:19771 172.17.0.1:19771\nRunning with TLS enabled. Set RECOVER_GH_SECRETS_CERT to the following CA\ncertificate on the client side:\n\n-----BEGIN CERTIFICATE-----\nMIIBsTCCAWOgAwIBAgIBATAFBgMrZXAwYDELMAkGA1UEBhMCU0UxEjAQBgNVBAcT\nCVN0b2NraG9sbTEdMBsGA1UEChMUU2VjcmV0cyBSZWNvdmVyeSBJbmMxHjAcBgNV\nBAMTFVJlY292ZXIgR0ggU2VjcmV0cyBDQTAeFw0yMTA5MTIxNjM4MDNaFw0yMTA5\nMTQxNjM4MDNaMGAxCzAJBgNVBAYTAlNFMRIwEAYDVQQHEwlTdG9ja2hvbG0xHTAb\nBgNVBAoTFFNlY3JldHMgUmVjb3ZlcnkgSW5jMR4wHAYDVQQDExVSZWNvdmVyIEdI\nIFNlY3JldHMgQ0EwKjAFBgMrZXADIQDdxuFyC+EnlHlPP/yEsqkpgiXXMasWwqyi\n+lxoCFkBI6NCMEAwDgYDVR0PAQH/BAQDAgIEMA8GA1UdEwEB/wQFMAMBAf8wHQYD\nVR0OBBYEFPXi3kQbgCr64l/nxh+e9uvLOY7VMAUGAytlcANBAGT/D8fmZgBEuJ8L\nrysYxJcpxEo9bpDQtEn/BbnEZTSLZNvM72y72gmOydWHHU+HExjQ1wgGu9DlEzEg\nZ8hmbQU=\n-----END CERTIFICATE-----\n\nThe certificate is valid for 24 hours. After that time you need to restart\nthe server to issue new certificates\n```\n\nNote that if you're running your server with TLS and it's behind a router with NAT you need to pass the IP address of the router to the `-t` flag. Otherwise the client will refuse to connect since the certificate does not contain the public IP address of the server.\n\n### 4. Run Client\nThe client needs to run as part of GitHub Actions workflow to get access to the GitHub Actions Secrets.\n\nIn the settings for the GitHub repository where the secrets you want to recover are, define a new repository secret named *RECOVER_GH_SECRETS_CERT*. The value should be the certificate written to the terminal by the server in step 3. Here it would be:\n```\n-----BEGIN CERTIFICATE-----\nMIIBsTCCAWOgAwIBAgIBATAFBgMrZXAwYDELMAkGA1UEBhMCU0UxEjAQBgNVBAcT\nCVN0b2NraG9sbTEdMBsGA1UEChMUU2VjcmV0cyBSZWNvdmVyeSBJbmMxHjAcBgNV\nBAMTFVJlY292ZXIgR0ggU2VjcmV0cyBDQTAeFw0yMTA5MTIxNjM4MDNaFw0yMTA5\nMTQxNjM4MDNaMGAxCzAJBgNVBAYTAlNFMRIwEAYDVQQHEwlTdG9ja2hvbG0xHTAb\nBgNVBAoTFFNlY3JldHMgUmVjb3ZlcnkgSW5jMR4wHAYDVQQDExVSZWNvdmVyIEdI\nIFNlY3JldHMgQ0EwKjAFBgMrZXADIQDdxuFyC+EnlHlPP/yEsqkpgiXXMasWwqyi\n+lxoCFkBI6NCMEAwDgYDVR0PAQH/BAQDAgIEMA8GA1UdEwEB/wQFMAMBAf8wHQYD\nVR0OBBYEFPXi3kQbgCr64l/nxh+e9uvLOY7VMAUGAytlcANBAGT/D8fmZgBEuJ8L\nrysYxJcpxEo9bpDQtEn/BbnEZTSLZNvM72y72gmOydWHHU+HExjQ1wgGu9DlEzEg\nZ8hmbQU=\n-----END CERTIFICATE-----\n```\n\nDefine another repository secret named *RECOVER_GH_SECRETS_REMOTE*. The value should be one of the IP addresses written to the terminal by the server in step 3. Here it would be:\n```\n93.184.216.34\n```\n\nDefine yet another repository secret named *RECOVER_GH_SECRETS_KEY*. The value should be the key written to the terminal in step 2. Here it would be:\n```\nrgMXauXNOI8Ta4ewmoPJhA61CvwV5zpQKaPaNJ6Rymw=\n```\n\nUnder Actions in the repository where the secrets you want to recover are add the following as a new workflow:\n```\nname: Recover Secrets\non: workflow_dispatch\njobs:\n  recover:\n    name: Recover Secrets\n    runs-on: ubuntu-latest\n    steps:\n      - name: Recover Secrets\n        uses: docker://ghcr.io/skagget77/recover-gh-secrets:latest\n        with:\n          args: client TEST_SECRET\n        env:\n          RECOVER_GH_SECRETS_CERT: ${{ secrets.RECOVER_GH_SECRETS_CERT }}\n          RECOVER_GH_SECRETS_KEY: ${{ secrets.RECOVER_GH_SECRETS_KEY }}\n          RECOVER_GH_SECRETS_REMOTE: ${{ secrets.RECOVER_GH_SECRETS_REMOTE }}\n          TEST_SECRET: ${{ secrets.TEST_SECRET }}\n```\nWhere `TEST_SECRET` is the name of the secret to recover. The workflow triggers on `workflow_dispatch` which means it has to be started manually. Note that if the workflow is in a branch other than the default branch the trigger needs to be `push` for GitHub to run it.\n\n### 5. Decrypt\nIf the workflow run successfully in step 4 there should be a base64 encoded blob on the server's terminal.\n\nDecrypt the base64 encoded blob:\n```\n$ docker run --rm ghcr.io/skagget77/recover-gh-secrets:latest decrypt \\\n    rgMXauXNOI8Ta4ewmoPJhA61CvwV5zpQKaPaNJ6Rymw= \\\n    O7XIRGVIuCeflQe3H+0hm5wEFhdYm1fRHXlKznUSVR34CuZuHak1lwu6jTDqsrPGMeikMwsFfvc=\nTEST_SECRET=\"My Supercerial Secret\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskagget77%2Frecover-gh-secrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskagget77%2Frecover-gh-secrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskagget77%2Frecover-gh-secrets/lists"}