Security Review

backendApi development @ a6445ea09 · capExpertApp development @ d9293b779 · mobile checked · 19 Oct 2026

Verdict: critical. The review found server-side code execution, ways for users to reach other organisations' accounts and data, and internal endpoints that accept requests they should refuse.

12 of the worst findings are fixed (11 fully, 1 partly). The fixes are committed on a branch but not yet deployed, so all of them are still live in production. This public page leaves out file locations, endpoints and reproduction steps on purpose; the full report is kept off the web.

8 critical7 backend, 1 front end; 5 fixed in branch
17 high15 backend, 2 front end; 6 fixed, 1 partly
31 medium25 backend, 6 front end; 1 fixed, 1 partly
Mobile: 0mobileApp and mobileApi unaffected by the fixes

On this page

What happens next

  1. Review, merge and deploy the CAP-246 commits (one per repo, already on the branch). Before merging, check adding and editing users (as an admin and as a Primary user), 2FA login, opening chat, and a shipping-quote reply email.
  2. Rotate the token-signing secret after that deploy, so tokens issued before the fix stop working.
  3. Rotate or restrict the Google API key found in git history (B-M16).
  4. List the service accounts that run background jobs (web API, Cloud Scheduler, mobile API). Needed for B-C4.
  5. Lock the internal task endpoints in two deploys (B-C3): first make every caller send a signed token, including the mobile API, then enforce it.
  6. Design the replacement for signed file links (B-C7) around record ids, since several features legitimately open other accounts' files. Then work through the open highs.

backendApi: critical and high

IDSeverityAreaFindingStatus
B-C1CriticalCoPilotServer-side code execution from request inputFixed in branch
B-C2CriticalUser managementEditing a user can move it into, or take over, accounts in other organisationsFixed in branch
B-C3CriticalBackground tasksInternal task endpoints accept unauthenticated requestsNeeds input
B-C4CriticalBackground jobsThe job runner accepts tokens from any Google service accountNeeds input
B-C5CriticalLoginTwo-factor login and logout can be bypassedFixed in branch
B-C6CriticalShipping emailsA token sent in shipping emails works as a loginFixed in branch
B-C7CriticalFile storageSigned file links can be issued for other organisations' documentsOpen
B-H1HighContent adminServer-side code execution from admin-only request inputFixed in branch
B-H2HighEquipment planningSQL injection in an admin bulk updateOpen
B-H3HighUser managementUsers can be created in accounts the caller does not manageFixed in branch
B-H4HighNotificationsAn unauthenticated stream exposed every organisation's notificationsFixed in branch
B-H5HighLoginThe import service accepted half-finished 2FA loginsFixed in branch
B-H6HighLoginPassword change works without a session and without an attempt limitOpen
B-H7HighChatChat history readable outside your own roomsPartly fixed
B-H8HighCaptureRoom import into another organisation's projectOpen
B-H9HighDocument ManagerDocuments can point at other organisations' filesOpen
B-H10HighAssistantAssistant attachments can point at other organisations' filesOpen
B-H11HighAdmin rolesLimited admins can reset any user's passwordOpen
B-H12HighOnboardingRegistration links issued for other organisations' pending usersOpen
B-H13HighCoPilotA vendor can decline an RFP on another vendor's behalfOpen
B-H14HighCoPilotBids and prices readable across organisationsOpen
B-H15HighDashboardAny user can change dashboard layouts platform-wideOpen

backendApi: medium and low

IDAreaFindingStatus
B-M1Admin rolesLimited admins can act outside their assigned accountsOpen
B-M2NotificationsOther users' notifications can be read or changedOpen
B-M3Vendor offersA vendor can cancel another vendor's offerOpen
B-M4Denovo / CoPilotSome pre-order and bid details readable across organisationsOpen
B-M5AccountsPrimary-user contact details readable for any accountOpen
B-M6PermissionsFeature permissions open up when the cache is downOpen
B-M7SessionsSuspending a user or changing a password does not end sessionsOpen
B-M8LoginNo rate limits; login codes have no attempt limit; captcha is the client's choiceOpen
B-M9Account settingsThe 'require 2FA' setting is not enforcedOpen
B-M10PrintingThe print-signing service works without loginOpen
B-M11UploadsUpload links are not limited by account, size or typeOpen
B-M12PDF generationPDF rendering runs untrusted content without a sandboxOpen
B-M13Email ingestionInbound email fetches remote content and trusts attachments and sendersOpen
B-M14Assistant analyticsThe database-analysis guard can be bypassed (feature off by default)Open
B-M15TokensTokens are no longer written to logs; Denovo link expiry and the Dialogflow agent credential are still openPartly fixed
B-M16SecretsA Google API key remains in git history and must be rotated; the ignore files now block example env filesOpen
B-M17DependenciesVulnerable packages that the code actually reachesOpen
B-M18ExportsExport files briefly downloadable without loginOpen
B-M19SearchA long search can exhaust server CPUOpen
B-M20ImportsArchive uploads are not size-limitedOpen
B-M21StickersUnvalidated input forwarded to an external serviceOpen
B-M22Action feedsService dates can be changed on other organisations' equipmentOpen
B-M23Asset registryVerify works on other organisations' assetsOpen
B-M24Import logsImport logs readable for other accountsOpen
B-M25DocumentsThe document log accepts other accounts and file locationsOpen

13 low findings are hardening items: stricter origin matching, user-enumeration responses, webhook signature checks, guard structure, error logging, a public default admin inbox, and dead code that should be deleted. All open.

capExpertApp

IDSeverityAreaFindingStatus
F-C1CriticalShared rich textStored cross-site scripting in bids, listings, comments and logsFixed in branch
F-H1HighAccount settingsOrg-wide 'require 2FA' is only a banner (backend fix, B-M9)Open
F-H2HighAdmin screensCross-site scripting reaching platform-admin sessionsFixed in branch
F-M1MediumLoginOpen redirect after loginFixed in branch
F-M2MediumHardeningBrowser security policy allows inline scripts; tokens kept in local storageOpen
F-M3MediumChatSession token sent in a URLOpen
F-M4MediumLoginCaptcha requirement decided by the clientOpen
F-M5MediumSSOThe SSO callback can switch a signed-in user into another accountOpen
F-M6MediumDenovo external linksA non-expiring link token stays in the page URLOpen

9 low findings cover token handling in URLs and storage, logout clean-up, editor configuration, and dependency bumps. None of the front-end dependency advisories is reachable in the browser. All open.

Mobile

Scope and method