Review: forumer-b9907523bffc

Repository: https://github.com/bristinWild/forumer @ b9907523bffc975723762f1766f483d576b677e3
When: 2026-10-28 07:37 UTC · Model: venice/deepseek-v4-1-flash-1017
Sandbox: container dressed as a laptop; the host kernel is not hidden.
The review hit its 150-minute limit and was stopped; what it found by then is below.
The reviewer hit the 150-minute limit before writing its report; it wrote it afterwards from its session (resumed by hand on 2026-10-28), testing nothing more.

Summary: Forumer's cryptographic core is sound: signed canonical posts with PoW/Ed25519/id re-verification, XChaCha20-Poly1305 for private wire/at-rest data, Argon2id vaults, encrypted account state/outbox, parameterised SQL and a bounded sync parser. The serious weaknesses are resource control and metadata privacy. Any author can attach four 96 KiB signed previews per post to an uncapped, never-runtime-pruned SQLite table (remote disk fill), and unsigned mprev/mhere messages grow in-memory maps without a budget. Private-forum posts are sealed at rest but their forum id, persona public key, timestamps and thread graph are stored in clear, so a local file reader learns who posts in which private forum. Holder hints also let a peer make the victim dial loopback/LAN/arbitrary addresses, and CI/release workflows use mutable action refs with a write token. Several smaller findings include unbounded vault KDF parameters, a wrong Markdown backslash assumption, log scrubbing gaps, weak forum-name Unicode validation, and store-page/digest/range work limits. 163/163 core tests passed under ASan/UBSan; the published .lgx QML matches the reviewed source, but the module itself could not be built without Nix/logos-module-builder.

Findings

idseverityfindingconfirmedwhere
FR-1HighSigned posts allow uncapped preview storage; previews are only pruned at startupreadsrc/forumer_backend.cpp:2532-2593; lib/forumer_core/src/post_store.cpp:44-53,344-348; src/forumer_backend.cpp:450-457; src/forumer_backend.h:355; lib/forumer_core/include/forumer_core/media.h
FR-2MediumPrivate-forum post metadata (forum id, persona key, timestamps, reply graph) is stored in clearrunlib/forumer_core/src/post_store.cpp:24-42,248-260,44-53; lib/forumer_core/src/forums.cpp (sealStored seals only envelope)
FR-3MediumUnsigned mprev/mhere messages grow in-memory maps without a budgetreadsrc/forumer_backend.h:526-550; src/forumer_backend.cpp:2317-2350,2378,2536
FR-4MediumHolder hints make the storage node dial attacker-chosen addresses, including loopback/LAN/UDPreadlib/forumer_core/src/sync.cpp:83-105; src/forumer_backend.cpp:2377-2400,2398
FR-5MediumCI/release workflows use mutable action refs and a contents:write release jobread.github/workflows/ci.yml:15-16,39-44; .github/workflows/release.yml:31,36,67; .github/workflows/e3-ui.yml:28,41; .github/workflows/e3-two-node-manual.yml:25,33; .github/workflows/windows-build.yml:17,25
FR-6LowVault accepts unbounded Argon2id parameters from the vault filerunlib/forumer_core/src/vault.cpp:73-84
FR-7LowMarkdown sanitiser backslash assumption is wrong for Qt; limited raw HTML injection/text spoofingrunsrc/qml/markdown.js:21-51,111-130; src/qml/MdText.qml:12-13
FR-8LowLog scrubbing misses full local paths, 16-char private forum ids and 10-char fingerprintsrunsrc/forumer_backend.cpp:433,458,3136,3189,3213,3236,819; lib/forumer_core/include/forumer_core/redact.h:22-40; src/forumer_backend.cpp:74-100
FR-9LowPrivate-forum names accept bidi/invisible/overlong UTF-8; display spoofing and a serialisation throwrunlib/forumer_core/src/forums.cpp:40-60; lib/forumer_core/src/identity.cpp (AccountState::toJson); src/qml/links.js:66-73; src/qml/Sidebar.qml
FR-10LowStore-page parser has no message/size/cursor limits and wraps statusCodereadsrc/delivery_module_transport.cpp:112-155; src/forumer_backend.cpp:3793
FR-11LowPreview answers cross forum boundaries and leak private post idsreadsrc/forumer_backend.cpp:2317-2370,2440-2465; lib/forumer_core/src/post_store.cpp:356-364
FR-12LowPost log rows are trusted on read and not integrity-protectedreadlib/forumer_core/src/post_store.cpp:24-42,248-275,286-300; src/forumer_backend.cpp (loadPost, emitPost, sendOwn)
FR-13LowfetchAround multiplies an unchecked day before validating it (signed overflow)readsrc/forumer_backend.cpp (fetchAround, ~3567-3590)
FR-14LowDisplay fingerprints are only 40 bits and grindablereadlib/forumer_core/src/identity.cpp:52-68
FR-15LowRepository hygiene: committed development log and fixture-looking keyreadgit history commit 3737669 file '-a'; scripts/test-links.mjs:36
FR-16LowStorage upload completion can be attributed to another app's uploadreadsrc/forumer_backend.cpp (storageUploadDone handler ~965-1010; pumpUploads ~1960-2010)
FR-17LowDigest scans and empty range requests still perform per-message workreadlib/forumer_core/src/digest_plan.cpp:10-45,56-75; src/forumer_backend.cpp (handleDigest, handleRange)
FR-18LowreadIndex/vault::open are not exception-safe on malformed local JSONreadlib/forumer_core/src/account_store.cpp (readIndex ~112-132); lib/forumer_core/src/vault.cpp:60-85
FR-19LowA peer can forge outbox Sent confirmationreadsrc/forumer_backend.cpp (confirmHeldByPeers, handleDigest)

Full exploit and fix per finding in report.md.

Screenshots and recording

The whole session in Basecamp, recorded in the sandbox.

installed
forumer open
identity created
phrase
phrase screen
filled
phrase
phrase screen
09 phrase 24 words
home
home with feed
profile
composer
new forum sheet
new forum sheet
new forum named
private forum
composer private
posted private
private thread
settings
settings
alias rejected
alias bidi
after alias
recover
backup
backup
wrong password
phrase shown
phrase shown
image ready
image thread

Usage

model calls200
input tokens42,817,195 (41,285,198 cached)
output tokens105,042
model time1990.7 s
estimated cost$0.8953
provider errors0 (retries 2)

What was run

Not tested

Observed behaviour

Evidence

Triage, not approval. Automated and imperfect; the environment was instrumented.