Tecmie · Independent Security Review
Independent verification of an internal, AI-assisted security assessment — issued under Tecmie's name, grounded in our own source review and live reproduction.
Robin engaged Tecmie to independently verify an internal, AI-assisted security assessment of Robin Enterprise and to issue our own report. We reviewed all 27 findings against the source at both the assessed and remediated commits, reproduced the most serious ones against live instances, and formed our own view of severity. This report is our assessment, not a countersignature of Robin's.
We concur that the findings are real and that the remediations close them. One finding is a genuine High: an anonymous attacker could seize an invited account with no proof of mailbox control. The rest are authenticated-origin issues — a member or an organization administrator reading another workspace's private content or instance-wide data they should not see. Under the confirmed single-organization deployment, the workspace is the tenancy boundary, and several of these reads break the workspace-confidentiality guarantee the product is sold on. All 27 are fixed at 94610791, three with minor residuals noted below.
Where we differ from the internal assessment is severity, not facts. Robin's scoring multiplies any authenticated-origin finding by 0.2, which caps every insider finding at 4.4 and lands 21 of 27 as "Informational." We think that buries reads which cross a workspace boundary the product treats as a security boundary. We keep Robin's metric score for traceability and add a Tecmie severity for those findings, with rationale, in the register.
| Findings reviewed | 27 |
| Independently reproduced by Tecmie (live) | 7 TEC-001, 003, 004, 005, 017, 018, 025 |
| Concurred from source review only | 20 |
Open at 94610791 | 0 |
| Closed with a noted residual | 3 TEC-011, 014, 019 |
Robin's published distribution is 1 High / 1 Medium / 4 Low / 21 Informational. The difference is a re-rating on impact of five findings the origin multiplier held down — not new evidence — and it stays short of Critical because single-org gives no anonymous path to the insider reads.
In scope: the server-side application, workspace packages, and configuration at the two commits — authentication and session handling, the authorization and tenant-isolation layer, the MCP tool surface, background workers, the LLM boundary, data lifecycle, and dependency and configuration posture.
Out of scope / not independently verified: the Next.js frontend beyond the published-wiki render sink; third-party dependency internals beyond version and reachability; production infrastructure and runtime configuration; and the 16 findings we did not reproduce live (we concur from source review, stated per finding).
Method. Source review at both commits, verifying each finding's cited code path and each remediation line-for-line; then live reproduction of the High, the four cross-workspace reads, the related enumeration finding, and the anonymous chain, against a running pre-remediation instance and a freshly built, migrated, and seeded 94610791 instance.
Severity. Robin's metric is retained as the "Assessed score." Tecmie severity is assigned on business impact under the single-org model, diverging only where the metric's attack-origin multiplier collapses a real cross-workspace exposure to Informational.
Against a live pre-remediation instance and a fresh 94610791 instance:
| Finding | Pre-remediation, observed | Remediated, observed |
|---|---|---|
| TEC-001 | email-only sign-up for an invited address → 200 + session (account seized) | → 403; with the bound invitation id → 200 (legitimate invitee only) |
| TEC-017 | member denied the entry (403) but read its private signals (200): "Project Falcon Confidentiality Directive", "Meridian Dynamics Acquisition Details" | → 404 |
| TEC-018 | member → 200 on spend endpoints (instance-wide usage_events) | → 403 on both |
| TEC-004 | member → 200 on /admin/graph/stats | → 403 |
| TEC-003 | diagnose → 200 returning a private board memo verbatim | org_admin (not a member) → 404 |
| TEC-005 | not isolable on the shared instance (no stuck-signal precondition) | org_admin dry-run → 200 count:0 with a stuck signal present |
| TEC-025 | legs open end to end from an anonymous start | severed at three points (403 / 403 / 404) |
Two honest limits on the pre-remediation side. TEC-003 could not be isolated as an escalation live, because the only administrator available is a super-admin who reads the private entry directly regardless; the remediation is nonetheless shown cleanly with an org-admin returning 404. TEC-005's disclosure needs a stuck signal in a foreign workspace, which we did not seed into a shared instance; its fix is confirmed positively on the fresh stack. Neither limit affects the remediation verdict.
The product partitions an organization's knowledge into workspaces and enforces per-workspace membership; private workspaces keep board, HR, or deal material away from other members. Under single-org, a workspace is the security boundary that matters, and a member or admin reading across it is a real breach of the product's promise — even though no external attacker can reach it without an account. Robin's metric assigns such findings Attack Origin "Specific" (×0.2), which caps them at 4.4 and lands them at Informational. We rate on impact:
usage_events — entry, wiki, and signal identifiers plus user ids across every workspace — the chain's key-harvest source.We concur with Robin on the remaining insider findings and did not raise them; the critique is that the model buries the significant cross-workspace reads, not that every authenticated-origin item deserves a higher band. Nothing is raised to Critical: single-org removes the anonymous path that would make these arbitrary-origin. TEC-001 remains the single High on its own merits.
A fair counter-view: under a strict external-attacker threat model, insider findings are correctly low and Robin's bands are defensible. We give it weight, but the product is sold on workspace confidentiality, so we rate the cross-workspace reads on that promise and state the trade-off rather than hide it.
All 27 findings are closed at 94610791. Three carry residuals that Robin disclosed and we confirmed — non-blocking follow-ups:
emitAuditEvent swallows insert errors, so an audit write can fail silently.The two items open at Robin's first remediation pass — a 500 regression on aggregate spend (TEC-018) and a backlinks name leak (TEC-012) — are both fixed at 94610791, which we confirmed.
Every finding, with Robin's metric score, Tecmie severity, verification method, and status. ↑ marks a Tecmie raise above the metric.
| ID | Title | Assessed | Tecmie | Verified | Status |
|---|---|---|---|---|---|
| TEC-001 | Anonymous pre-registration of an invited email seizes the account | High 7.6 | High | reproduced | Fixed |
| TEC-003 | Diagnose route returns any entry + signals, no workspace scope | Low 2.1 | Medium ↑ | reproduced | Fixed |
| TEC-018 | Spend endpoints return instance-wide usage_events to any member | Info 1.3 | Medium ↑ | reproduced | Fixed |
| TEC-017 | Entry-signals route lists another workspace's signals, no scope | Info 1.3 | Medium ↑ | reproduced | Fixed |
| TEC-025 | Chain: anonymous seizure → cross-workspace signals + usage | Med 4.8 | Medium | reproduced | Resolved |
| TEC-015 | Client IP taken from left-most X-Forwarded-For, forgeable | Low 3.2 | Low | source | Fixed |
| TEC-004 | Graph-stats exposes instance-wide aggregates to any user | Info 0.7 | Low ↑ | reproduced | Fixed |
| TEC-005 | Retry-stuck enumerates PENDING signals across workspaces | Info 0.4 | Low ↑ | reproduced | Fixed |
| TEC-023 | Chain: org admin enumerates then reads private-workspace content | Low 2.1 | Low | source | Resolved |
| TEC-026 | Chain: anonymous org-admin invite seizure → any private content | Low 3.4 | Low | source | Resolved |
| TEC-006 | MCP write authority on a 4-char passcode, no rate limit, oracle | Info 0.9 | Info | source | Fixed |
| TEC-012 | Signal-relationship backfill links signals across workspaces | Info 1.1 | Info | source | Fixed |
| TEC-027 | Chain: anonymous seizure → MCP write as member, unattributed | Info 1.9 | Info | source | Resolved |
| TEC-022 | Chain: member harvests keys → enumerates signals across workspaces | Info 1.3 | Info | source | Resolved |
| TEC-008 | MCP set_auto_accept_persons behind a weaker gate than HTTP | Info 0.8 | Info | source | Fixed |
| TEC-007 | MCP confused deputy: authorized vs attributed identity split | Info 0.4 | Info | source | Fixed |
| TEC-020 | Unescaped organization name injects HTML into invite/reset emails | Info 0.7 | Info | source | Fixed |
| TEC-024 | Chain: org admin sends attacker-authored mail from verified sender | Info 0.7 | Info | source | Resolved |
| TEC-019 | Native better-auth org endpoints bypass app controls and audit | Info 0.7 | Info | source | Fixed (residual) |
| TEC-009 | MCP write-tool invocations emit actorless audit rows | Info 0.5 | Info | source | Fixed |
| TEC-010 | Classifier model-emitted domainId written cross-workspace | Info 0.5 | Info | source | Fixed |
| TEC-014 | Bulk export and self-service erasure write no audit record | Info 0.5 | Info | source | Fixed (residual) |
| TEC-013 | Capture-upload gate authorizes against a caller-asserted org label | Info 0.4 | Info | source | Fixed |
| TEC-002 | Member/invitation passcode written to application logs in cleartext | Info 0.3 | Info | source | Fixed |
| TEC-011 | Handlebars allowlist bypassed for structure fields at regen | Info 0.2 | Info | source | Fixed (residual) |
| TEC-021 | Chain: application-log reader gains MCP write authority as a member | Info 0.7 | Info | source | Resolved |
| TEC-016 | Branch-protection rulesets require a check no workflow emits | Info 0.1 | Info | source | Fixed |
e0326609) for the vulnerable side, asserted byte-identical to public 90c033b0 on finding-bearing files. We verified the finding-bearing excerpts against 90c033b0 directly; we could not verify byte-identity of the full snapshot, which is not on the public remote.Tecmie independent review. Verdicts reflect Tecmie's own source review at the two commits and live reproduction on 2026-09-08–09. Reproduction transcripts and the runbook that produced them are held with the reproduction package. This document does not cover runtime configuration, production infrastructure, or organisational processes except where evidenced in the repository.