fix: accept comma in Fly.io macaroon tokens & handle flat org dict (#1593)

Real `fly auth token` returns comma-separated multi-segment macaroon
tokens (fm2_...,fm2_...,fo1_...). The token validation regex rejected
commas, forcing re-auth on every run. Add comma to the allowed charset.

`fly orgs list --json` returns a flat dict ({"slug": "Name"}) on some
flyctl versions, not the list/nodes format the parser expected. Detect
and handle both formats so the org picker works correctly.

Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
A 2026-02-21 08:20:48 -08:00 committed by GitHub
parent ed9501235b
commit 3db19d90ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 13 deletions

View file

@ -190,16 +190,23 @@ _fly_list_orgs() {
import json, sys
try:
data = json.loads(sys.stdin.read())
orgs = data if isinstance(data, list) else data.get('nodes', data.get('organizations', []))
if not orgs:
sys.exit(1)
for o in orgs:
slug = o.get('slug') or o.get('name') or ''
name = o.get('name') or slug
otype = o.get('type') or ''
suffix = ' (' + otype + ')' if otype else ''
if slug:
print(slug + '|' + name + suffix)
if isinstance(data, dict) and not any(k in data for k in ('nodes', 'organizations')):
# Flat dict format: {'slug': 'Display Name', ...}
if not data:
sys.exit(1)
for slug, name in data.items():
print(slug + '|' + str(name))
else:
orgs = data if isinstance(data, list) else data.get('nodes', data.get('organizations', []))
if not orgs:
sys.exit(1)
for o in orgs:
slug = o.get('slug') or o.get('name') or ''
name = o.get('name') or slug
otype = o.get('type') or ''
suffix = ' (' + otype + ')' if otype else ''
if slug:
print(slug + '|' + name + suffix)
except Exception:
sys.exit(1)
" 2>/dev/null

View file

@ -2766,10 +2766,11 @@ _load_token_from_config() {
# SECURITY: Validate token characters to prevent curl config injection via -K -
# Similar to key-request.sh _try_load_env_var (^[a-zA-Z0-9._/@-]+$) but also
# allows colon (:) for Fly.io FlyV1 tokens and URL-style formats,
# plus (+) / equals (=) for base64-encoded token segments, and
# plus (+) / equals (=) for base64-encoded token segments,
# comma (,) for multi-segment macaroon tokens (fm2_...,fm2_...,fo1_...), and
# space ( ) for Fly.io "FlyV1 <macaroon>" prefixed tokens.
# Space is safe inside curl -K double-quoted values: header = "Authorization: FlyV1 fm2_..."
if [[ ! "${saved_token}" =~ ^[a-zA-Z0-9._/@:+=\ -]+$ ]]; then
# Space and comma are safe inside curl -K double-quoted values.
if [[ ! "${saved_token}" =~ ^[a-zA-Z0-9._/@:+=,\ -]+$ ]]; then
log_warn "Saved ${provider_name} token is malformed — clearing cached credentials."
rm -f "${config_file}" 2>/dev/null || true
return 1