fix(android): escape JS bridge args via JSONObject.quote (#7925)

`loadFromDb` interpolated the stored value into a single-quoted JS string
literal passed to `evaluateJavascript`. Beyond the security smell, this is
a real data-loss bug: `JSON.stringify` does not escape apostrophes, so a
backup blob containing one (e.g. a task titled "don't…") terminated the JS
literal and the load returned garbage — silently corrupting any restore
from `KeyValStore`.

Use `JSONObject.quote()` (already established in the file for
`emitForegroundServiceStartFailed`) for all three callback args, so values
containing `'`, `\`, newlines or `</script>` round-trip cleanly.
This commit is contained in:
johannesjo 2026-06-01 23:14:59 +02:00
parent 7483ba241b
commit 663d747b4c

View file

@ -100,8 +100,18 @@ class JavaScriptInterface(
@JavascriptInterface
fun loadFromDb(requestId: String, key: String) {
val r = (activity.application as App).keyValStore.get(key, "")
// NOTE: ' are important as otherwise the json messes up
callJavaScriptFunction(FN_PREFIX + "loadFromDbCallback('" + requestId + "', '" + key + "', '" + r + "')")
// Use JSONObject.quote() so the stored value can contain ' / \ / newlines /
// </script> without breaking out of the JS literal (#7925). The previous
// raw single-quote interpolation broke on any value with a literal '
// (JSON.stringify does not escape apostrophes), so an apostrophe in a
// backup blob silently corrupted the load. quote() produces a properly
// escaped double-quoted JS string.
callJavaScriptFunction(
FN_PREFIX + "loadFromDbCallback(" +
JSONObject.quote(requestId) + ", " +
JSONObject.quote(key) + ", " +
JSONObject.quote(r) + ")"
)
}
@Suppress("unused")