Audit findings
TalX is continuously reviewed internally: source-code review of the crypto core, complete test and lint runs, a release build with a runtime check, and an ongoing field test on two real devices. This page lists the findings – those fixed and those open.
State of the last cryptography audit
Section titled “State of the last cryptography audit”- 12fixed
- 1high, open
- 0low, open
- 6accepted or informational
Overview of findings
Section titled “Overview of findings”| ID | Title | Severity | Status |
|---|---|---|---|
| F-01 | No X3DH – static initial ratchet root key | Medium | fixed |
| F-02 | WebRTC connection details over the raw static key | Low | fixed |
| F-03 | Backup key derivation not memory-hard | Low | fixed |
| F-04 | Groups: sender keys did not rotate periodically | Low | fixed |
| F-05 | Keystore key not bound to user authentication | Low | accepted |
| F-06 | Relay sees metadata (who with whom, when) | Information | accepted |
| F-07 | No independent external cryptography audit | High | open |
| F-08 | Exportable private identity key during device linking | Information | mitigated |
| F-09 | ML-KEM silently yields a different secret on a tampered capsule | Information | accepted |
| F-10 | Delivery stall after a one-sided session reset | Medium | fixed |
| F-11 | Message-key consumption through retries → overflow | Medium | fixed |
| F-12 | Presence on the local network visible via mDNS | Information | accepted |
| F-13 | Call and connection signals without proof of freshness | Information | accepted |
| F-14 | Server credentials unencrypted in the app settings | Low | resolved |
| F-15 | Post-quantum exchange ran over the ratchet (chicken-and-egg lock) | Medium | fixed |
| F-16 | Data connection activated the microphone; audio session stayed open | Medium | fixed |
| F-17 | Ghost call through stale accept intents | Medium | fixed |
| F-18 | Duplicated restart requests voided the post-quantum secret | Low | fixed |
| F-19 | Contact deletion left group key material behind | Low | fixed |
The open and accepted points, plainly
Section titled “The open and accepted points, plainly”F-07 · No independent external cryptography audit High
Section titled “F-07 · No independent external cryptography audit High”The crypto core has only been reviewed internally and with tools. For a security product that is not a sufficient basis for dependable statements to users: operational blindness and subtle protocol flaws can only be excluded to a limited degree from the inside.
The recommendation, as it stands in the audit report: before any 1.0 or production claim, commission an independent audit by a specialised lab – focusing on the ratchet bootstrap, PAKE choreography, post-quantum integration, call and media signalling, and the relay protocol.
That is why this website never claims TalX has been security-audited. It sits first on the roadmap.
F-05 · Keystore key not bound to user authentication
Section titled “F-05 · Keystore key not bound to user authentication”The wrapping key decrypts the database, the identity and the attachments – and is deliberately created without a binding to user unlock, so that the background service can receive even while the device is locked.
With physical access to an unlockable device the bar is therefore lower. Mitigated by the separate app lock. A separate, auth-bound key for particularly sensitive parts is listed in the report as an optional measure.
F-06 · Relay sees metadata
Section titled “F-06 · Relay sees metadata”The relay receives nothing but ciphertext and identifiers and cannot read content. It does see, however, which identifiers communicate with each other and when. That is inherent to server-based delivery. Mitigation: run the relay yourself, or use TalX purely offline over the short-range paths.
F-09 · Silent mis-encapsulation in ML-KEM
Section titled “F-09 · Silent mis-encapsulation in ML-KEM”Given a tampered but correctly sized capsule, ML-KEM does not report an error but yields a different secret – that is intentional in the FIPS 203 design. A planted capsule therefore only leads to diverging derivations, not to an exploitable compromise. Uncritical, because the capsule is transported authenticated.
F-12 · Presence on the local network
Section titled “F-12 · Presence on the local network”The LAN transport announces itself via mDNS; the service name and the greeting carry the device’s own identifier. Anyone on the same network therefore sees which TalX identities are present – content stays encrypted. That matches the metadata level of the relay, only locally rather than server-side. Accepted for the home-network scenario; ephemeral service identifiers rotating per session are planned as later hardening.
F-13 · Signalling without proof of freshness
Section titled “F-13 · Signalling without proof of freshness”Call signals and connection details are encrypted with authentication but carry no proof of freshness. A network observer can re-deliver recorded blocks; at worst that disrupts an ongoing call. The accept path is additionally protected against repeated intents.
F-08 · The exported identity key
Section titled “F-08 · The exported identity key”For device linking, the private identity key is exported and transferred – the crown jewel. It happens exclusively after a successful J-PAKE and encrypted with the key negotiated in the process. Residual risk: an active attacker who controls the brokering and has observed the code gets exactly one online guess. That is why the user-facing note “only tell the code to your own device” stays in place.
What the internal reviews have found since
Section titled “What the internal reviews have found since”The reviews continue, and they continue to turn things up. That speaks for the depth of the review – and at the same time for the fact that a young codebase still produces such finds. A selection of the most significant since the last cryptography audit:
| What was found | Why it mattered |
|---|---|
| Attachments did not arrive at all. Under load the receive buffer silently dropped pieces; on the sending side a short-circuited condition swallowed the rest of the transfer. | Data loss without any error message – the worst kind. |
| Group messages were silently lost after a gap in the chain. The sender repeated the very same block 30 times, which the other side demonstrably could never open. | Ten minutes of radio traffic for a guaranteed impossible outcome, after which the message was gone. |
| Group decryption failures were completely silent – not a single log line. | With no thread to pull on, tracking it down cost hours. Today the failure is logged, with metadata, never with keys or content. |
| A guaranteed deadlock cycle in the crypto core. Two paths ran through the same two locks in opposite order. | Never observed, because today’s start-up order happens to miss it – but one reordered line would have been enough. A deadlock at start-up is a non-reproducible crash. |
| After a re-pairing nothing arrived for minutes, because a stale prekey survived the key change. | The fault looked like a network problem and was not one. |
| Half-states in device linking and restore. An abort halfway left a partial data set. | Both are all-or-nothing today. |
| Zip-slip in the model download and an unverified model archive. | Fixed, plus built-in checksums. |
| Retained message keys never expired. | They now expire after seven days. |
| A retained key was discarded BEFORE verification ran. The ratchet header travels in the clear – anyone recording a ciphertext and flipping a single byte of the body addresses the same retained key and makes verification fail. | The key was then gone and the real message permanently unreadable. In the attachment path a full disk was enough to trigger it. Today decryption comes first and discarding second. |
| A repeated first message rolled back the running session. The bootstrap fallback could not tell the very first message of a long-running session apart from a genuine fresh start. | For the operator of the brokering that would have been an off switch per chat – with no key material at all, purely by re-delivering a stored message. The session now remembers which of the other side’s keys it grew out of. |
Every one of these points has a regression test that demonstrably fails against the old code.
Test coverage
Section titled “Test coverage”As of 0.85.3: 160 test cases in 27 classes on the JVM and 131 test cases in 40 classes on a real Android runtime.
- Unit tests on the JVM, for both the debug and release variants: J-PAKE, ML-KEM, compression, protocol and wire compatibility, LAN framing including its limits, group forward secrecy, chat-list preview and ordering, model integrity, transfer limits.
- Instrumented tests on a real Android runtime: AES-GCM with additional data, attachment formats, one-time subkeys, the Double Ratchet including prekey bootstrap, the post-quantum transition, periodic group rotation, backup with both derivation methods, the safety number, the complete J-PAKE handshake, ratchet self-healing, defence against ghost calls, cleanup on contact deletion, keystore lock ordering, database migrations, replay handling.
- Two-device field test on real hardware: delivery with confirmation in both directions, a direct connection on the local network, voice and video calls on Wi-Fi only, analysis of the audio sessions before, during and after a call.
- Android Lint with no errors in the crypto core.
- Release build with obfuscation: builds, installs and loads the crypto classes correctly at runtime.
Crypto and database tests deliberately do not run as plain JVM tests: they need the real Android keystore and the native database library.
