Skip to content

Commit 0bc801c

Browse files
committed
Pass CLI login tokens via CODER_SESSION_TOKEN instead of --token
Switch the CLI manager to provide session tokens through the CODER_SESSION_TOKEN environment variable when running `coder login` instead of appending `--token <value>` to the process arguments. We’re making this change for security reasons. Command-line arguments are more likely to be exposed through process listings, shell history, CI/job logs, and command auditing, while environment variables have a smaller exposure surface on typical systems. This aligns the plugin with the Coder CLI guidance that prefers CODER_SESSION_TOKEN over `--token`.
1 parent 625daad commit 0bc801c

3 files changed

Lines changed: 27 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Changed
6+
7+
- reduce token exposure in process arguments and command logs
8+
59
## 0.9.0 - 2026-05-14
610

711
### Added

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ support, may trigger regeneration of SSH configurations.
539539
> [!IMPORTANT]
540540
> Token authentication is required when TLS certificates are not configured.
541541
542+
When the plugin logs the Coder CLI in with a session token, it passes that token through the
543+
`CODER_SESSION_TOKEN` environment variable instead of `--token`. This reduces the chances of the token showing up in
544+
process listings, shell history, or command-line audit logs.
545+
542546
## Releasing
543547

544548
1. Check that the changelog lists all the important changes.

src/main/kotlin/com/coder/toolbox/cli/CoderCLIManager.kt

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,9 @@ class CoderCLIManager(
265265
fun login(token: String): String {
266266
context.logger.info("Storing CLI credentials in $coderConfigPath")
267267
return exec(
268+
env = mapOf(CODER_SESSION_TOKEN_ENV_VAR to token),
268269
"login",
269270
deploymentURL.toString(),
270-
"--token",
271-
token,
272271
"--global-config",
273272
coderConfigPath.toString(),
274273
)
@@ -534,17 +533,23 @@ class CoderCLIManager(
534533
return matches
535534
}
536535

537-
private fun exec(vararg args: String): String {
538-
val stdout =
539-
ProcessExecutor()
540-
.command(localBinaryPath.toString(), *args)
541-
.environment("CODER_HEADER_COMMAND", context.settingsStore.headerCommand)
542-
.exitValues(0)
543-
.readOutput(true)
544-
.execute()
545-
.outputUTF8()
546-
val redactedArgs = listOf(*args).joinToString(" ").replace(tokenRegex, "--token <redacted>")
547-
context.logger.info("`$localBinaryPath $redactedArgs`: $stdout")
536+
private fun exec(vararg args: String): String = exec(env = emptyMap(), *args)
537+
538+
private fun exec(env: Map<String, String>, vararg args: String): String {
539+
val executor = ProcessExecutor()
540+
.command(localBinaryPath.toString(), *args)
541+
.exitValues(0)
542+
.readOutput(true)
543+
544+
context.settingsStore.headerCommand?.let {
545+
executor.environment("CODER_HEADER_COMMAND", it)
546+
}
547+
env.forEach { (key, value) ->
548+
executor.environment(key, value)
549+
}
550+
551+
val stdout = executor.execute().outputUTF8()
552+
context.logger.info("`$localBinaryPath ${listOf(*args).joinToString(" ")}`: $stdout")
548553
return stdout
549554
}
550555

@@ -572,7 +577,7 @@ class CoderCLIManager(
572577
}
573578

574579
companion object {
575-
private val tokenRegex = "--token [^ ]+".toRegex()
580+
private const val CODER_SESSION_TOKEN_ENV_VAR = "CODER_SESSION_TOKEN"
576581

577582
private fun getHostnamePrefix(url: URL): String = "coder-jetbrains-toolbox-${url.safeHost()}"
578583

0 commit comments

Comments
 (0)