Skip to content

Commit 1f23762

Browse files
authored
fix: class cast exception when handling Failed verification result & signature download on Windows (#158)
Verification result was improperly cast to download result when signature verification failed to run. I discovered this issue while porting the signature verifications to Coder Gateway plugin. Additionally the signature for windows CLI follows the format: coder-windows-amd64.exe.asc Currently it is coded to coder-windows-amd64.asc which means the plugin always fail to find any signature for windows CLI
1 parent 478a5b1 commit 1f23762

File tree

5 files changed

+32
-57
lines changed

5 files changed

+32
-57
lines changed

CHANGELOG.md

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

33
## Unreleased
44

5+
### Fixed
6+
7+
- fix class cast exception during signature verification
8+
- the correct CLI signature for Windows is now downloaded
9+
510
## 0.5.1 - 2025-07-21
611

712
### Added

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
version=0.5.1
1+
version=0.5.2
22
group=com.coder.toolbox
33
name=coder-toolbox

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ class CoderCLIManager(
277277
}
278278

279279
else -> {
280-
UnsignedBinaryExecutionDeniedException((result as Failed).error.message)
281-
val failure = result as DownloadResult.Failed
280+
val failure = result as Failed
281+
UnsignedBinaryExecutionDeniedException(result.error.message)
282282
context.logger.error(failure.error, "Failed to verify signature for ${cliResult.dst}")
283283
}
284284
}
@@ -467,7 +467,7 @@ class CoderCLIManager(
467467
*/
468468
private fun writeSSHConfig(contents: String?) {
469469
if (contents != null) {
470-
if (!context.settingsStore.sshConfigPath.isNullOrBlank()) {
470+
if (context.settingsStore.sshConfigPath.isNotBlank()) {
471471
val sshConfPath = Path.of(context.settingsStore.sshConfigPath)
472472
sshConfPath.parent.toFile().mkdirs()
473473
sshConfPath.toFile().writeText(contents)
@@ -492,9 +492,9 @@ class CoderCLIManager(
492492
throw MissingVersionException("No version found in output")
493493
}
494494
return SemVer.parse(json.version)
495-
} catch (exception: JsonDataException) {
495+
} catch (_: JsonDataException) {
496496
throw MissingVersionException("No version found in output")
497-
} catch (exception: EOFException) {
497+
} catch (_: EOFException) {
498498
throw MissingVersionException("No version found in output")
499499
}
500500
}
@@ -532,7 +532,7 @@ class CoderCLIManager(
532532
val buildVersion =
533533
try {
534534
SemVer.parse(rawBuildVersion)
535-
} catch (e: InvalidVersionException) {
535+
} catch (_: InvalidVersionException) {
536536
context.logger.info("Got invalid build version: $rawBuildVersion")
537537
return null
538538
}

src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -250,42 +250,17 @@ class CoderSettingsStore(
250250
/**
251251
* Return the name of the binary (with extension) for the provided OS and architecture.
252252
*/
253-
private fun getCoderCLIForOS(
254-
os: OS?,
255-
arch: Arch?,
256-
): String {
253+
private fun getCoderCLIForOS(os: OS?, arch: Arch?): String {
257254
logger.debug("Resolving binary for $os $arch")
258-
return buildCoderFileName(os, arch)
259-
}
260-
261-
/**
262-
* Return the name of the signature file (.asc) for the provided OS and architecture.
263-
*/
264-
private fun getCoderSignatureForOS(
265-
os: OS?,
266-
arch: Arch?,
267-
): String {
268-
logger.debug("Resolving signature for $os $arch")
269-
return buildCoderFileName(os, arch, true)
270-
}
271-
272-
/**
273-
* Build the coder file name based on OS, architecture, and whether it's a signature file.
274-
*/
275-
private fun buildCoderFileName(
276-
os: OS?,
277-
arch: Arch?,
278-
isSignature: Boolean = false
279-
): String {
280-
if (os == null) {
281-
logger.error("Could not resolve client OS and architecture, defaulting to WINDOWS AMD64")
282-
return if (isSignature) "coder-windows-amd64.asc" else "coder-windows-amd64.exe"
283-
}
284255

285-
val osName = when (os) {
286-
OS.WINDOWS -> "windows"
287-
OS.LINUX -> "linux"
288-
OS.MAC -> "darwin"
256+
val (osName, extension) = when (os) {
257+
OS.WINDOWS -> "windows" to ".exe"
258+
OS.LINUX -> "linux" to ""
259+
OS.MAC -> "darwin" to ""
260+
null -> {
261+
logger.error("Could not resolve client OS and architecture, defaulting to WINDOWS AMD64")
262+
return "coder-windows-amd64.exe"
263+
}
289264
}
290265

291266
val archName = when (arch) {
@@ -295,14 +270,17 @@ class CoderSettingsStore(
295270
else -> "amd64" // default fallback
296271
}
297272

298-
val extension = if (isSignature) ".asc" else when (os) {
299-
OS.WINDOWS -> ".exe"
300-
OS.LINUX, OS.MAC -> ""
301-
}
302-
303273
return "coder-$osName-$archName$extension"
304274
}
305275

276+
/**
277+
* Return the name of the signature file (.asc) for the provided OS and architecture.
278+
*/
279+
private fun getCoderSignatureForOS(os: OS?, arch: Arch?): String {
280+
logger.debug("Resolving signature for $os $arch")
281+
return "${getCoderCLIForOS(os, arch)}.asc"
282+
}
283+
306284
/**
307285
* Append the host to the path. For example, foo/bar could become
308286
* foo/bar/dev.coder.com-8080.

src/test/kotlin/com/coder/toolbox/store/CoderSettingsStoreTest.kt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,11 @@ class CoderSettingsStoreTest {
3535

3636
@Test
3737
fun `Default CLI and signature for Windows AMD64`() =
38-
assertBinaryAndSignature("Windows 10", "amd64", "coder-windows-amd64.exe", "coder-windows-amd64.asc")
38+
assertBinaryAndSignature("Windows 10", "amd64", "coder-windows-amd64.exe", "coder-windows-amd64.exe.asc")
3939

4040
@Test
4141
fun `Default CLI and signature for Windows ARM64`() =
42-
assertBinaryAndSignature("Windows 10", "aarch64", "coder-windows-arm64.exe", "coder-windows-arm64.asc")
43-
44-
@Test
45-
fun `Default CLI and signature for Windows ARMV7`() =
46-
assertBinaryAndSignature("Windows 10", "armv7l", "coder-windows-armv7.exe", "coder-windows-armv7.asc")
42+
assertBinaryAndSignature("Windows 10", "aarch64", "coder-windows-arm64.exe", "coder-windows-arm64.exe.asc")
4743

4844
@Test
4945
fun `Default CLI and signature for Linux AMD64`() =
@@ -65,13 +61,9 @@ class CoderSettingsStoreTest {
6561
fun `Default CLI and signature for Mac ARM64`() =
6662
assertBinaryAndSignature("Mac OS X", "aarch64", "coder-darwin-arm64", "coder-darwin-arm64.asc")
6763

68-
@Test
69-
fun `Default CLI and signature for Mac ARMV7`() =
70-
assertBinaryAndSignature("Mac OS X", "armv7l", "coder-darwin-armv7", "coder-darwin-armv7.asc")
71-
7264
@Test
7365
fun `Default CLI and signature for unknown OS and Arch`() =
74-
assertBinaryAndSignature(null, null, "coder-windows-amd64.exe", "coder-windows-amd64.asc")
66+
assertBinaryAndSignature(null, null, "coder-windows-amd64.exe", "coder-windows-amd64.exe.asc")
7567

7668
@Test
7769
fun `Default CLI and signature for unknown Arch fallback on Linux`() =

0 commit comments

Comments
 (0)