Skip to content

v0.6.80: security hardening, nextjs minor version bump, cloudwatch tools, seo fixes - #4608

Merged
waleedlatif1 merged 12 commits into
mainfrom
staging
May 15, 2026
Merged

v0.6.80: security hardening, nextjs minor version bump, cloudwatch tools, seo fixes#4608
waleedlatif1 merged 12 commits into
mainfrom
staging

Conversation

@waleedlatif1

@waleedlatif1waleedlatif1 commented May 15, 2026

Copy link
Copy Markdown
Collaborator

TheodoreSpeaksand others added 9 commits May 14, 2026 12:54
… tx (#4593)
* v0.6.29: login improvements, posthog telemetry (#4026)
* feat(posthog): Add tracking on mothership abort (#4023)
Co-authored-by: Theodore Li <theo@sim.ai>
* fix(login): fix captcha headers for manual login (#4025)
* fix(signup): fix turnstile key loading
* fix(login): fix captcha header passing
* Catch user already exists, remove login form captcha
* improvement(db): add session statement/lock timeouts; simplify KB doc tx
* fix(knowledge): close soft-delete TOCTOU on KB document insert
Fix the race the bots flagged: KB delete is soft (`deletedAt = now`) so
the FK can't catch a concurrent KB delete between the existence check
and the document insert.
- Add `insertDocumentsIfKbAlive` helper that gates the insert on
`EXISTS(SELECT 1 FROM knowledge_base WHERE id=$kb AND deleted_at IS NULL)`
in the same statement via INSERT...SELECT...WHERE EXISTS. Atomic at the
MVCC snapshot — no transaction, no row lock.
- Use jsonb_to_recordset to declare column types once, avoiding per-param
casts for nullable columns.
- Wire into both `createDocumentRecords` (bulk) and `createSingleDocument`.
- Keep the upfront KB existence check as a fast-path early-out for the
common case; the atomic insert is the race guard.
---------
Co-authored-by: Waleed <walif6@gmail.com>
Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
* fix(seo): use canonical SITE_URL for robots and sitemap
* fix(seo): drop /templates from sitemap and guard robots/sitemap in seo test
* improvement(scheduler): drain in chunks instead of a single capped claim
Replaces the fixed MAX_CRON_CLAIMS (200) with a chunked drain loop:
claim WORKFLOW_CHUNK_SIZE + JOB_CHUNK_SIZE per iteration, process via
Promise.allSettled, repeat until both claim queries return empty or
MAX_TICK_DURATION_MS elapses. Throughput is no longer bounded by a
static per-tick ceiling; it scales until DB or trigger.dev is the
limit. Per-iteration chunk size still bounds row-lock set and fan-out
concurrency.
Extracts processScheduleItem and processJobItem so the loop body stays
readable. Existing claim semantics (FOR UPDATE SKIP LOCKED, lastQueuedAt
as the claim signal, staleness reclaim) are unchanged.
* improvement(scheduler): skip claim once a queue is exhausted and drop workflowUtils non-null assertion
Addresses Greptile review on PR #4578:
- track per-queue exhaustion when a claim returns fewer than CHUNK_SIZE
rows; subsequent iterations skip the claim query for that queue. Saves
one DB round-trip per iteration once one queue drains while the other
is still working.
- narrow workflowUtils to a local const inside the loop body so the
schedule processing branch only runs when the import has completed.
Removes the misleading non-null assertion.
…ck get_message ts (#4600)
* fix(integrations): gdrive trashed search, slack blocks-with-file, slack get_message ts
- Google Drive search/list: skip default `trashed = false` when user query
already specifies a `trashed = ...` predicate, so trashed-file searches work.
- Slack send-message with files: forward `blocks` through to
`files.completeUploadExternal` so Block Kit renders when files are attached.
- Slack get_message: switch from `conversations.history` (oldest lower-bound
returned the next message after) to `conversations.replies` with `ts=`
for exact-match lookup, plus a defensive ts-equality guard and clearer error.
* fix(google_drive): revert list.ts trashed guard — query is plain text, not gdrive syntax
* fix(slack): omit initial_comment when blocks present so Block Kit actually renders on file uploads
…ounds (#4601)
* fix(security): harden file access controls, webhook auth, and input bounds
* fix(security): extend file access checks to remaining tool routes
* fix(logs): address PR review comments on time filter
* fix(logs): set end-time milliseconds to 999 for datetime filter strings
* fix(files): return 404 instead of 500 on file access denial in utility paths
* remove tooltip from resource tabs
* chore(deps): bump next to 16.2.5 for CVE-2026-44578 SSRF fix
* chore(deps): bump next to 16.2.6 for full May 2026 security release coverage
…rage quota coverage (#4605)
* fix(security): supabase rpc path validation, ssh stream byte cap, storage quota coverage
* fix(security): scope execution log writes to owning workflow; add env-var workspace membership guard
Closes two cross-tenant vulnerabilities:
1. Workflow log cross-tenant write (route.ts + logging-session.ts):
- Route: SELECT before creating LoggingSession to verify executionId belongs
to the claimed workflowId; reject with 404 if owned by a different workflow.
- LoggingSession: add workflow_id to all UPDATE/SELECT WHERE clauses
(raw SQL marker queries, flushAccumulatedCost, loadExistingCost) so
writes are a no-op if executionId was somehow injected.
2. Env-var workspace membership guard (environment/utils.ts):
- getPersonalAndWorkspaceEnv now calls checkWorkspaceAccess when workspaceId
is provided; throws if the userId is not a member, preventing any future
caller from reading another workspace's decrypted secrets without
explicit membership verification at the call site.
* fix(security): remove fileSize > 0 quota bypass gate; exempt logs context from quota
* chore: remove extraneous inline comments
* fix(security): scope markExecutionAsFailed UPDATE by workflowId; thread workflowId through HITL callers
* fix(security): add personal credential ownership check in sharepoint site route; scope markExecutionAsFailed by workflowId
* fix: remove logs from user-accessible upload contexts; restore distinct biome .next glob
* fix(sharepoint): migrate site route to authorizeCredentialUse
The previous fix only checked userId equality for personal credentials and
workspace membership (via getUserEntityPermissions) for workspace credentials.
authorizeCredentialUse additionally enforces credentialMember access for
workspace-scoped credentials, matching the standard pattern used by all
other tool selector routes.
* fix(logging): make workflowId required in markExecutionAsFailed
Making workflowId optional left a footgun — future callers could silently
omit it and the WHERE clause would degrade to executionId-only, losing the
cross-tenant scoping guarantee. All callers already supply workflowId, so
making it required (with string | undefined for the middle params to keep
call sites unchanged) closes the gap without touching any caller.
* test(security): add tests for cross-tenant log guard, quota bypass fix, and workflowId scoping
- log/route.test.ts: verifies cross-tenant executionId guard returns 404
when the execution belongs to a different workflow, and passes for same
workflow or fresh executions
- multipart/route.test.ts: verifies fileSize:0 no longer bypasses quota
check and that the logs context is rejected at the endpoint level
- logging-session.test.ts: verifies markExecutionAsFailed scopes by both
executionId and workflowId, and that the instance method forwards workflowId
* fix(lint): move IconComponent outside ToolInput to fix noNestedComponentDefinitions
* fix(logging): scope completeWithCancellation and completeWithPause reads by workflowId
Both SELECT queries that check execution status before writing a
terminal result were only filtering on executionId. Adds workflowId
to the WHERE clause so all seven reads and writes in LoggingSession
consistently scope by (workflowId, executionId).
@vercel

vercelBot commented May 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
docsSkippedSkippedMay 15, 2026 2:49am

Request Review

@cursor

cursorBot commented May 15, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Touches security-sensitive authorization and file-download paths across many tool endpoints and modifies scheduled execution draining logic, so regressions could impact data isolation or background job throughput. Also adds new AWS CloudWatch operations that exercise external credentials/permissions.

Overview
Security hardening: Adds a shared assertToolFileAccess/FileAccessDeniedError flow and applies it across many tool routes before downloading user files; tightens internal-auth checks to require userId; adds workflow-scoped guardrails for /api/workflows/[id]/log to prevent cross-tenant executionId reuse; and switches SharePoint site lookup to authorizeCredentialUse. Also adds workspace-access validation when fetching environment variables.

Limits & quota: Enforces storage quota checks for multipart upload initiation across contexts (with exemptions) and disallows logs uploads via the multipart endpoint; bounds SSH read maxSize and adds a streaming byte cap.

New capability: Introduces CloudWatch mute_alarm/unmute_alarm tool endpoints + contracts, and wires them into the CloudWatch block UI/param parsing.

Operational/UI fixes: Refactors schedule execution to claim due schedules/jobs in chunks with a per-tick time budget; fixes robots/sitemap to use SITE_URL (and adds /contact), adds tests to prevent regressions, and updates the date-range picker to support optional time selection and avoid reopen re-render loops; minor logs/resource tab UI tweaks and a Next.js patch bump in apps/docs.

Reviewed by Cursor Bugbot for commit 922de38. Configure here.

Comment threadapps/sim/app/api/tools/slack/utils.ts
@greptile-apps

greptile-appsBot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This release bundles a broad security hardening pass, a new CloudWatch mute/unmute feature, scheduler throughput improvements, and a date-picker re-render fix across 87 files.

  • Security: assertToolFileAccess is now enforced before every file download across ~20 tool routes; workflowId added to all LoggingSession WHERE clauses to prevent cross-workflow ID spoofing; WhatsApp verification token comparison switched to safeCompare; debug logs that leaked HMAC secret lengths removed; Supabase RPC function names now validated and URL-encoded; SSH streaming reads are hard-capped; getPersonalAndWorkspaceEnv gates on workspace membership before fetching env rows.
  • CloudWatch: New mute_alarm / unmute_alarm operations backed by DisableAlarmActionsCommand / EnableAlarmActionsCommand; contracts validate region format and cap alarm list at 100 entries.
  • Scheduler: Replaced fixed-max single-batch claim with a chunked drain loop bounded by MAX_TICK_DURATION_MS (3 min), processing schedules in 100-item chunks until exhausted.

Confidence Score: 5/5

The changes are safe to merge — every security fix is narrowly scoped, all markExecutionAsFailed callers were updated for the new required workflowId parameter, and the scheduler refactor maintains the same claim-then-process contract.

The PR is a well-executed security pass. File-ownership checks are consistent across all updated routes, the WhatsApp timing fix is guarded correctly, the SQL raw-string replacement is accurate, and the logging-session WHERE-clause additions cover every query in the class. The CloudWatch feature follows existing tool patterns exactly. No functional regressions were identified.

No files require special attention.

Important Files Changed

FilenameOverview
apps/sim/app/api/files/authorization.tsTightened assertToolFileAccess signature to require non-optional userId: string, removed the now-redundant internal !userId guard, and added FileAccessDeniedError export class.
apps/sim/app/api/files/multipart/route.tsBroadened storage-quota enforcement to cover all non-exempt upload contexts (not just workspace), using the new QUOTA_EXEMPT_STORAGE_CONTEXTS set; removed logs from allowed contexts.
apps/sim/lib/logs/execution/logging-session.tsAdded workflowId to all WHERE clauses in cost flush, status reads, marker persistence, and markExecutionAsFailed to prevent cross-workflow ID confusion; updated static method signature to require workflowId.
apps/sim/app/api/workflows/[id]/log/route.tsAdded a pre-check that rejects logging if the provided executionId is already associated with a different workflow, preventing cross-workflow log pollution.
apps/sim/app/api/schedules/execute/route.tsRefactored from single-batch claim to a chunked drain loop bounded by MAX_TICK_DURATION_MS (3 min); extracted processScheduleItem and processJobItem as standalone functions for clarity.
apps/sim/lib/webhooks/providers/whatsapp.tsFixed timing-attack vulnerability: replaced direct === comparison with safeCompare for WhatsApp webhook verification token; verificationToken is guarded as truthy before the call.
apps/sim/tools/supabase/vector_search.tsAdded validateDatabaseIdentifier + encodeURIComponent to prevent RPC path traversal when constructing the Supabase REST URL for function names.
apps/sim/app/api/tools/ssh/read-file-content/route.tsAdded streaming byte counter to enforce maxBytes cap during SFTP read, destroying the stream early if the file exceeds the limit.
apps/sim/lib/workflows/executor/human-in-the-loop-manager.tsFixed SQL injection risk: replaced sql.raw(now.toISOString()) with a parameterized binding; also updated markExecutionAsFailed callers to pass workflowId.
apps/sim/components/emcn/components/date-picker/date-picker.tsxFixed infinite re-render on popover re-open via lazy useState initialization; added showTime prop for HH:mm selection.
apps/sim/tools/cloudwatch/mute_alarm.tsNew tool: mute CloudWatch alarm via DisableAlarmActionsCommand; follows existing CloudWatch tool patterns.
apps/sim/app/api/tools/cloudwatch/mute-alarm/route.tsNew route for CloudWatch mute alarm; authenticated, validated against awsCloudwatchMuteAlarmContract, properly destroys CloudWatch client in finally block.
apps/sim/lib/environment/utils.tsAdded checkWorkspaceAccess guard before fetching workspace environment variables, preventing unauthorized env reads across workspaces.
apps/sim/tools/google_drive/search.tsFixed trashed-file search: only prepend trashed = false when the user query does not already specify a trashed = predicate.
apps/sim/tools/slack/get_message.tsSwitched from conversations.history to conversations.replies for precise message lookup, and added a timestamp mismatch guard.

Reviews (3): Last reviewed commit: "fix(date-picker): eliminate infinite re-..." | Re-trigger Greptile

Comment threadapps/sim/app/api/tools/telegram/send-document/route.ts
Comment threadapps/sim/lib/uploads/shared/types.ts
Comment threadapps/sim/app/api/schedules/execute/route.ts
@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@greptile

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@cursor review

Comment threadapps/sim/components/emcn/components/date-picker/date-picker.tsx Outdated
Comment threadapps/sim/app/api/files/multipart/route.ts
…existing selection (#4609)
* docs(uploads): clarify QUOTA_EXEMPT_STORAGE_CONTEXTS logs entry in JSDoc
* fix(date-picker): eliminate infinite re-render on re-open with existing selection
The useEffect that syncs picker state on open had initialStart and
initialEnd — Date objects computed on every render — in its dependency
array. Because Object.is returns false for any two distinct Date
instances, the effect fired on every render when open=true, calling
setRangeStart/setRangeEnd and triggering another render, producing an
infinite loop that crashed the page.
Fix: compute start and end as local variables inside the effect and
use the stable string props (props.startDate, props.endDate) as deps
instead.
Also removes the redundant typeof fileSize === 'number' guard in the
multipart quota check — fileSize is z.number() (required) in the
contract so it can never be undefined at that point.
* refactor(date-picker): comprehensive cleanup and reliable crash fix
The previous fix still had derived Date objects in useEffect deps.
Object.is(new Date(), new Date()) === false, so any Date in deps causes
the effect to run every render, reproducing the infinite loop on
re-open with existing time selection.
Key changes:
- useEffect deps now use only stable primitives (startDate, endDate strings)
and compute Date values inside the effect — eliminating the loop
- Replace `rest as any` with a FlatDatePickerProps merged type for safe,
typed destructuring across the discriminated union
- Remove initialStart/initialEnd render-scope variables; compute inline or
inside effects to keep derivation local to each use site
- Callbacks use destructured props (onChange, onRangeChange, etc.) instead
of props.x references
- Remove verbose TSDoc on internal callbacks — names are self-documenting
- Preserve all existing JSX structure and CalendarMonth logic unchanged
@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@greptile

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@cursor review

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 922de38. Configure here.

…width (#4611)
* fix(gmail): send emails as multipart/alternative so they render full-width
* fix(gmail): decode &amp; last in htmlToPlainText to avoid double-decoding compound entities
* fix(gmail): encode body parts as base64 and decode numeric HTML entities
Comment threadapps/sim/tools/gmail/utils.ts Fixed
Comment threadapps/sim/tools/gmail/utils.ts Fixed
Comment threadapps/sim/tools/gmail/utils.ts Fixed
Comment threadapps/sim/tools/gmail/utils.ts Fixed
…4613)
* improvement(gmail): replace custom html-to-text regex with html-to-text library
Resolves 4 CodeQL alerts on htmlToPlainText (incomplete tag/entity handling,
unsafe regex backtracking). Delegates to the html-to-text npm package already
used by the outlook polling trigger and the mail/send route.
* improvement(gmail): match outlook selectors config, add nbsp/anchor tests
Aligns html-to-text options with apps/sim/lib/webhooks/polling/outlook.ts:
suppress anchor hrefs when identical to text, drop bare # anchors, skip
img/script/style content. Adds tests for nbsp preservation and anchor
behavior.
@waleedlatif1
waleedlatif1 merged commit 4efe999 into mainMay 15, 2026
30 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@waleedlatif1@TheodoreSpeaks@github-advanced-security