Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
@cursor review |
|
@greptile review |
PR SummaryHigh Risk Overview Updates token/credential resolution to handle Extends the UI to let admins add/delete service accounts from Integrations (paste/upload JSON, validation, encrypted storage) and updates Google blocks to show an Impersonated Account field only when a service account credential is selected; adds docs for setup and required scopes. Written by Cursor Bugbot for commit 54683d7. This will update automatically on new commits. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for all 3 issues found in the latest run.
- ✅ Fixed: Impersonation field shown for non-service-account credentials
- The impersonation input now renders only when the selected credential is a service account by gating on
isServiceAccountinstead of provider-level support.
- The impersonation input now renders only when the selected credential is a service account by gating on
- ✅ Fixed: Return type mismatch:
undefinedinstead offalsehasExternalApiCredentialsnow coalesces the optional chaining result with?? falseso it always returns a boolean.
- ✅ Fixed: Serializer orphan logic is broader than intended
- The orphan serialization path was narrowed to only include the known
impersonateUserEmailkey instead of all orphan sub-blocks with values.
- The orphan serialization path was narrowed to only include the known
Or push these changes by commenting:
@cursor push 035b79165e
Preview (035b79165e)
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx
--- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/credential-selector/credential-selector.tsx
@@ -10,7 +10,6 @@
import {
getCanonicalScopesForProvider,
getProviderIdFromServiceId,
- getServiceAccountProviderForProviderId,
OAUTH_PROVIDERS,
type OAuthProvider,
parseProvider,
@@ -122,11 +121,6 @@
[selectedCredential]
)
- const supportsServiceAccount = useMemo(
- () => !!getServiceAccountProviderForProviderId(effectiveProviderId),
- [effectiveProviderId]
- )
-
const selectedCredentialSet = useMemo(
() => credentialSets.find((cs) => cs.id === selectedCredentialSetId),
[credentialSets, selectedCredentialSetId]
@@ -377,7 +371,7 @@
className={overlayContent ? 'pl-7' : ''}
/>
- {supportsServiceAccount && !isPreview && (
+ {isServiceAccount && !isPreview && (
<div className='mt-2.5 flex flex-col gap-2.5'>
<div className='flex items-center gap-1.5 pl-0.5'>
<Label>
diff --git a/apps/sim/lib/auth/hybrid.ts b/apps/sim/lib/auth/hybrid.ts
--- a/apps/sim/lib/auth/hybrid.ts
+++ b/apps/sim/lib/auth/hybrid.ts
@@ -25,7 +25,7 @@
export function hasExternalApiCredentials(headers: Headers): boolean {
if (headers.has(API_KEY_HEADER)) return true
const auth = headers.get('authorization')
- return auth?.startsWith(BEARER_PREFIX)
+ return auth?.startsWith(BEARER_PREFIX) ?? false
}
export interface AuthResult {
diff --git a/apps/sim/serializer/index.ts b/apps/sim/serializer/index.ts
--- a/apps/sim/serializer/index.ts
+++ b/apps/sim/serializer/index.ts
@@ -347,14 +347,17 @@
)
)
- const isOrphanWithValue =
- matchingConfigs.length === 0 && subBlock.value != null && subBlock.value !== ''
+ const isImpersonateUserEmailOrphanWithValue =
+ id === 'impersonateUserEmail' &&
+ matchingConfigs.length === 0 &&
+ subBlock.value != null &&
+ subBlock.value !== ''
if (
(matchingConfigs.length > 0 && shouldInclude) ||
hasStarterInputFormatValues ||
isLegacyAgentField ||
- isOrphanWithValue
+ isImpersonateUserEmailOrphanWithValue
) {
params[id] = subBlock.value
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
...omponents/editor/components/sub-block/components/credential-selector/credential-selector.tsx
Outdated
Show resolved
Hide resolved
Greptile SummaryThis PR adds Google service account (domain-wide delegation) as a first-class credential type in Sim, enabling automated workflows to access Gmail, Drive, Sheets, Calendar, and other Google Workspace APIs without per-user OAuth consent flows. Key changes:
Confidence Score: 5/5Safe to merge — all remaining findings are P2 (non-blocking improvements). The core security properties are solid: service account keys are encrypted at rest, the JWT is signed server-side with the stored private key, scopes are correctly filtered, and authorization checks gate every token-exchange path. DB schema changes are additive with proper constraints. All 13 Google blocks consistently apply the service account subblocks. The only issues found are (1) a swallowed apps/sim/app/api/auth/oauth/token/route.ts — error message from ServiceAccountTokenError is swallowed; apps/sim/app/api/auth/oauth/utils.ts — no token caching. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as Workflow UI
participant ToolExec as tools/index.ts
participant TokenAPI as /api/auth/oauth/token
participant UtilsFn as getServiceAccountToken
participant DB as Database
participant GoogleToken as Google Token Endpoint
UI->>ToolExec: execute tool (credential=SA, impersonateUserEmail=alice@co)
ToolExec->>ToolExec: build tokenPayload (scopes, impersonateEmail)
ToolExec->>TokenAPI: POST /api/auth/oauth/token
TokenAPI->>DB: resolveOAuthAccountId(credentialId)
DB-->>TokenAPI: {credentialType: 'service_account', credentialId}
TokenAPI->>TokenAPI: authorizeCredentialUse()
TokenAPI->>UtilsFn: getServiceAccountToken(credentialId, scopes, impersonateEmail)
UtilsFn->>DB: SELECT encrypted_service_account_key
DB-->>UtilsFn: encrypted key
UtilsFn->>UtilsFn: decryptSecret → JSON.parse → filter scopes
UtilsFn->>UtilsFn: createSign(RS256) → JWT assertion
UtilsFn->>GoogleToken: POST grant_type=jwt-bearer
GoogleToken-->>UtilsFn: {access_token}
UtilsFn-->>TokenAPI: accessToken
TokenAPI-->>ToolExec: {accessToken}
ToolExec->>ToolExec: call Google API with accessToken
Reviews (4): Last reviewed commit: "Fix build error" | Re-trigger Greptile |
apps/sim/app/workspace/[workspaceId]/settings/components/integrations/integrations-manager.tsx
Show resolved
Hide resolved
|
@BugBot review |
|
@greptile review |
|
@BugBot review |
|
@greptile review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


Summary
Add google service support as a integration. Allows users with admin credentials to assume roles on behalf of their google workspace users.
Created new credential type
service_account.Added documentation to sim docs.
Type of Change
Testing
Checklist
Screenshots/Videos