You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CLI prints the API token (and other secrets) in full under --format json/pretty and --debug, regardless of --show-sensitive #94
After setting an instance token via context add, I don't want the CLI to ever print that token back out unless I explicitly ask for it. This matters a lot for using the CLI from scripts/AI agents: any command's output can end up in a log file, a transcript, or an agent's context window, and today there's no safe way to guarantee the token (or other secrets) won't be in there.
Fields like the instance token are already tagged sensitive:"true" in the model structs and are correctly hidden by the default table output unless --show-sensitive/-s is passed. That protection only exists in the table formatter, though.
Bug
internal/output/json.go and internal/output/pretty.go marshal structs directly with encoding/json.Encoder, which has no concept of the sensitive struct tag at all. So fetching context/instance details with the json or pretty output format prints the real token in plaintext, even without --show-sensitive. The same is true for every other sensitive:"true" field across the codebase — SSH private/public keys (the private-key commands), webhook secrets, OAuth client secrets, database/service environment variable values, server IP/user, etc. A few individual commands (cloud-token, s3, cloudinit) have their own hand-rolled redaction for their one specific field, but most commands have none, so the underlying model's real value goes straight to stdout.
Separately, debug mode logs full request/response bodies to stderr and only masks the literal JSON key named "token" — every other sensitive field above is printed there too, independent of the output format or show-sensitive flag entirely.
Impact
This already leaked a live Coolify API token (and, separately, private key material) into an AI coding agent's transcript, just from running an ordinary structured-output command for inspection.
Expected behavior
Any field marked sensitive:"true" should be hidden (********) under every output format — table, json, and pretty — unless --show-sensitive/-s is explicitly passed, exactly like table output already behaves. Debug logging should never print real secret values regardless of flags, since it's a diagnostic trace, not a deliberate request to reveal a value.
Fix
I've written and verified a fix (reflection-based redaction shared across all three formatters, plus closing the same gap in the debug logger) and will open a PR against main shortly.
One addition to the report above, found while hardening the fix in #95.
models.Database carries ten database credentials — postgres_password, mysql_root_password, mysql_password, mariadb_root_password, mariadb_password, mongo_initdb_root_password, redis_password, keydb_password, clickhouse_admin_password, dragonfly_password — that are not tagged sensitive:"true" at all. They carry table:"-", which keeps them out of the table columns, but that tag only controls column selection, not redaction. So they leak through both paths described in this issue, and they would still have leaked after a fix that only taught the json/pretty formatters to honour the existing tags:
$ coolify database get <uuid> --format json
{"uuid":"...","name":"db","postgres_password":"<real password>","redis_password":"<real password>"}
Same under --debug, since the debug logger redacts by JSON key name and these names weren't in its set either.
#95 now tags all ten and adds their names to the debug key set. It also adds a test that parses internal/models and internal/config and fails if any sensitive:"true" field's JSON name is missing from that set — so the next tag added to a model can't silently keep being logged in full, which is the class of gap that let these ten sit untagged in the first place.
Two adjacent exposure paths I noticed while tracing this, both predating the formatter bug and both out of scope for #95 — happy to open separate issues if either is worth tracking:
internal/api/client.go: on a non-2xx response whose body has no message/error key, the raw response body is surfaced to the user verbatim, with no redaction and independent of --debug/--show-sensitive. A validation error echoing the submitted payload would print whatever secret was in it.
internal/service/deployment.go: deployment logs are returned as a raw JSON string that never passes through internal/output, so nothing in them is redacted.
Activity
noamloewenstern commentedon Sep 17, 2026
One addition to the report above, found while hardening the fix in #95.
models.Databasecarries ten database credentials —postgres_password,mysql_root_password,mysql_password,mariadb_root_password,mariadb_password,mongo_initdb_root_password,redis_password,keydb_password,clickhouse_admin_password,dragonfly_password— that are not taggedsensitive:"true"at all. They carrytable:"-", which keeps them out of the table columns, but that tag only controls column selection, not redaction. So they leak through both paths described in this issue, and they would still have leaked after a fix that only taught the json/pretty formatters to honour the existing tags:Same under
--debug, since the debug logger redacts by JSON key name and these names weren't in its set either.#95 now tags all ten and adds their names to the debug key set. It also adds a test that parses
internal/modelsandinternal/configand fails if anysensitive:"true"field's JSON name is missing from that set — so the next tag added to a model can't silently keep being logged in full, which is the class of gap that let these ten sit untagged in the first place.Two adjacent exposure paths I noticed while tracing this, both predating the formatter bug and both out of scope for #95 — happy to open separate issues if either is worth tracking:
internal/api/client.go: on a non-2xx response whose body has nomessage/errorkey, the raw response body is surfaced to the user verbatim, with no redaction and independent of--debug/--show-sensitive. A validation error echoing the submitted payload would print whatever secret was in it.internal/service/deployment.go: deployment logs are returned as a raw JSON string that never passes throughinternal/output, so nothing in them is redacted.noamloewenstern commentedon Sep 29, 2026
Any update?
JKamsker commentedon Oct 12, 2026
Would also like to see a fix for this - my agents constantly reveal the api keys