The imaging proxy passes MediaService's download and sandbox headers through
MediaService now serves any attachment outside its safe raster/audio/video list (SVG, HTML, PDF…) with Content-Disposition: attachment, X-Content-Type-Options: ...
Require a valid *** session on the unauthenticated pipeline endpoints
POST /convert-vector and WS /ws/pipeline took no auth at all — 4820f44 capped upload size and conversion concurrency but left the actual hole open pending a dec...
Break a circular bean dependency the STOMP live-session guard introduced
d47b471's SessionAccessGuard field on WebSocketConfig crash-looped every pod: Spring must fully construct WebSocketConfig (a **************** every @Autowired f...
Only an organization's owner may change who pays for mailboxes or extensions
**************** and **************** had no authorization check at all — any member of the organization, not only its owner, could move the whole organization'...
Guard STOMP SUBSCRIBE to a session's live messages and WebRTC signaling
/topic/chat/session/{guid} and /topic/webrtc/session/{guid} were not guarded at all: any authenticated socket could SUBSCRIBE to another session's live chat mes...
Drop the process-wide TLS verification bypass
NODE_TLS_REJECT_UNAUTHORIZED: "0" in k8s/configmap.yaml made every server-side outbound TLS call in this process — to any host, for any purpose, for as long as ...
Stop logging session tokens, cookies and message content
A grep for the shape of two known offenders (chat message text and chat-list previews going to console.log) turned up a much wider pattern across the session/au...
Reject unauthenticated uploads before the body is spooled
The chat attachment upload, the support bug-report screenshot upload, the meet background upload and the two ConversionService image-resize proxies all called b...
Forward subjectMemberId and role so TimecardService can verify punch ownership
**************** resolved the caller's role against a CLIENT-SUPPLIED subjectMemberId (resolveRole -> EMPLOYEE whenever actor==subject) but never forwarded that...
Chat attachment uploads authenticate before the body is spooled
POST /sessions/{guid}/attachments bound its parts as a @RequestParam MultipartFile[] method parameter. Spring resolves method parameters before a controller met...
DocsService is no longer published directly at docs-api.kamocrm.com
The docs-api-ingress IngressRoute sent the internet straight to DocsService, around the api gateway (and its identity-header stripping). Nothing used the host: ...
ConversionService is no longer published to the internet
The conversion-api.kamocrm.com IngressRoute sent anyone on the internet to this service, where several endpoints (/image/resize-bg, /favicon/generate, /convert-...
Strip client-supplied identity headers at the media.* edge
media-route (HostRegexp ^media[.].+$) carried only media-websocket-upgrade, so a caller hitting media.<domain> directly could set X-Org-Id, X-Member-Id, X-Publi...
Presence bulk reads and the stale-presence sweep stop using Redis KEYS
getBulkPresence/getBulkLastSeen ran KEYS PRESENCE:*/PRESENCE_LAST_SEEN:* on every call - hit on every presence-socket mount and tab focus - and the 30s sweep ra...
Auth on the endpoints that can take it now, ffmpeg/Batik hardening on the rest
ResourceServerConfig permits every request (this service is reachable anonymously at conversion-api.kamocrm.com), and none of ImageOpsController's or Conversion...
Give the gateway a memory request and limit
The deployment had no resources: block at all. No request, so the scheduler could not reason about this pod's footprint; no limit, so nothing capped the JVM's -...
Forward commission Stripe Connect webhooks, which reached nothing at all
CommissionService registers **************** directly with Stripe (OrgStripeSetupService), but no /api/commissions/** forward existed anywhere in this gateway -...
Carve out VOIPService's internal SMS-template API, and never forward a client's own X-Internal-Auth
Two related gaps in the same trust boundary. /api/voip/sms/templates/** was forwarded wholesale by the /api/voip/** wildcard. VOIPService's InternalAuthFilter ...
Stop logging STOMP frame headers/payloads and /ws request headers
Two leftover debug-logging spots on the WebSocket path: - WebSocketConfig's inbound channel interceptor logged every STOMP frame at INFO, including accessor....
Derive X-Real-IP from the right-most hop, not the client's own
forward() set the outgoing X-Real-IP to X-Forwarded-For.split(",")[0] -- the LEFT-most hop, which is the one part of that header a client controls outright: a r...
Bound upstream calls with a connect and a read timeout
Both RestTemplate beans were built from a bare JdkClientHttpRequestFactory with no timeout at all. One upstream that accepts the connection and then never answe...
Stop logging session tokens, OTKs and auth headers on every request
forward() printed the entire copied-header map on every single call -- System.out.println("APIService: copied headers: " + outHeaders) -- which serializes X-***...
Internal-auth secret comparisons are constant-time and fail closed
TranscriptionController, RecordingIngestController and RecordingProcessController all compared X-Internal-Auth with String.equals (a timing oracle on a shared s...
Imaging proxy forces a download for anything that isn't a safe raster or a stream
GET/HEAD **************** always answered with the client-declared Content-Type from upload, no Content-Disposition, no X-Content-Type-Options and no CSP. ChatA...
The meet-provider OAuth result page can no longer break out of its own script tag
MeetProviderController's GET /oauth/callback is sessionless and reflects the provider's error_description into an inline <script> block. The old jsString() only...
The learner media route's HEAD answers instead of hanging
useAttachmentSource probes with a HEAD after a media element fails, to tell a file that is gone from a session that lapsed. The route awaited response.body.canc...
The internal envelope API fails closed and compares its secret in constant time
**************** used String.equals against X-Internal-Auth (a timing side channel on a shared secret) and, when esig.internal-auth-secret was unset, logged a w...
The staff envelope API now requires a document right, and HR envelopes need an HR one
EsignEnvelopeController's **************** checked org membership only — no document right, no clearance, nothing context-specific. Any authenticated staff memb...
Thread orgId through every template handler, EDIT_DOCUMENTS on writes
ESignTemplateService's signer/design handlers (getSigners, upsertSigners, reorderSigners, deleteSigner, saveDesign, getLatestDesign, listDesignVersions, getDesi...
RegisterExistingDocument checks the dat's org, and a template can be found by imgId within one
Two org-scoping gaps the esig/imaging audit found, both in shared entry points other services build on: - **************** (the conversion service's dedup-skip...
The Hold'em invite is a kind the site knows: label, icon, filter and mute
MediaService has raised HOLDEM_INVITE notifications since Hold'em shipped, but the kind was missing here: the toast's eyebrow printed the raw translation key, t...
The member who caused a notification opens their card from it
"Dana Reyes dealt you in", "Weekly sync · Dana Reyes", an unread-chat card whose body is the sender: EmailService (29cb21e) now sends actorMemberId (as text) an...
Gate adding people and moving a position as the server does, and list every storage area
- The Add and Bulk Add buttons on /account, and the four create pages, need MANAGE_MEMBERS (MemberAdministrationGate), which SecurityService now enforces. Som...
Five reasons the golden image had never actually been built
The build had never been run. Running it found one bug per attempt, and the first three would each have produced a plausible-looking image with something missin...
StatusReasonAdviceTest's alias case also needs MANAGE_EMAIL_ACCOUNTS
Same shape as the AliasResponseMemberIsTextTest fix: this class's one shared session lacked the right, so createAlias's new gate answered 403 "MANAGE_EMAIL_ACCO...
Count an org's unconfirmed talent-alert rows for the anonymous form's cap
DocsService's public talent-alert subscribe endpoint sends a confirmation email on every accepted call, with no limit on how many not-yet-confirmed rows one org...
UpdateDocType now requires the doc type to belong to the document's own org
ImageService.updateDocType loaded the target ImgDocType by UUID alone; requireEditableAndOwned proves the caller may edit the Img, but says nothing about whose ...
Org-scoped counterparts for the thumbnail-backfill candidate queries
DocsService's /backfill-thumbnails admin endpoint selected candidates from **************** (platform-wide, no organization predicate) or, as a last resort, a r...
Clearing the image version has to send "", not null
**************** merges rather than replaces, and for the image version a null means "leave whatever is there alone" — only a blank string clears it: if (i...
Right checks, SSRF/credential guards and cross-org fixes across VOIP
Findings 2-6 from the phone-system audit, fixed together because several share files. 2. HIGH — VoipInstanceController had no right check on any mutating endpo...
Growth Hub files are reported on their own line
This pins the GROWTH_HUB domain kamo-shared-library gained today. Before it, no domain claimed the Growth Hub's two associations, and the imaging pass dropped t...
The Notes app is "Notes & Checklists"
The Notes app holds checklists as well since 2026-09-23 (steps ticked off as they are done, a step that waits until the steps before it are finished, a checklis...
Adding people and member security need their rights
POST /members/create, /create-team-member and /bulk-create, and GET /members/lookup-user, now require MANAGE_MEMBERS or an open god window. They checked only fo...
The Hold'em invite and the meeting reminder say who they are from
MemberNotificationClient.raise gains an overload carrying actorMemberId/actorName (the id sent as text; the old signature is unchanged and sends neither). Holde...
Who caused a notification travels with it, so the bell can draw them as a member
- NotificationRequest gains actorMemberId/actorName; the old constructor stays for every producer that predates them. - raise() keeps the pair only when both ...
A notification can say whose doing it is
MemberNotification gains ACTOR_MEMBER_ID (INT8) and ACTOR_NAME (255): the member who caused it - who dealt you in, whose meeting is starting, who wrote to you -...
The Notes plan feature is "Notes & Checklists"
The Notes app holds checklists as well since 2026-09-23 and is called "Notes & Checklists" everywhere it is named. The pricing page's comparison chart takes its...
The NOTES mirrors say "Notes & Checklists", as Java now does
ServiceType.NOTES is renamed in kamo-shared-library, in copy only: the display name is "Notes & Checklists" and the description now covers the checklists. Both ...
The platform tab, and three links that showed their own keys
Two bugs, both reported from the running site. THE SETTINGS LINKS SHOWED KEY PATHS The three Hosted Computer sub-links carried key: 'computers' | 'capacity' | ...
Require MANAGE_DOCS_SETTINGS on every doc-settings mutation, not just some
The settings page always sent a member without MANAGE_DOCS_SETTINGS away, but ten mutation endpoints in ImagingSettingsController never asked themselves: canMan...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
