fix: P0 auth and tenant-scoping security fixes (GH-036, GH-042, GH-046, GH-049, GH-052, GH-075, GH-102, GH-272) - #3573
Merged
Merged
Conversation
Every SOA handler now overwrites dto.organizationId with the trusted @organizationId() session value before calling the service, closing the cross-tenant read/tamper/destroy gap in save-answer, auto-fill, create-document, ensure-setup, approve, decline, and submit-for-approval. Refs GH-36
automationId lookups are now verified against the task in the URL and the caller's organization via a shared verifyAutomationAccess helper, so an automationId from another org's task 404s on read, update, delete, runs, versions, and publish instead of leaking or mutating it. Refs GH-46
reclaimAccess no longer returns the access link/token in the response body and returns an identical generic message whether or not a grant exists, removing the unauthenticated token disclosure and the email-enumeration oracle; the link is only emailed to the requester. findPublishedTrustByRouteId no longer auto-creates a published Trust row or flips drafts to published: public endpoints only resolve rows that are already published and 404 otherwise, so an unauthenticated caller can no longer force-publish an organization's trust portal. Refs GH-42, GH-272
Every exported server action now resolves the caller's session and active organization and fails closed when unauthenticated. Actions that take orgId must match the session's active org; S3 keys must be prefixed with the active org; automationId-only actions verify ownership through the automation's task before proxying to the enterprise API. Refs GH-52
healAndSetAccessToken and createAccessToken now require a session with an active organization and only mint a Trigger.dev run-read token when the run id is recorded against that organization (onboarding job, knowledge base document, or remediation batch). Refs GH-102
The device-agent release pipeline runs branch-controlled build scripts with Apple and SSL.com code-signing secrets in scope, so push triggers are now limited to main and release (manual staging builds remain via workflow_dispatch), and the secret-bearing jobs are gated behind the staging/production GitHub environments. Refs GH-49, GH-75
|
|
dennisofficial
marked this pull request as ready for review
September 22, 2026 16:48
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 13 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
This was referenced Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Draft PR fixing eight P0 security findings tracked in Glass House. All changes are minimal, in-place fixes — no refactoring.
organizationIdfrom the request body. EverySOAControllerhandler now overwritesdto.organizationIdwith the session-derived@OrganizationId()value before calling the service (previously onlyget-setupandexportdid). Closes cross-tenant read/tamper/destroy of any org's ISO 27001 SoA, including the auto-fill SSE exfil path.POST /v1/trust-access/:org/reclaimreturned the live access link/token in the HTTP response and 404'd when no grant existed (email-enumeration oracle). It now returns an identical generic message either way and only emails the link to the requester.AutomationsServicekeyed lookups onautomationIdalone. A sharedverifyAutomationAccesshelper now confirms the automation belongs to the task in the URL and the caller's organization before any read/update/delete/run/version operation.device-agent-release.ymlfired on push to any branch and ran branch-controlled build scripts (bun installpostinstall,package:mac|win,electron-builder.config.js) with Apple + SSL.com code-signing secrets in scope. Push trigger is now limited tomain/release(manual staging builds remain viaworkflow_dispatch), and the secret-bearing jobs (build-macos,build-windows,upload-s3) are gated behind thestaging/productionGitHub environments.'use server'actions did no authn/authz and acceptedorgIdfrom the caller. All now resolve the session and fail closed when unauthenticated; caller-suppliedorgIdmust equal the session's active org; S3 keys must be prefixed with the active org;automationId-only actions verify ownership via the automation's task before proxying to the enterprise API.healAndSetAccessToken/createAccessTokenminted a Trigger.dev run-read token for any run id with no auth. Both now require a session with an active organization and only mint when the run id is recorded against that org (onboarding job, knowledge base document, or remediation batch).findPublishedTrustByRouteIdauto-created aTrustrow withstatus: 'published'(or flipped a draft to published) when called from unauthenticated endpoints. It now only resolves already-published rows and 404s otherwise; publishing remains exclusively behind the authenticated, permission-gated settings controller.Verification
apps/api:NODE_ENV=test bunx jest src/soa src/tasks/automations src/trust-portal— 228 tests pass, including new specs asserting the org-override per SoA handler, cross-tenant 404s for automations, the generic reclaim response, and no-create/no-publish behavior for unpublished trust rows. Two controller suites fail at module load with a pre-existingDATABASE_URL/TLS guard error — reproduced identically atorigin/main, unrelated to this diff.apps/app:bunx vitest run src/actions/trigger/heal-access-token.test.ts— 10/10 pass (new spec: no session, no active org, unowned run id, per-model ownership, cross-org rejection).tsc --noEmitforapps/apiandapps/appshows zero errors in any touched file; remaining errors are pre-existing in unrelated spec files.unbound-methoderror class on these files; lint is not CI-gated).device-agent-release.ymlvalidated as parseable YAML.Product decisions to be aware of
environment:gates only bite if thestagingandproductionenvironments have protection rules (required reviewers / restricted branches) configured in repo settings. Worth confirming after merge.workflow_dispatchfor those.getAutomationRunStatusresidual gap (feat: editor switch to liveblocks #52) — enterprise/trigger run ids have no org mapping in this app's database, so that action can only require an authenticated session, not verify run ownership. Closing it fully needs the enterprise service to scope runs by org.Summary by cubic
Fixes eight P0 security issues in auth and tenant-scoping across the API and web app.
Security fixes
organizationIdfrom the request body with the session-derived org.orgIdand S3 keys, and verify automation ownership.Operational notes
main/release; manual staging builds are viaworkflow_dispatch, and secret-bearing jobs are gated behindstaging/productionenvironments — confirm those environments have protection rules configured.getAutomationRunStatusonly enforces an authenticated session since run ids can't be mapped to orgs locally.Written for commit 849a320. Summary will update on new commits.