aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-06 10:24:23 +0100
committerDanilo M. <danix@danix.xyz>2026-11-06 10:24:23 +0100
commit4f1b534aec26e6f33e40f877282465f334c5f1fd (patch)
tree0a1ccdf8182a0adbef4486888d077504690f7f4d
parent9ec740b0c73e33485e1d754759de46aa99444733 (diff)
downloadHardenedPass-4f1b534aec26e6f33e40f877282465f334c5f1fd.tar.gz
HardenedPass-4f1b534aec26e6f33e40f877282465f334c5f1fd.zip
fix(app): keep sensitive details out of debug logs
A log export makes logs easy to share, so audit what they hold. Turn off the sshj trace level, which dumps SSH packets in the clear, password authentication included; until now only the minimum priority of the Android logger kept it out. Drop entry names from commit and autofill match lines, and log only descriptive HTML attributes of form fields, since value and placeholder can hold what the user typed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--app/src/main/java/app/passwordstore/ui/list/StoreActions.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt7
-rw-r--r--autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt9
-rw-r--r--autofill-parser/src/test/kotlin/com/github/androidpasswordstore/autofillparser/FormFieldLogTest.kt19
6 files changed, 33 insertions, 8 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt b/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
index 94a234c1..f300a814 100644
--- a/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
+++ b/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
@@ -179,7 +179,7 @@ private suspend fun BaseGitActivity.moveFile(source: File, destination: File): B
}
}
if (!moved) {
- logcat(ERROR) { "Something went wrong while moving $source to $destination." }
+ logcat(ERROR) { "Something went wrong while moving a file." }
prompts.ask(
title = getString(R.string.password_move_error_title),
message = getString(R.string.password_move_error_message, source, destination),
diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt
index dbaa5675..b4b3d017 100644
--- a/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt
+++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt
@@ -194,7 +194,7 @@ class AutofillMatcher {
.minus(oldNewPathMap.values)
.map { match ->
val newPath = oldNewPathMap[match] ?: return@map match
- logcat { "Updating match for $key: $match --> $newPath" }
+ logcat { "Updating match for $key" }
newPath
}
.toSet()
diff --git a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
index 382a5617..e24f96ca 100644
--- a/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
+++ b/app/src/main/java/app/passwordstore/util/extensions/AndroidExtensions.kt
@@ -71,7 +71,7 @@ suspend fun FragmentActivity.commitChange(message: String): Result<Unit, Throwab
)
override suspend fun preExecute(): Boolean {
- logcat { "Committing with message: '$message'" }
+ logcat { "Committing" }
return true
}
}
diff --git a/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt b/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt
index c62e60a8..948e3fa9 100644
--- a/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt
+++ b/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt
@@ -12,7 +12,8 @@ import logcat.logcat
/** An implementation of [AbstractLogger] that forwards logging calls to [logcat]. */
class LogcatLogger(name: String) : AbstractLogger(name) {
- override fun isTraceEnabled() = true
+ // sshj's trace level dumps every SSH packet in the clear, passwords included. Never log it.
+ override fun isTraceEnabled() = false
override fun isDebugEnabled() = true
@@ -27,9 +28,7 @@ class LogcatLogger(name: String) : AbstractLogger(name) {
@Suppress("RegExpRedundantEscape")
private fun String.fix() = replace("""(?!<\\)\{\}""".toRegex(), "%s")
- override fun t(message: String, t: Throwable?, vararg args: Any?) {
- logcat(name, LogPriority.VERBOSE) { message.fix().format(*args) + (t?.asLog() ?: "") }
- }
+ override fun t(message: String, t: Throwable?, vararg args: Any?) = Unit
override fun d(message: String, t: Throwable?, vararg args: Any?) {
logcat(name) { message.fix().format(*args) + (t?.asLog() ?: "") }
diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt
index b8df0664..bcd1081d 100644
--- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt
+++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt
@@ -141,7 +141,7 @@ internal class FormField(
?.filter { it.first != null && it.second != null }
?.associate { Pair(it.first.lowercase(Locale.US), it.second.lowercase(Locale.US)) }
?: emptyMap()
- private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" }
+ private val htmlAttributesDebug = htmlAttributesForLog(htmlAttributes)
private val htmlInputType = htmlAttributes["type"]
private val htmlName = htmlAttributes["name"] ?: ""
private val htmlMaxLength = htmlAttributes["maxlength"]?.toIntOrNull()
@@ -292,3 +292,10 @@ internal class FormField(
return autofillId.hashCode()
}
}
+
+/** The [attributes] that describe a field: `value` and the like can hold what the user typed. */
+internal fun htmlAttributesForLog(attributes: Map<String, String>): String =
+ attributes
+ .filterKeys { it in setOf("id", "name", "type", "autocomplete", "maxlength") }
+ .entries
+ .joinToString { "${it.key}=${it.value}" }
diff --git a/autofill-parser/src/test/kotlin/com/github/androidpasswordstore/autofillparser/FormFieldLogTest.kt b/autofill-parser/src/test/kotlin/com/github/androidpasswordstore/autofillparser/FormFieldLogTest.kt
new file mode 100644
index 00000000..be6b4b32
--- /dev/null
+++ b/autofill-parser/src/test/kotlin/com/github/androidpasswordstore/autofillparser/FormFieldLogTest.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+package com.github.androidpasswordstore.autofillparser
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class FormFieldLogTest {
+
+ @Test
+ fun onlyDescriptiveAttributesAreLogged() {
+ val attributes =
+ mapOf("type" to "email", "value" to "me@example.org", "placeholder" to "me@example.org")
+ assertEquals("type=email", htmlAttributesForLog(attributes))
+ }
+}