Created
April 15, 2026 13:35
-
-
Save LeoFalco/37ccdae0bad02aa3c098c319fb9c87b5 to your computer and use it in GitHub Desktop.
List all GitHub Actions secrets (org + repo level) for a GitHub organization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { writeFileSync } from 'node:fs' | |
| import { execSync } from 'node:child_process' | |
| const ORG = 'FieldControl' | |
| const OUTPUT_FILE = 'fieldcontrol-secrets.csv' | |
| function gh(args) { | |
| return execSync(`gh ${args}`, { encoding: 'utf-8', timeout: 30_000 }).trim() | |
| } | |
| function ghJson(args) { | |
| const raw = gh(args) | |
| if (!raw) return [] | |
| return JSON.parse(raw) | |
| } | |
| const lines = ['scope,repo,secret_name,updated_at'] | |
| // Org-level secrets | |
| console.log('Fetching org-level secrets...') | |
| try { | |
| const orgSecrets = ghJson(`api orgs/${ORG}/actions/secrets --paginate --jq '.secrets'`) | |
| for (const secret of orgSecrets) { | |
| lines.push(`org,${ORG},${secret.name},${secret.updated_at}`) | |
| } | |
| console.log(` Found ${orgSecrets.length} org secrets`) | |
| } catch { | |
| console.warn(' Could not list org secrets (needs admin:org scope)') | |
| console.warn(' Run: gh auth refresh -h github.com -s admin:org') | |
| } | |
| // Repo-level secrets | |
| console.log('Fetching repo list...') | |
| const repos = ghJson(`repo list ${ORG} --limit 500 --json name`) | |
| .map(r => r.name) | |
| .sort() | |
| console.log(`Scanning ${repos.length} repos...`) | |
| let repoSecretCount = 0 | |
| for (const [i, repo] of repos.entries()) { | |
| try { | |
| const secrets = ghJson(`secret list --repo "${ORG}/${repo}" --json name,updatedAt`) | |
| for (const secret of secrets) { | |
| lines.push(`repo,${repo},${secret.name},${secret.updatedAt}`) | |
| repoSecretCount++ | |
| } | |
| } catch { | |
| // skip repos where we can't list secrets | |
| } | |
| if ((i + 1) % 20 === 0) { | |
| console.log(` Progress: ${i + 1}/${repos.length}`) | |
| } | |
| } | |
| console.log(`Found ${repoSecretCount} repo secrets`) | |
| writeFileSync(OUTPUT_FILE, lines.join('\n') + '\n') | |
| console.log(`\nCSV written to ${OUTPUT_FILE} (${lines.length - 1} secrets total)`) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment