Skip to content

Commit aeb79e5

Browse files
committed
impl: prompt the user if when signature verification fails
Ask the user if he wants to accept the risk of running a potentially tampered CLI when signature verification failed (i.e. we downloaded the signatures but either it doesn't match or there were some error while computing the signature.
1 parent 881a662 commit aeb79e5

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

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

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.coder.toolbox.cli.ex.MissingVersionException
99
import com.coder.toolbox.cli.ex.SSHConfigFormatException
1010
import com.coder.toolbox.cli.ex.UnsignedBinaryExecutionDeniedException
1111
import com.coder.toolbox.cli.gpg.GPGVerifier
12+
import com.coder.toolbox.cli.gpg.VerificationResult
1213
import com.coder.toolbox.cli.gpg.VerificationResult.Failed
1314
import com.coder.toolbox.cli.gpg.VerificationResult.Invalid
1415
import com.coder.toolbox.sdk.v2.models.Workspace
@@ -221,26 +222,21 @@ class CoderCLIManager(
221222
}
222223

223224
else -> {
224-
val exception = when {
225-
result.isInvalid() -> {
226-
val reason = (result as Invalid).reason
227-
UnsignedBinaryExecutionDeniedException(
228-
"Signature of ${cliResult.dst} is invalid." + reason?.let { " Reason: $it" }
229-
.orEmpty()
230-
)
231-
}
232-
233-
result.signatureIsNotFound() -> {
234-
UnsignedBinaryExecutionDeniedException(
235-
"Can't verify signature of ${cliResult.dst} because ${signatureResult.dst} does not exist"
236-
)
237-
}
238-
239-
else -> {
240-
UnsignedBinaryExecutionDeniedException((result as Failed).error.message)
241-
}
225+
logFailure(result, cliResult, signatureResult)
226+
// prompt the user if he wants to accept the risk
227+
val shouldRunAnyway = context.ui.showYesNoPopup(
228+
context.i18n.ptrl("Security Warning"),
229+
context.i18n.pnotr("Could not verify the authenticity of the ${cliResult.source}, it may be tampered with. Would you like to run it anyway?"),
230+
context.i18n.ptrl("Run anyway"),
231+
context.i18n.ptrl("Abort"),
232+
)
233+
234+
if (shouldRunAnyway) {
235+
downloader.commit()
236+
return true
237+
} else {
238+
throw UnsignedBinaryExecutionDeniedException("Running unverified CLI from ${cliResult.source} was denied by the user")
242239
}
243-
throw exception
244240
}
245241
}
246242
}
@@ -249,6 +245,30 @@ class CoderCLIManager(
249245
}
250246
}
251247

248+
private fun logFailure(
249+
result: VerificationResult,
250+
cliResult: Downloaded,
251+
signatureResult: Downloaded
252+
) {
253+
when {
254+
result.isInvalid() -> {
255+
val reason = (result as Invalid).reason
256+
context.logger.error("Signature of ${cliResult.dst} is invalid." + reason?.let { " Reason: $it" }
257+
.orEmpty())
258+
}
259+
260+
result.signatureIsNotFound() -> {
261+
context.logger.error("Can't verify signature of ${cliResult.dst} because ${signatureResult.dst} does not exist")
262+
}
263+
264+
else -> {
265+
UnsignedBinaryExecutionDeniedException((result as Failed).error.message)
266+
val failure = result as DownloadResult.Failed
267+
context.logger.error(failure.error, "Failed to verify signature for ${cliResult.dst}")
268+
}
269+
}
270+
}
271+
252272
/**
253273
* Use the provided token to initializeSession the CLI.
254274
*/

src/main/kotlin/com/coder/toolbox/cli/downloader/DownloadResult.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,5 @@ sealed class DownloadResult {
1919

2020
fun isFailed(): Boolean = this is Failed
2121

22-
fun isDownloaded(): Boolean = this is Downloaded
23-
2422
fun isNotDownloaded(): Boolean = this !is Downloaded
2523
}

src/main/resources/localization/defaultMessages.po

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,7 @@ msgid "Accept"
161161
msgstr ""
162162

163163
msgid "Abort"
164+
msgstr ""
165+
166+
msgid "Run anyway"
164167
msgstr ""

0 commit comments

Comments
 (0)