Skip to content

Commit

Permalink
fix: use sha256 for logging a hashed token
Browse files Browse the repository at this point in the history
The changes introduce a SHA-256 hashing function for strings and use it to log the hash of the Snyk authentication token instead of the Java `hashCode()` method.  This improves security by avoiding logging potentially sensitive information in plain text, even in debug logs.  The `hashCode()` method is not suitable for security purposes as it's not cryptographically secure and can lead to collisions.

Here's a breakdown:

* **`src/main/kotlin/io/snyk/plugin/Utils.kt`**: This file adds the `sha256()` extension function to the `String` class. This function computes the SHA-256 hash of the string and returns it as a hexadecimal string.

* **`src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt`**:  In the `hasAuthenticated` function:
    - The old token is now fetched with a null-safe operator (`?: ""`) to handle cases where no token is present.
    -  The logging lines using `oldToken.hashCode()` and `param.token.hashCode()` are replaced with `oldToken.sha256()` and `param.token?.sha256()` respectively. This change ensures that the actual token value is never logged, even in debug mode.  The null-safe operator (`?.`) on `param.token` handles the case where the new token might be null.

In summary, these changes improve the security of the plugin by preventing the accidental logging of sensitive authentication tokens. They replace the insecure `hashCode()` method with a proper cryptographic hash function (SHA-256) for logging purposes, offering better protection against information leakage.
  • Loading branch information
bastiandoetsch committed Feb 10, 2025
1 parent f917a70 commit 3351fd0
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/main/kotlin/io/snyk/plugin/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import java.net.URI
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.security.MessageDigest
import java.util.Objects.nonNull
import java.util.SortedSet
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -465,6 +466,13 @@ fun VirtualFile.isExecutable(): Boolean = this.toNioPathOrNull()?.let { Files.is

fun VirtualFile.isWhitelistedForInclusion() = this.name == "project.assets.json" && this.parent.name == "obj"

fun String.sha256(): String {
val bytes = this.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
val digest = md.digest(bytes)
return digest.fold("") { str, it -> str + "%02x".format(it) }
}

inline fun runInBackground(
title: String,
project: Project? = null,
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/snyk/common/lsp/SnykLanguageClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import io.snyk.plugin.getContentRootVirtualFiles
import io.snyk.plugin.getSyncPublisher
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.refreshAnnotationsForOpenFiles
import io.snyk.plugin.sha256
import io.snyk.plugin.toVirtualFile
import io.snyk.plugin.ui.SnykBalloonNotificationHelper
import io.snyk.plugin.ui.toolwindow.SnykPluginDisposable
Expand Down Expand Up @@ -282,7 +283,7 @@ class SnykLanguageClient :
@JsonNotification(value = "$/snyk.hasAuthenticated")
fun hasAuthenticated(param: HasAuthenticatedParam) {
if (disposed) return
val oldToken = pluginSettings().token
val oldToken = pluginSettings().token ?: ""
val oldApiUrl = pluginSettings().customEndpointUrl
if (oldToken == param.token && oldApiUrl == param.apiUrl) return

Expand All @@ -293,7 +294,7 @@ class SnykLanguageClient :
logger.info("received authentication information: Token-Length: ${param.token?.length}}, URL: ${param.apiUrl}")
logger.info("use token-auth? ${pluginSettings().useTokenAuthentication}")
logger.debug("is same token? ${oldToken == param.token}")
logger.debug("old-token-hash: ${oldToken.hashCode()}, new-token-hash: ${param.token.hashCode()}" )
logger.debug("old-token-hash: ${oldToken.sha256()}, new-token-hash: ${param.token?.sha256()}" )

pluginSettings().token = param.token

Expand All @@ -302,7 +303,7 @@ class SnykLanguageClient :
StoreUtil.saveSettings(ApplicationManager.getApplication(), true)
logger.info("force-saved settings")

if (oldToken.isNullOrBlank() && !param.token.isNullOrBlank() && pluginSettings().scanOnSave) {
if (oldToken.isBlank() && !param.token.isNullOrBlank() && pluginSettings().scanOnSave) {
val wrapper = LanguageServerWrapper.getInstance()
ProjectManager.getInstance().openProjects.forEach {
wrapper.sendScanCommand(it)
Expand Down

0 comments on commit 3351fd0

Please sign in to comment.