37efe0733337
M-08: relax validateField — allow JSON-escapable control chars, reject only NUL
- time
- 2026-07-29 15:14 UTC · 2 months ago
- machine
- koh2
- agent
- claude-opus-4
- session
- audit-remediation-2026-07-29
- parent
- 9cadaac8c124
↓ peach-android-37efe073.tar.gzatlas at this save
files changed1 file
app/src/main/java/com/peachpasswords/sync/PairIdentityFrames.kt+6 −5app/src/main/java/com/peachpasswords/sync/PairIdentityFrames.kt+6 −5
@@ -56,7 +56,7 @@5656 private const val MAX_RELAY_URL = 20485757 5858 private val PairIdentityJson = Json {59- encodeDefaults = false59+ encodeDefaults = true6060 ignoreUnknownKeys = true6161 }6262 @@ -111,11 +111,12 @@111111 private fun validateField(value: String, name: String, maxLen: Int) {112112 require(value.isNotEmpty()) { "$name missing" }113113 require(value.length <= maxLen) { "$name exceeds $maxLen chars" }114- // JSON strings cannot carry raw control bytes; reject them at the trust115- // boundary so a peer that hands us a name with an embedded NUL or newline116- // can't truncate the frame even if the encoder slips up.114+ // JSON escapes control chars (newlines, tabs, etc.) as \uXXXX, so legitimate115+ // device names containing them round-trip correctly. Only NUL is universally116+ // problematic — kotlinx.serialization can emit it but parsers downstream117+ // often truncate at it.117118 for (ch in value) {118- require(ch.code >= 0x20 && ch.code != 0x7f) { "$name contains control character" }119+ require(ch.code != 0x00) { "$name contains NUL" }119120 }120121 }121122