From e1ed8152d50f0cddf41014cfe460415886c8cf3b Mon Sep 17 00:00:00 2001 From: Valentyn Sobol <8640896+Saloed@users.noreply.github.com> Date: Wed, 22 Apr 2026 18:03:26 +0300 Subject: [PATCH] Add source-sink fingerprint (without trace) --- .../jvm/sast/sarif/SarifGenerator.kt | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/org/opentaint/jvm/sast/sarif/SarifGenerator.kt b/core/src/main/kotlin/org/opentaint/jvm/sast/sarif/SarifGenerator.kt index fca57feac..33f98fdc6 100644 --- a/core/src/main/kotlin/org/opentaint/jvm/sast/sarif/SarifGenerator.kt +++ b/core/src/main/kotlin/org/opentaint/jvm/sast/sarif/SarifGenerator.kt @@ -121,9 +121,11 @@ class SarifGenerator( var partialFingerPrints: Map? = null if (options.generateFingerprint) { - val fingerprint = computeFingerprint(ruleId, sinkLocation, threadFlows) + val fullFingerprint = computeFingerprint(ruleId, sinkLocation, FingerprintKind.FULL_TRACE, threadFlows) + val sourceSinkFingerprint = computeFingerprint(ruleId, sinkLocation, FingerprintKind.SOURCE_SINK, threadFlows) partialFingerPrints = mapOf( - "vulnerabilityWithTraceHash/v1" to fingerprint + "vulnerabilityWithTraceHash/v1" to fullFingerprint, + "vulnerabilitySourceSinkHash/v1" to sourceSinkFingerprint, ) } @@ -153,17 +155,30 @@ class SarifGenerator( return result } + private enum class FingerprintKind { + FULL_TRACE, SOURCE_SINK + } + @OptIn(ExperimentalEncodingApi::class) private fun computeFingerprint( ruleId: String, vulnerabilityLocation: IntermediateLocation, + kind: FingerprintKind, traces: List>? ): String { val digest = MessageDigest.getInstance("SHA-256") digest.update(ruleId.toByteArray()) digest.addLocationFingerprint(vulnerabilityLocation) traces?.forEach { trace -> - trace.forEach { digest.addLocationFingerprint(it) } + when (kind) { + FingerprintKind.FULL_TRACE -> { + trace.forEach { digest.addLocationFingerprint(it) } + } + + FingerprintKind.SOURCE_SINK -> { + trace.firstOrNull()?.let { digest.addLocationFingerprint(it) } + } + } } val digestData = digest.digest() return Base64.encode(digestData)