Home / Alt manpages / gh-secret-list(1)

  • gh-secret-list(1)
  • User command
  • linux

Audit GitHub Secret Scopes with gh secret list

You will finish with a read-only way to inspect which GitHub secret names are visible at repository, environment, organisation or user level. The command does not print secret values, but names and metadata can still disclose how a project is built.

Allow about ten minutes. You need GitHub CLI, an authenticated account with permission to see the target scope, and a repository or organisation to inspect. None of the commands below needs sudo, and this workflow does not create, change or delete a secret.

1. Confirm the local command

Check the executable and its version before copying examples. This matters because the installed help is the contract for the machine you are using:

$ command -v gh
/home/linuxbrew/.linuxbrew/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh secret list --help

On this host, the executable is GitHub CLI 2.87.3 from Linuxbrew. The Debian package database reports a separate gh package version, so do not use that package record as the version of the command selected by PATH. The local help lists the applications actions, codespaces and dependabot. Use gh secret list --help again if your version differs.

Checkpoint

Continue only when command -v gh points to the executable you intended to run and the help output is familiar.

2. Select the repository scope

With no scope flag, gh secret list lists secrets for the current repository. Make the target explicit with --repo when you are outside a checkout or want to avoid an accidental repository context:

$ gh secret list --repo OWNER/REPO
NAME                 UPDATED
DEPLOY_TOKEN         2026-09-20
PACKAGE_SIGNING_KEY  2026-08-11

The names and dates above are illustrative. Your output depends on the repository and your permissions. Replace OWNER/REPO with an actual value such as acme/inventory; do not paste a real token or secret value into the command line.

The repository level is the default. It covers secrets made available to GitHub Actions runs or Dependabot in that repository. If the command reports that you are not logged in, use your normal approved GitHub authentication process; do not put a token in shell history merely to make this listing work.

3. Inspect an environment without confusing it with the repository

An environment is a separate secret level within a repository. Pass its exact name with --env, and keep --repo explicit:

$ gh secret list --repo OWNER/REPO --env production
NAME                 UPDATED
DEPLOY_TOKEN         2026-09-18
PACKAGE_SIGNING_KEY  2026-08-11

An environment listing is not a second view of every repository secret. It tells you about secrets associated with that deployment environment. Names can be similar at both levels, so record the scope alongside any audit result.

Checkpoint

Confirm that the repository and environment names in the command match the deployment you meant to inspect. An empty list can be a correct result, not proof that the repository has no secrets anywhere.

4. Choose organisation or user scope

Use --org for organisation secrets and --user for secrets available to your user. These are alternative scopes, not options to combine with the repository scope:

$ gh secret list --org ORG
NAME             VISIBILITY
CI_READ_TOKEN    all

$ gh secret list --user
NAME             UPDATED
CODESPACE_KEY    2026-09-01

Replace ORG with the organisation login. The local command describes organisation secrets as available to Actions runs, Dependabot or Codespaces within that organisation, while user secrets are available to your Codespaces. GitHub permissions and policy decide which rows you can see.

Do not treat a successful organisation listing as permission to use those secrets. Listing is an audit operation. The command does not reveal values, and it does not test whether a workflow can actually consume a secret.

5. Narrow the application and output

When a scope supports more than one GitHub application, use --app to narrow the listing. The local help accepts actions, codespaces and dependabot:

$ gh secret list --repo OWNER/REPO --app actions
NAME          UPDATED
DEPLOY_TOKEN  2026-09-20

For scripts, request stable JSON fields rather than parsing the aligned table:

$ gh secret list --repo OWNER/REPO --json name,updatedAt
[{"name":"DEPLOY_TOKEN","updatedAt":"2026-09-20T14:32:00Z"}]

The available JSON fields in this installation are name, numSelectedRepos, selectedReposURL, updatedAt and visibility. Filter the JSON with --jq when you need a small report:

$ gh secret list --repo OWNER/REPO --json name,visibility --jq '.[] | [.name, .visibility] | @tsv'
DEPLOY_TOKEN	all

Templates are another option, using --template and the Go template syntax documented by gh help formatting. Keep output restricted to metadata. Avoid writing a full listing to a shared log if the names themselves reveal sensitive project structure.

6. Handle failures without escalating blindly

First rerun the exact command with --help and check the target scope. A missing repository context, misspelled environment, insufficient permission or expired authentication can all prevent a listing. sudo cannot fix any of those GitHub-side conditions.

If a script consumes the result, make failure visible instead of treating an empty output as success:

if ! output=$(gh secret list --repo OWNER/REPO --json name,updatedAt); then
    printf '%s\n' 'secret listing failed' >&2
    exit 1
fi
printf '%s\n' "$output"

This captures metadata only and leaves GitHub unchanged. If you accidentally expose secret names in a log, remove or restrict that log according to your organisation's incident process. There is no undo operation for a listing because it makes no remote state change.

Done means

  • You checked the executable and version actually selected by PATH.
  • You chose one explicit scope: repository, environment, organisation or user.
  • You used --repo, --env or --org where the target was not obvious.
  • You used --json and, where useful, --jq instead of brittle table parsing.
  • You treated secret names and metadata as sensitive and never expected values from this command.
  • You checked the command status so permission or authentication failures cannot look like an empty inventory.