runner tokens
Gerencia tokens GitHub registrados nas apps. Tokens NUNCA são mostrados em plaintext — apenas fingerprints. Disponivel a partir da v2.13.0.
Sintaxe
runner tokens list [--json]
runner tokens test <app> [--json]
runner tokens reveal <app> --insecure [--json]E no runner add:
runner add --repo <r> --branch <b> --token-from <APP>`runner tokens list`
Enumera tokens registrados, agrupados por fingerprint. Apps que compartilham token aparecem juntas no mesmo grupo.
Output humano
Tokens (2):
--------------------------------------------------------------------------------
tk_a1b2…c3d4 | 3 app(s) | app1, app2, app3
tk_e5f6…g7h8 | 1 app(s) | app4Output JSON
{
"count": 2,
"tokens": [
{
"fingerprint": "tk_a1b2…c3d4",
"apps_count": 3,
"apps": ["app1", "app2", "app3"]
},
{
"fingerprint": "tk_e5f6…g7h8",
"apps_count": 1,
"apps": ["app4"]
}
]
}Contrato de seguranca
- Tokens em plaintext nunca aparecem no output (qualquer formato)
- Apenas o fingerprint sha256 (12 chars hex, formato
tk_4hex…4hex) eh exibido - A lista eh derivada lendo cada state file e descriptografando localmente — sem trafego de rede
`runner tokens test `
Valida o token de uma app via GitHub API (GET /user). Desde a v2.158.0,
quando a app tem cofre (.runner/secrets.enc), também testa se o token
escreve no repositório:
runner tokens test app1
# Token VALID for app1:
# Fingerprint: tk_a1b2…c3d4
# Username: devborlot
# Scopes: repo, workflowOutput JSON
{
"valid": true,
"app": "app1",
"fingerprint": "tk_a1b2…c3d4",
"username": "devborlot",
"scopes": ["repo", "workflow"],
"write": true
}write é true, false ou null (a app não tem cofre ou não deu para
testar).
Erros
| Cenario | Comportamento |
|---|---|
| App nao tem token configurado | Exit 1, erro no_token_configured |
| Token revogado/invalido | Exit 1, output JSON com "valid": false, http_status, error |
| Erro de rede | Exit 1, mensagem do reqwest |
| Token só lê e a app tem cofre (v2.158.0+) | Exit 1, "write": false e error com token_sem_escrita |
Como o teste funciona
- Carrega
state.github_token(encriptado) - Decrypt com mkey atual
- Calcula fingerprint pra mostrar
- Pergunta à API do provedor do repositório quem é o token:
- GitHub (
github.com):GET https://api.github.com/user, escopos no headerx-oauth-scopes; - GitLab (v2.192.0+, por https):
GET /api/v4/personal_access_tokens/selfna instância do repositório, com escopos e validade (expires_at); - demais provedores: sem API de token. A validade é provada por um
git ls-remote, escopes_auditaveissaifalse.
- GitHub (
- Com cofre: pede ao servidor git o começo de um push
(
info/refs?service=git-receive-pack). 200 = escreve, 403 = só lê. Nada é escrito.
Por que a escrita importa
A cada mudança de secret, o runner comita e dá push no .runner/secrets.enc.
Com um PAT fine-grained em Contents: Read-only, esse push falha. O cofre
do repositório fica com o valor antigo, e uma recuperação do zero
(--ckey) traria de volta um segredo já trocado. Desde a v2.158.0:
runner tokens setrecusa token sem escrita em app com cofre (token_sem_escrita). O token antigo fica intacto.runner tokens auditmarca a credencial comono_writee lista as apps.- O deploy testa a escrita antes de comitar o cofre. Sem escrita, termina
pendente com
secrets_push_token_rejected.
No PAT fine-grained, dê Contents: Read and write nos repositórios das apps.
O token plaintext nao aparece em nenhum log/output.
`runner tokens reveal ` (v2.23.3+)
Revela o token GitHub em plaintext para uma app. Gated por --insecure (audit-logged). Mirror do runner ckeys reveal.
runner tokens reveal meu-app --insecure
# WARNING: plaintext GitHub token printed below. Store in password manager and clear terminal scrollback.
# app: meu-app
# fingerprint: tk_a1b2…c3d4
# ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
runner tokens reveal meu-app --insecure --json | jq -r .plaintextQuando usar
- Operações git ad-hoc fora do runner (clone de inspeção, push de file unrelated)
- Scripts que precisam do PAT pra chamar GitHub API
- Debug em emergência
Quando NÃO usar
- Para reusar o token em outra app no mesmo servidor — use
--token-from <APP>emrunner add - Para teste de validade — use
runner tokens test <app> - Sem motivo claro — cada reveal vira audit event em
/opt/runner/logs/runner.log
Erros
| Cenario | Comportamento |
|---|---|
Falta --insecure |
Exit 1, mensagem: "tokens reveal prints the plaintext..." |
| App não tem token | Exit 1, no_token_configured |
| mkey mismatch (token criado com outra mkey) | Exit 1, "Failed to decrypt token" |
`runner add --token-from `
Reusa o token de outra app ja registrada. Util quando varias apps usam o mesmo token (ex: todas as repos da mesma org).
# Primeiro registro
runner add --repo devborlot/app1 --branch main --token ghp_xxx --ckey
# Reusing token from 'app1' (fingerprint: tk_a1b2…c3d4)
# Apps subsequentes — sem precisar do plaintext do token
runner add --repo devborlot/app2 --branch main --token-from app1
runner add --repo devborlot/app3 --branch main --token-from app1Comportamento
- Mutuamente exclusivo com
--token(clap rejeita ambos) - Decrypt local da mkey + re-encrypt pra nova app, plaintext nunca persiste fora do state file
- Fingerprint mostrado em stderr pra confirmacao visual
- Falha com
token_source_not_foundoutoken_source_no_tokense a app fonte nao existe ou nao tem token
Erros
| Erro | Causa |
|---|---|
token_source_not_found |
App fonte nao existe no state dir |
token_source_no_token |
App fonte existe mas nao tem state.github_token |
Conflict com --token |
Clap erro: "argument '--token' cannot be used with '--token-from'" |
Quando usar
| Cenario | Comando recomendado |
|---|---|
| Identificar quantos tokens distintos estao em uso | runner tokens list |
| Auditar quais apps compartilham um token | runner tokens list --json |
| Verificar se um token ainda eh valido | runner tokens test <app> |
| Registrar nova app reusando token existente | runner add --token-from <other-app> |
| Rotacionar um token compartilhado | (manual) gerar novo, runner edit --token em cada app |
| Recuperar token pra scripts/debug | runner tokens reveal <app> --insecure (v2.23.3+) |
Veja Tambem
- runner add — registrar app
- runner edit — atualizar token de uma app existente
- Secrets e Encriptacao — duas-camadas (mkey + ckey)