Repository navigation
v0.9.53: saved credentials with keyless AWS and Databricks OIDC, read-only API keys, workspace members endpoint, trigger health and pinned versions, proxy support, search source permissions - #9871
Conversation
…quoting, retire the legacy simstudio CLI (#9830) * fix(cli): bind sim-setup's containers to loopback, fix reset and env quoting, retire the legacy simstudio CLI * fix(setup): rebind containers an earlier sim-setup published on every interface, and stop a dev reset that failed to tear down * fix(setup): warn about containers an earlier sim-setup exposed instead of replacing them
…ent asks for more chunks (#9823) * improvement(search): return a longer live read window when an MCP client asks for more chunks * improvement(search): share one character budget across the documents of a scaled read call * docs(search): say where the scaled read budget stops bounding a call's size * improvement(search): size a scaled read window by its JSON-encoded length
…ns, with keyless AWS/Databricks OIDC (#9763) * feat(credentials): saved AWS and Databricks credentials with keyless OIDC Adds an optional saved credential to every AWS block and the Databricks block, alongside the existing inline key fields, plus Sim's own workload-identity (OIDC) issuer so a credential can assume a customer's AWS role or federate into a Databricks service principal without any stored secret. Existing workflows are unchanged: the inline fields stay, show, and validate exactly as before until someone selects a saved credential. - Issuer at /oidc/workload (discovery + JWKS), signing key from WORKLOAD_IDENTITY_SIGNING_KEY; 404 and keyless option off when unset - Credential-scoped subjects, HMAC-bound to the preparing user and workspace, so a member cannot reuse another credential's subject - aws-service-account: access keys, keys + AssumeRole (external ID), or keyless AssumeRoleWithWebIdentity; resolved server-side per call - databricks-service-account: PAT, service principal M2M secret, or keyless RFC 8693 token federation - AWS families accept the executor-authorized credential through trusted operation context; clients add the session token only for that pair - S3 get_object signs x-amz-security-token for temporary credentials; inline signatures are byte-identical to before - Tool credential binding honors optional (required: false) policies * fix(credentials): close review findings on saved AWS/Databricks credentials - Models can no longer inject a credential selector (or the token, session token, or host derived from one) into a hybrid tool call, which would have swapped an agent tool's inline keys for another workspace credential - Databricks connections own the workspace host (authoritative `domain`) - Drop the advanced credential-ID input: with a single picker, "is a credential selected" can no longer disagree with the active canonical mode - OIDC subject proofs are bound to their provider - Databricks token and identity fetches refuse redirects - Correct the AWS module doc on presigned URLs carrying a session token * chore(credentials): satisfy test-pattern, unused-export, and test-type audits * fix(credentials): keyless reconnect, availability, and shared credential plumbing - Reconnecting a keyless AWS role or Databricks principal keeps its trusted subject by default instead of issuing a new one that breaks the customer's trust policy - The connect dialogs offer the keyless mode only where the deployment can sign tokens; the prepare endpoint reports availability instead of failing - Register AWS (all 19 block types) and Databricks as stored-credential integrations, so org settings, the v2 credentials API, and Copilot can create and see them - Optional STS region for GovCloud and China access keys - One subject binder and config parser shared by both providers (neutral copy), one modal core for submit/errors/trust display - Generic `authorizedServiceAccountCredential` operation context instead of an AWS-specific field; Databricks resolver checks credential type and honors cancellation - Model-blocked params derive from each tool's authoritative params * test(credentials): type the handler mock in the AWS credential seam test * feat(credentials): credential-only block versions instead of hybrid inline keys Existing AWS and Databricks blocks are left exactly as on staging, only marked legacy and hidden from the toolbar; placed instances keep running and show an upgrade badge. Each gets a credential-only successor (s3_v2 ... databricks_v2, textract_v3) built by spreading the legacy block and swapping its secret fields for a required saved-credential picker. - withSavedCredential derives the successor's fields, inputs, and params builder; S3 and Textract split their builders so legacy key checks stay - tools declare credentialSuppliedParams so serializer validation and the canonical-id check stop asking credential-only blocks for inline keys - CloudWatch gets saved-credential log group/stream selectors that sign inside the credential's STS session - docs generator resolves multi-level spreads and same-file param builders - the AWS/Databricks providers are derived from the catalog again, so the hand-maintained token-credential mapping is reverted * docs(credentials): document credential-only blocks by their credential, not inline keys The generator omits a tool's credential-supplied params on pages for blocks that sign in with a saved credential, as it already omits accessToken. Intros now point at the AWS/Databricks credential guides. Regenerates OpenAPI, CLI API, and CLI docs for the new selector keys. * fix(blocks): never replace trigger fields that share a secret's id A webhook trigger can register with a field named like the block's secret (PagerDuty, Fathom, EmailBison, GitLab). withSavedCredential now leaves trigger-mode fields, and their dependencies, exactly as they are. * feat(credentials): generic saved-token plumbing for credential-only blocks Wave 0 of moving inline-secret blocks onto saved credentials. - tokenCredentialOAuth(provider, credentialParams) declares which tool params a saved token fills; credentialSuppliedParams is derived from it - the executor fills those params after authorization, overriding any caller value, and fails closed when the credential lacks a field - hosted keys are never injected when a saved credential supplies the key - v2 tool execute no longer demands credential-supplied params when a credentialId is passed (fixes AWS/Databricks direct calls) - withSavedCredential accepts an optional/conditional requirement - check-block-registry verifies every credential-only successor's tools authorize the picker's provider and actually fill what they declare - redact secretAccessKey/awsSecretAccessKey keys in logs - serializer contract test covers every operation of each successor * feat(credentials): Tavily saved credential and credential-only tavily_v2 Reference migration for wave 1. A generic tokenCheckValidator verifies a token with one documented authenticated request (no redirects); Tavily uses GET /usage. Legacy tavily is unchanged apart from its legacy marker. * fix(credentials): close wave-0 audit findings - agent tool-input no longer synthesizes inline secret fields a block's saved-credential picker supplies; one shared rule (credentialSuppliedParamsFor) now drives tool-input, serializer validation, and the canonical-id check - the picker inherits the replaced secret's condition and requirement, so sts_v2's unsigned calls (web identity, SAML) need no credential - withSavedCredential replaces both halves of a canonical secret pair and refuses options that would silently do nothing - Databricks fills its inline apiKey/host through credentialParams, so its tools are byte-identical to staging apart from the policy line - AWS operation families record their tool ids; a test and an executor guard ensure every AWS-credential tool resolves the credential - the registry contract check fails on unpinned host params, optional credentials over required params, malformed pickers, and kind mismatch - hosted-key admission (v2) and pre-resolution validation honor a selected saved credential; credential errors name fields in plain words * feat(credentials): wave 1 — saved token credentials for 48 single-token blocks Each block keeps its legacy definition (only hideFromToolbar + sunset) and gains a credential-only <type>_v2. Every service gets a token-paste provider with a one-request validator against a documented, read-only, credit-free endpoint, and its tools fill the inline key from the saved credential via tokenCredentialOAuth. Blocks: affinity, agentmail, agentphone, ahrefs, apify, apollo, brex, brightdata, browser_use, buffer, circleback, clerk, cloudflare, crunchbase, daytona, elevenlabs, enrich, gamma, hex, huggingface, incidentio, instantly, langsmith, launchdarkly, linq, loops, luma, mailchimp, otter, persona, pinecone, profound, quartr, rb2b, rippling, rocketlane, semrush, sendgrid, similarweb, sixtyfour, smartlead, sportmonks, square, tailscale, trigger_dev, uptimerobot, youcom, youtube. The registry contract check now probes each request tool's real URL builder to find params that steer the host, and requires the saved credential to fill them. * fix(credentials): close wave-1 audit findings - Pinecone and Semrush leave wave 1: Pinecone's per-call indexHost would let a shared key reach any host, and Semrush has no credit-free check that rejects a wrong key. Both are back to staging exactly. - tokenCheckValidator: forbiddenMeansScoped accepts a valid key that lacks the check endpoint's scope (Apollo, Brex, Bright Data, Apify, Rippling, Persona); acceptsBody proves keys whose rejection arrives in a 200 body (Buffer GraphQL) - the host-steering probe lives in scripts/saved-credential-contract.ts: typed placeholders for required params only, id/host shapes, bare and scheme probes, and a broad destination-name fallback where the URL cannot be built; covered by a fixture test - S3 refuses a bucket or region that would move the signed request's host - spread-inheriting docs keep their base block's outputs (restores the Smartlead, Trigger.dev, and Instantly output tables) - incident.io's credential is optional for alert events, which use their own alert source token - withSavedCredential refuses replaced secrets that show or require differently; copy, intro, and hint fixes from the audit * fix(credentials): close wave-1 re-audit findings - host probe also defeats unparsed suffix checks and finds hosts behind optional switches, probing every placeholder shape; broader destination names where a URL cannot be built; the contract check fails when a successor's tool is missing from the executable registry - the optional-credential rule evaluates a conditional picker per operation; incident.io hides its picker on alert events instead - withSavedCredential takes an explicit picker condition and refuses one that depends on a replaced secret at any nesting depth - a scoped 403 counts only when it is the vendor's JSON response, never a firewall or CDN page - S3 names a bad bucket or region in its error - pinecone/semrush catalog dates restored to staging * feat(credentials): wave 1b — Mem0, Zep, and Discord saved credentials Their legacy params builders throw without an inline secret, so each is extracted into a module function with a requireKey flag: the legacy block keeps identical validation and messages, the credential-only v2 skips only the key check. discord_v2 hides its picker for webhook posts, which never use the bot token. BlockToolParams is now a shared type for extracted builders (S3, Textract, Discord). * feat(credentials): wave 1b — v3 credential-only versions and Flint Blocks that already had a v2 get a credential-only v3 that spreads it: cursor, dub, extend, fireflies, intercom, pulse, quiver, reducto. The v2 becomes legacy and every older version's replacedBy points at v3. Extend, Pulse, and Reducto's v2 builders trimmed the key inline, so each is extracted into a builder that takes the key as an argument; the legacy v2 passes the trimmed key exactly as before. Flint gets flint_v2 with a dedicated validator: its API has no read endpoint, so an unknown task id answering 404 proves the key. tokenCheckValidator gains rejectsKey for vendors that answer a bad key with a server error (Fireflies returns 500 auth_failed), so the user is told the key is wrong rather than the vendor down. * fix(credentials): close wave-1b audit findings and CI boundary failures - token checks for the 59 new providers live in one module (validators/token-checks.ts) and their tool policies in tools/shared/saved-credentials.ts, so the tool-registry boundary stays within its baselines instead of adding ~60 modules to every graph - the host-steering probe builds URLs through the shared transport (new prepareToolRequestUrl) and also flags a host validated against a vendor allowlist when two accepted values reach different tenants - the AWS routing test reads typed metadata through getToolMetadata - Flint accepts only its documented JSON 'Task not found' 404; Intercom no longer treats a 403 (suspended workspace, plan without API) as valid; Fireflies keeps its error text in logs when a 5xx isn't auth_failed - Cursor help text, placeholder wording, Pulse intro, sorted secret fields * fix(credentials): address pre-ship verification findings - Refuse a keyless AWS role whose trust policy doesn't pin the credential's subject, so no other workspace can assume it - Treat a malformed workload-identity signing key as not configured - Brex: reject an unknown token's scope-style 403; the token-check factory now runs rejectsKey before accepting a scoped 403 - Flint: probe with a docs-shaped task id and a size-capped body read - Drop the versioned BlockMeta entries that doubled templates; alias bare block types in the app icon map so template icon clusters resolve - Widen the host-probe fallback names and rotate digits in alternates - Copy: picker placeholder casing, Databricks v2 description, Pulse and Tailscale skills, AWS/Persona/Rippling intros, AWS credential docs - Tests: AWS executor signing, AWS/Databricks credential setup, legacy params builders, serializer coverage for blocks without operations * refactor(credentials): one saved-credential table and shared helpers - withSavedCredential reads the replaced fields from SAVED_CREDENTIAL_OAUTH, so blocks and tools share one table instead of two hand-kept copies - Reuse isTriggerModeSubBlock, getDependsOnFields, and a shared isSavedCredentialPicker; build the replacedBy map once in the registry check - newWorkloadIdentitySubject owns the subject format; the AWS trust-pin probe runs alongside verification - The issuer parses a bad signing key once instead of per request - Token checks share the accepted result and the capped JSON reader * chore(credentials): cleanup pass - Keyless setup query gets its own key root, so broad credential invalidations can't refetch an open setup and mint a new subject - Named staleTime constant for the setup query - Correct stale comments (relying parties, Databricks param names) - Tighten tests: assert the refusal reason, make the BYOK guard reachable, drop a duplicate and a test that could not fail * fix(credentials): address review round 1 - A scoped 403 whose body can't be read is provider_unavailable, never accepted - Provider error snippets read through the bounded reader - Props interfaces for KeylessTrustFields and useWorkloadIdentitySetup; TSDoc on issuer responses * fix(credentials): never cache the issuer's not-configured 404
Bumps the actions group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [docker/login-action](https://github.com/docker/login-action) | `4.7.0` | `4.8.0` | | [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) | `4.1.2` | `4.1.3` | | [actions/setup-java](https://github.com/actions/setup-java) | `6.1.0` | `6.2.0` | | [actions/setup-dotnet](https://github.com/actions/setup-dotnet) | `6.0.0` | `6.1.0` | | [helm/kind-action](https://github.com/helm/kind-action) | `1.15.1` | `1.15.2` | | [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `3.0.3` | `3.0.4` | Bumps the actions group with 1 update in the /.github/actions/image directory: [useblacksmith/setup-docker-builder](https://github.com/useblacksmith/setup-docker-builder). Updates `docker/login-action` from 4.7.0 to 4.8.0 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](docker/login-action@81c6f93...8aa5831) Updates `sigstore/cosign-installer` from 4.1.2 to 4.1.3 - [Release notes](https://github.com/sigstore/cosign-installer/releases) - [Commits](sigstore/cosign-installer@6f9f177...756fe2d) Updates `actions/setup-java` from 6.1.0 to 6.2.0 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](actions/setup-java@b843ebf...77dd5b2) Updates `actions/setup-dotnet` from 6.0.0 to 6.1.0 - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](actions/setup-dotnet@a98b568...0f4a354) Updates `helm/kind-action` from 1.15.1 to 1.15.2 - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](helm/kind-action@1544676...ea822c7) Updates `softprops/action-gh-release` from 3.0.3 to 3.0.4 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](softprops/action-gh-release@efb3536...8a0cd65) Updates `useblacksmith/setup-docker-builder` from 2.2.0 to 2.3.0 - [Release notes](https://github.com/useblacksmith/setup-docker-builder/releases) - [Commits](useblacksmith/setup-docker-builder@1921511...06dd9c8) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 4.8.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: sigstore/cosign-installer dependency-version: 4.1.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/setup-java dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: actions/setup-dotnet dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: helm/kind-action dependency-version: 1.15.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: softprops/action-gh-release dependency-version: 3.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: useblacksmith/setup-docker-builder dependency-version: 2.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
… to Decide (#9844) Co-authored-by: Sim Pi Agent <pi@sim.ai>
* feat(search): update GitLab permission CSVs through the API * fix(search): align GitLab CSV updates with CLI and API policies * test(cli): cover confirmation for GitLab permission replacement
…9845) * feat(search): manage source permissions through a shared API and CLI * chore(search): document the shared permission grant format
…K 2.4, and small in-range updates (#9846)
…s, and keyless hardening (#9840) * fix(credentials): accept scoped keys on save, isolate the retiring signing key, surface Databricks token errors * improvement(credentials): report Databricks token failures in the shared service-account codes * feat(credentials): saved credentials and credential-only versions for 17 more token blocks Ashby, Calendly, Checkr, Fathom, Grain (v3), Granola, Lemlist, PagerDuty, Resend, Rootly, Semrush, Sentry, Stripe, Telegram, Typeform, Vercel and WhatsApp get a token credential with a vendor check on save and a credential-only successor. Legacy blocks only gain hideFromToolbar and a sunset; Telegram's params builder is extracted so the legacy block keeps its bot-token check. * fix(credentials): close batch-2 audit findings Restricted keys that name their missing permission (Ashby, Resend, ElevenLabs) are accepted through a provesKey check; Typeform rejects every 403; WhatsApp keeps the phone number ID in its own path segment; Semrush is held back because its free balance check accepts unknown keys. * improvement(credentials): put the credential picker under the operation picker and share the provider-failure split Credential-only blocks now show their saved-credential picker right under the operation picker. Validators reuse the tools' header builders, one providerFailureCode decides caller vs provider errors (a Databricks token reply without a token is the provider misbehaving), and new providers sit in alphabetical order. * fix(credentials): harden keyless sign-in for AWS and Databricks Saving a keyless Databricks connection now refuses a federation policy that trusts every Sim subject, as AWS roles already were. Keyless stays off when the issuer isn't https on the default port, and an unpinned issuer is logged. Docs cover a zero-downtime key rotation, the issuer requirements, finding the service principal ID, and troubleshooting. * feat(credentials): saved GitLab token credential and credential-only gitlab_v2 A GitLab credential holds a personal, project, or group access token and the instance host (gitlab.com or self-managed). Saving verifies the token's self-lookup at that exact host over the SSRF-guarded fetch with no redirects and requires an active token with an API scope; runs only reach the verified host. Successors may now state the picker's required rule when the replaced fields differ (GitLab's host was optional). * fix(credentials): close final-audit findings on keyless wording, issuer logs, and WhatsApp IDs The Databricks refusal names the real cause (a subject_claim other than sub), the issuer failure log points at the key or issuer, the AWS troubleshooting leads with the message users see, rotation steps cover background workers, and a WhatsApp phone number ID can no longer leave its path segment. * fix(credentials): keep GitLab personal tokens available after GitLab moves to gitlab_v2 Personal-token visibility resolved the GitLab integration by the legacy block type, so hiding that block and renaming its catalog entry hid every existing personal token and refused new ones. It now resolves the current GitLab version, and the integration page lists personal tokens beside saved GitLab credentials. * chore(credentials): cleanup pass on the batch-2 changes * chore(credentials): shrink the unused-exports baseline * fix(credentials): type the GitLab check's secure-fetch response * fix(credentials): address review round 1 GitLab's integration page offers personal tokens and saved access tokens side by side, a malformed GitLab token lookup reports the provider as unavailable, and the keyless issuer refuses a query string or fragment. * fix(credentials): close the PR-wide audit findings Docs describe credential-only Telegram and Typeform actions and the issuer's query/fragment refusal, PagerDuty and Grain copy name every token type that works, Granola accepts a key whose note scope an admin turned off, a GitLab reply that isn't a token lookup reports the provider, and Semrush's catalog entry matches staging exactly. * improvement(credentials): simplify and clean up the review-round changes * fix(credentials): address review round 2 Ashby's restricted-key check reads the missing permission from object-shaped error entries too, and a GitLab host that doesn't resolve is reported as not found instead of the provider being unavailable.
* fix(firecrawl): complete v2 response and depth compatibility * fix(firecrawl): preserve index pages with crawl path filters
…-release fixture (#9850)
…one host-aware check factory (#9849) * refactor(credentials): host-aware token checks in the shared validator factory tokenCheckValidator now takes a domain normalizer (stored as the credential's domain), an account-id normalizer, an SSRF-guarded egress profile for hosts the user chose, and a flag that keeps token-echoing error bodies out of logs. GitLab becomes a declaration on it, so every token check reads the same way. * feat(credentials): saved credentials for 20 token-and-host blocks Algolia, Azure DevOps, Convex, Devin, Dynatrace, Email Bison, Grafana, Infisical, Jotform, Jupyter (v3), Logfire, Mailgun, New Relic, Okta, Plane, Supabase, Tinybird, Twilio SMS and Voice (one shared Twilio credential), and Upstash get a credential that carries the token plus its host, region, or account id, and a credential-only successor. Every host-deciding param comes from the credential; a typed host is normalized as the tools do it and verified through the guarded egress, a region or account id is checked before any request, and Databricks subject tokens last up to an hour so long Genie polls keep their token. * feat(credentials): Thrive saved credential, and close the batch-3 audit findings Thrive gets a credential holding its key, tenant id, and region host (one of its four API hosts). Audit fixes: the connect form sends URL-shaped domains as typed so the provider check keeps their scheme and path; credentials default to a name with their domain or account id (GitLab keeps its token name) and record it in the audit log; Upstash accepts http and a read-only token refused PING; Infisical keeps http and a proxy path; Devin, Dynatrace, and Logfire refuse dot segments, non-http schemes, and mistyped regions. * improvement(credentials): simplify and clean up the token-and-host checks One normalizeHttpBaseUrl and one allowedDomain replace five URL normalizers and four region checks (fixing Grafana and Tinybird treating a non-http scheme as a host); region tables come from the tools; acceptsBody can name the credential (GitLab); Email Bison and Jupyter refuse credentials in the URL instead of dropping them; the Supabase public-URL policy is inlined; the Databricks token lifetime uses the issuer's cap. * fix(credentials): address review round 1 Azure DevOps tools build every project-scoped URL through one traversal-safe helper, so a project or build id can't climb into another organization with a saved token; Tinybird and Upstash restricted-token replies are covered by tests. * fix(credentials): address the final audit An Azure DevOps project or organization pasted already encoded is decoded once before the traversal-safe segment, so it isn't encoded twice; a base URL with a single-slash scheme is refused; Upstash accepts a proxy path like the legacy block; a Thrive tenant id must be printable ASCII. * docs(skills): teach the saved token credential pattern in the integration skills add-integration, add-block, add-tools, and validate-integration now describe the token credential (descriptor, tokenCheckValidator declaration with its host and account normalizers, shared policy mapping every host-deciding param) and credential-only successors for blocks that take a secret inline. * docs(skills): address review round 2 The token-credential skill steps name the real tokenCredentialOAuth factory, scope the checklist to token-credential and successor blocks, and keep the AuthMode.ApiKey path for token-only blocks; normalizeEmailBisonBaseUrl gains its TSDoc. * fix(credentials): refuse an Email Bison instance typed with a non-https scheme normalizeEmailBisonBaseUrl now keeps any typed scheme, so ftp://host is refused instead of becoming a host named ftp. * fix(credentials): close release-audit findings in the saved-credential executor - A policy that maps credential fields owns them: the generic domain, instanceUrl, apiDomain and cloudId fills no longer write a stored host into a same-named user param (Thrive create/update user sent its region host as the user's domain). - An agent tool with a saved credential selected is neither asked for nor allowed to send the params the credential supplies (Azure DevOps organization, Infisical base URL). - ENOTFOUND is read from the error or its cause, so a mistyped host or account id is site_not_found under Bun as well as Node. - A service-account secret is released only to a tool bound to its provider; a bare credential ID is refused. * fix(credentials): refuse non-http schemes on typed hosts; correct docs and copy - One refuseUnsafeTypedUrl guard refuses a typed instance URL with credentials or a non-http(s) scheme, for Email Bison, Jupyter and Logfire, before their normalizers can read the scheme as a host. The Email Bison tool normalizer is back to its staging behavior; the check lives in the credential validator, so legacy blocks are unchanged. - Docs for successor users: Jotform region, Dynatrace scopes, Logfire host, Plane instance, Infisical, Fathom and Supabase now point at the saved credential; self-hosting no longer says API keys live in blocks; the AWS keyless step names the dialog's Issuer. - ElevenLabs and Instantly copy no longer asks for a permission their checks don't need; Okta lists trexcloud.com.
… requests, AWS SDK clients and OTLP export (#9851) * feat(network): honor HTTP_PROXY, HTTPS_PROXY and NO_PROXY for guarded outbound requests * fix(network): limit environment proxies to http and https, cover an https proxy * feat(network): route AWS SDK clients and OTLP exporters through the environment proxy * fix(network): record the proxy dependencies under apps/sim and register the proxy agent as egress infrastructure
… Mistral Parser (#9856) * feat(mistral): extract PDF images as files and expose table format in Mistral Parser * fix(mistral): type the v3 images output as optional for the shared v2 base * fix(mistral): name extracted images as storage does, drop inline table format, align image switch with tool param * docs(mistral): describe Extract Images and Tables options in the Mistral Parser page
… from the start URL, and drop stale route cache on upgrade (#9860) * fix(release): cap proxied plain-http responses, count Firecrawl depth from the start URL, and drop stale route cache on upgrade * fix(firecrawl): read a scheme-less start URL as https when counting depth
…pose don't expand them (#9861) * fix(sim-setup): quote env values containing $ so dotenv, Bun, and Compose don't expand them * fix(sim-setup): write $ as \$ in double quotes, the one form Next, Bun, and Compose all read literally
…orkflow access middleware and docs (#9858)
…LI key-creation errors, show GitLab tokens as the current block (#9862)
… saved-credential contract, and drop SDK copy (#9864)
…t paths from the release audit (#9865) * fix(security): harden saved-credential, proxy egress, and response-cap paths from the release audit - Refuse session callers resolving saved service-account secrets on POST /api/auth/oauth/token - Refuse a proxied hostname when any resolved record is blocked (the proxy re-resolves) - Apply the response cap to every body, not only decoded ones (undici's http proxy wrapper ignores maxResponseSize) - Bind workload-identity subjects to their owner at mint time - Bound Databricks token/identity JSON reads; refuse single-slash https:/ in typed URLs; case-insensitive Dynatrace /api/vN strip - Twilio recordings: stay on the Twilio API origin and bound fetch concurrency - Firecrawl: count crawl maxDepth below the start URL; stop sending unused search sources - sim-setup reset refuses when Docker is installed but unreachable - Remove the dead requireDeployment branch from workflow access middleware; reuse requireMutableWorkflow; move a misplaced TSDoc - Docs: CONTRIBUTING setup via sim-setup, sim-setup README, Helm read-only-root mounts, proxy and NO_PROXY behavior, GitLab CSV body limit * fix(security): stop queued Twilio recordings fetches on cancel, type token-route auth mocks, bump chart - Twilio list calls takes the run's signal: queued recordings requests stop once it aborts, and fetch receives it - Token route tests type the hybrid-auth mock through the real AuthResult and pass a route context - Chart version 1.11.13 for the README and helper comment changes
…k crawl depth as unset (#9857) * fix(release): measure Firecrawl crawl depth from the start URL and reuse only full-access delegation keys * fix(release): leave Firecrawl crawl depth to #9864 * fix(firecrawl): treat a blank crawl maxDepth as unset * test(release): prove delegation refuses read-only keys and type a blank crawl depth
* fix(release): small release-audit cleanups - Read a paused run's pause points once per status read instead of querying paused_executions twice. - Log a polling webhook's auto-disable only when this failure disables it, in the same race-free statement. - /api/v2/meta reports the scopes a credential can actually reach, using the same check enforcement uses. Enforcement is unchanged. - MACHINE_ACCESS.md names MCP TypeScript SDK 2.4.0. * test(webhooks): overlapping poll failures count every failure and disable once * test(mcp): expect the search:read scope a full-access key reaches in v2 meta
… boot secret, and remaining audit follow-ups (#9866) * docs(api-keys): add rollback guidance to the api-key-read-only flag * docs(api): say v2 workflow execution needs a full-access API key * chore(api): regenerate MCP operations for the execute scope wording * fix(hitl): stop duplicating input fields across listed pause points * fix(api): refuse a personal v2 key with a missing owner as invalid, not a 500 * fix(credentials): refuse a keyless subject another live credential already holds A keyless subject proof stays valid for 24 hours and is not bound to one credential, so a member removed from a keyless AWS or Databricks credential could save a second credential with the same subject and proof and keep assuming the customer's role. Creating or reconnecting a credential onto a subject it did not already hold now refuses (409 conflict) when another non-revoked credential of the same owner holds it. The subject lives only in the encrypted secret, so the check decrypts the owner's keyless credentials inside the write transaction, under a per-subject advisory lock so concurrent saves serialize. A reconnect keeping its stored subject binds nothing new and skips the check. * refactor(tools): detect the saved-credential picker with isSavedCredentialPicker credentialSuppliedParamsFor matched any oauth-input feeding oauthCredential, without the credentialKind === 'service-account' check isSavedCredentialPicker applies. It now uses that predicate. No registered block changes: every block whose loose-match picker lacks the service-account kind has no tool that declares credentialSuppliedParams. * fix(runtime-secrets): fetch the boot secret through the configured proxy The Secrets Manager client used the SDK's Node handler, which ignores HTTPS_PROXY, so a container whose only egress is a proxy could not load its env and never booted. Under Bun with a proxy set, send through Bun's fetch, which honors HTTPS_PROXY/HTTP_PROXY/NO_PROXY. apps/sim's awsRequestHandler is out of reach for packages and the realtime bootstrap needs the same path. * fix(models): mark NVIDIA Nemotron 3 Super retired and move the NVIDIA default NVIDIA's model page states the nvidia/nemotron-3-super-120b-a12b API is no longer supported after 2026-10-19, and Pi 1.0.1 dropped it as its NVIDIA default for the same reason. Mark it deprecated (hidden from pickers, still a known id for pinned workflows) and default the NVIDIA provider to Nemotron 3 Ultra, which the Pi catalog also serves. The Mistral IDs Pi 1.5 dropped (mistral-large-2411, devstral-small-2507, devstral-medium-2507) were retired by Mistral on 2026-05-31 and are already deprecated here, so saved Pi blocks fail before credentials with the choose-a-model error instead of being mapped onto a different model. * fix(credentials): lock keyless subject checks through the advisory-lock helper and refuse on unreadable siblings assertWorkloadIdentitySubjectUnclaimed now takes a DbTransaction and locks through acquireAdvisoryXactLock, so the lock carries its SQLCommenter tag and cannot be taken on the pool by mistake. A sibling keyless credential whose secret does not decrypt or parse used to throw a generic error, failing every keyless create or rotation for the owner with a 500. Since it might hold the subject, the save is now refused as a conflict naming that credential, with a warning logged, and stored subjects are read with a schema safeParse. * fix(network): match NO_PROXY entries like curl, including bare IPv6 and CIDR A bare IPv6 entry such as ::1 was read as host ':' port 1 and never matched, IP entries only matched their exact spelling, and CIDR ranges were ignored. Entries now follow curl: domains cover their subdomains, bracketed IPv6 may carry a port, IP entries match any spelling, and CIDR ranges match IP-literal destinations. NO_PROXY is parsed once per distinct value. The comments and the self-hosting networking page describe these rules, and note that Bun's default fetch applies its own. * docs(network): note the boot secret fetch follows Bun's NO_PROXY rules * fix(credentials): decide subject reuse under the lock on every keyless reconnect A reconnect that kept its subject skipped the uniqueness check, but whether it kept the subject was decided from the secret read before provider verification. If another reconnect moved the credential to a new subject and a second credential claimed the old one meanwhile, the stale reconnect wrote the old subject back unchecked and two credentials held it. Every keyless reconnect now locks the subject it is writing, then the credential row (FOR UPDATE), re-reads the row's current subject, and runs the sibling check whenever the two differ, with the decision and the write in one transaction. * fix(runtime-secrets): pick the boot fetch's proxy with the app's rules Bun's fetch picks a proxy by scheme only, so with just HTTP_PROXY set the https Secrets Manager request went direct and a proxy-only container still could not boot. Move proxy selection (HTTPS_PROXY falling back to HTTP_PROXY, curl-style NO_PROXY) from apps/sim into @sim/security/environment-proxy, and have runtime-secrets pass the selected proxy to Bun's fetch explicitly, or send through the Node handler when NO_PROXY excludes the endpoint. * docs(api): state the credential and role a manual v2 run requires Manual runs need api:write, which read-only personal keys lack, workspace write access, and a personal key or OAuth token; workspace API keys are refused. Regenerate the OpenAPI document and the MCP operation catalog.
…normalized account ids, cap Databricks reads (#9859) * fix(credentials): report a refused host as the user's input, persist normalized account ids, cap Databricks reads - A saved-credential check whose typed host the egress policy refuses (private address, plain http where https is required) now fails as invalid_credentials instead of provider_unavailable, which rendered as a retryable 503 - The stored account id is the validator's normalized value, matching how the domain is stored - Databricks token and identity responses are read through the capped JSON reader - Comparison data no longer says Sim can be built in code via an SDK * fix(credentials): fail Databricks verification on an oversized identity reply, cite the CLI docs * fix(credentials): report an oversized Databricks token reply as oversized * fix(credentials): tell an interrupted Databricks token reply apart from an oversized one
… literals (#9868) * fix(sim-setup): mirror env values as written so ${VAR} references survive doctor --fix * fix(sim-setup): leave $ references for a hand copy instead of mirroring them, drop the single-quote rewrite * fix(sim-setup): never generate a shared secret doctor can't copy, and report unwritable values instead of aborting * fix(sim-setup): give a placeholder shared secret the same fix as a missing one
…ecret release, and final release-audit cleanups (#9870) * fix(api): tell a missing key owner from an owner whose ban state is null user.banned is nullable, so a real owner with banned = NULL had every personal key refused as orphaned. Select the joined user id and test that instead; the ban and suspension checks are unchanged. * fix(credentials): report a refused connection host as host_not_allowed - egress validation names its refusal (dns or policy) instead of callers inferring it from a missing cause; an empty DNS answer is ENOTFOUND - the token check judges every DNS record when an environment proxy will carry the request, so a mixed public/private host is refused up front rather than failing in the transport as a retryable 502; the transport's own refusal is a typed EgressRefusedError and maps the same way - new host_not_allowed code (400) with its own connect-modal message - Flow and GitLab personal-token verification classify a refused or missing host the same way - the typed-URL scheme guard is shared and ignores the tabs and newlines the URL parser drops * fix(credentials): report an oversized Databricks token success as a 502 An oversized 2xx token reply carried status 200 into provider_unavailable and its logs. A refusal keeps its own status. * docs(api): say v2 execute options need a full-access key or api:write run.version, async and waitTimeoutSeconds refuse read-only keys; the meta example lists search:read with the full-access scopes. * chore(scripts): scope the payload-param allowlist to internal operations Every listed tool is an internal operation, so the probed-request fallback no longer builds or consults it. * fix(redaction): keep Infisical secret names visible; redact only deployKey * docs(networking): the SSRF guard matches NO_PROXY like curl, not like Bun * fix(api-keys): never echo an internal key-creation failure to the caller The unauthenticated CLI poll route and the settings routes returned the raw error message for an internal failure. Return a fixed message and keep the cause in the server log; a conflict still names the existing key. The CLI's comment now says a 400 can also be a refused key creation. * chore: log a failed route-cache clear and spell out the read-only key rollback The route-cache clear stays non-fatal but warns when it fails for any reason other than a missing build id or cache. The api-key-read-only flag says to revoke or replace read-only keys before rolling back. * fix(credentials): release saved secrets only to internal-JWT callers The token route refused only session callers; any other auth type would have been handed a saved secret. Allow internal JWT and refuse the rest. Tools never execute in the browser (the registry boundary keeps the tool registry out of every workspace client graph, and nothing else imports the executor), so the browser-only token fetch through the route is deleted. * fix(firecrawl): treat a blank maxDiscoveryDepth as unset A cleared field arrived as '' and was sent as 0, a crawl of the start page only. It now follows the blank maxDepth handling. * chore(credentials): log a broken JWKS and keep the successor map out of credential display The JWKS route still answers 404 when the signing key is broken, but warns with the error. The GitLab personal-token display reads its block type from the catalog entry instead of importing the generated successor map into a client-imported module. * test: drop or tighten assertions that could not fail - delegation: the read-only replacement case decided its filter by scanning bound params in a fake DB; no real-boundary check exists, so it is dropped with the fake's filter - Twilio: assert how many recordings requests were sent, so an empty loop cannot pass - Pi: the removed-model case restated the absent-from-catalog case * fix(security): ignore a malformed CIDR NO_PROXY entry 10.0.0.0/8/junk parsed as /8. An entry with extra segments is dropped like any other unparseable entry, and the TSDoc says IP entries match within their address family. * chore(workflows): scope the paused-row read to its workflow and reuse the mutability guard - the execution-status paused-row read filters by workflowId as well - delete-workflow uses requireMutableWorkflow instead of an inline copy - polling webhook logs carry the webhook id in metadata * fix(credentials): never name a sibling credential in a trust-setup refusal The caller may not be able to see the credential that holds or blocks the subject, so both refusals name only the workspace or organization. The uniqueness check documents its limits. * docs: correct the Helm readOnlyRootFilesystem note and the deployed-run variables TSDoc * test(credentials): rely on the shared env reset in the proxy validator tests * chore(helm): bump the chart version for the README correction * fix(redaction): keep prefixed secret keys masked while leaving Infisical's bare secretKey visible * fix(release): keep bare secretKey redacted, leave the proxy every-address rule to the transport, and report unknown GitLab hosts as input errors
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
[High impact] The reviewed changes appear safe to merge; no actionable findings were accepted. SummaryThis release adds saved credentials, keyless AWS and Databricks connections, read-only API keys, and new v2 management endpoints.
|
There was a problem hiding this comment.
All reported issues were addressed across 3000 files
Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Turn on auto-fix | Re-trigger cubic
…credential steps (#9873)
…Max Images at 100 (#9872)
…ng, and the NO_PROXY reference (#9874) * docs(release): correct the Discord allowlist note, Mistral image naming, and the NO_PROXY reference * docs(networking): state the NO_PROXY rules without the curl comparison
…eyless, GitHub and Bitbucket tokens, DocuSign JWT (#9869) * feat(credentials): keyless Snowflake connections through workload identity federation A Snowflake connection can now trust Sim's OIDC issuer instead of holding a programmatic access token. Sim signs a short-lived token (audience snowflakecomputing.com) for the credential's own random subject; the customer creates a SERVICE user with WORKLOAD_IDENTITY = (TYPE = OIDC ISSUER SUBJECT). - Save verifies by minting a token and running the identity statement at the pinned account host through the guarded egress path; Snowflake's refusals keep the shared codes (invalid_credentials, site_not_found, provider_unavailable). Subjects bind to their creator like AWS/Databricks. - Runtime: the resolver returns authStyle 'snowflake-workload-identity' for a keyless credential, and the tools and selectors send Bearer WIF.OIDC.<token> with the WORKLOAD_IDENTITY_FEDERATION token type. authStyle and domain are authoritative on every Snowflake tool, so a caller can no longer choose the token type or steer the account host of a saved credential. - PAT credentials resolve and verify exactly as before. - Connect dialog offers the keyless service user with the CREATE USER statement; it falls back to the token dialog where keyless is unavailable. - Docs: Snowflake connections page with keyless setup, troubleshooting, and the 60-minute Snowflake key cache on signing-key rotation. * fix(snowflake): run Cortex Analyst SQL with the resolved credential and reopen keyless reconnects as keyless Cortex Analyst's "run the SQL" went through a nested snowflake_execute_sql call carrying the already-resolved token and host. With authStyle and domain now authoritative, the executor cleared both before the nested call, so it failed for every credential (and a keyless token would have been sent as a PAT). The generated SQL now runs as one guarded statement request built from the parent call's credential-derived host, token, and token type, through the same requestTarget egress the tool transport uses, with redirects refused. The Snowflake connect dialog opened every reconnect on the programmatic access token. The workload-identity prepare call now takes the reconnected credential and reports whether it is keyless (only to an admin of that credential in the same workspace), and the dialog opens on that mode. Docs: the 60-minute wait applies before signing with a new key; removing the old key needs 10 minutes with keyless Snowflake connections. * fix(snowflake): cancel Cortex Analyst's generated SQL with the run The generated SQL used to run as a nested tool call, which inherited the run's abort signal; running it directly dropped that. postProcess now receives the executor's effective abort signal as an optional fourth argument (the same signal the tool's own request used), and Cortex Analyst forwards it to the DNS check, the guarded fetch, and the response read. Other tools' postProcess hooks are unchanged. * feat(credentials): saved GitHub personal access tokens and Bitbucket access tokens GitHub: a saved personal access token credential (fine-grained or classic), verified against api.github.com/user with the tools' own headers. GitHub's workflow block authenticates with an inline token rather than OAuth, so it follows the token-block pattern: github_v3 is the credential-only successor of github_v2, which stays exactly as it was, marked legacy and hidden from the toolbar. Every GitHub tool declares the optional saved-token policy; inline tokens keep working. The GitHub App installation credential (Search) is a separate service and is untouched: the Assistant still projects GitHub tools onto the person's connected GitHub account, and Search policy now follows the visible GitHub block (github_v3). Bitbucket: a workspace, project, or repository access token as a second option next to OAuth (the Linear pattern), verified by listing one repository of the typed workspace on api.bitbucket.org; the slug is validated so it cannot steer the path. List Workspaces needs a signed-in user, so it now refuses a saved access token before any request. Also: isHostNotFound no longer lets an outer error code mask ENOTFOUND on its cause. * fix(credentials): close wave 2a review findings on GitHub and Bitbucket tokens - The GitHub token service is `github-token`, so it no longer shares an id with the GitHub sign-in provider: parseProvider and getProviderIdFromServiceId answer for sign-in exactly as before, and a token-only service is never marked connected from a sign-in account whose id prefixes it. - Suggested connect rows offer each integration once and count it connected when any of its services' OAuth or service-account credentials is saved (GitHub's Search App and saved tokens share one integration). - Assistant GitHub calls bind through the connected-account policy the Assistant projects (the person's github-repositories OAuth account) in the token resolver too, on both the ordinary and managed paths; workflow runs and saved workspace tokens are unaffected. - Bitbucket verification reads one repository (`workspace/repository`), the request Atlassian documents for workspace, project, and repository access tokens alike; listing a workspace is not documented for repository tokens. - prepare-workload-identity test uses the central credentials-access mock. * feat(credentials): DocuSign JWT Grant credentials next to OAuth A saved DocuSign credential that authenticates with JWT Grant (an integration key, an impersonated user ID, the app's RSA private key, and an environment), offered as a second option beside the existing OAuth connection, which is unchanged. The minter signs an RS256 assertion (iss = integration key, sub = user, aud = the environment's authentication host without a scheme, scope "signature impersonation"), exchanges it at that host's /oauth/token, then reads /oauth/userinfo on the same host to bind the pinned account (or the user's default) and returns its eSignature REST base. Both hosts come only from the stored environment; a base_uri outside that environment's docusign.net shape is never trusted with the token. GUIDs and the key are checked before any request, and tokens are re-minted about 15 minutes before they expire, as DocuSign advises. DocuSign tools take the account base as an authoritative credential param, so a caller can never supply it, and DocuSignClient skips its deployment-host userinfo lookup when one is bound. OAuth tokens resolve exactly as before. Save-time failures map to consent_required (the connect modal shows the exact consent URL for the key and environment) and account_not_found (a pinned account the user does not belong to), alongside the shared invalid_credentials and provider_unavailable codes. * fix(credentials): close wave 2b review findings on DocuSign JWT Grant - The DocuSign knowledge connector now honours a JWT Grant credential's bound account. The resolved token's instanceUrl reaches the connector as credentialInstanceUrl in the sync context (seeded on every path through syncContextForToken). The connector re-validates it with the same parser as DocuSignClient, lists and fetches from that account in the credential's environment, links envelopes to that environment's web app, and validates without asking the deployment host. A seeded value of the wrong shape fails closed. OAuth syncs are unchanged. - RSA keys under 2048 bits are refused as invalid_credentials with copy that names the size, instead of jose's raw TypeError. - A short expires_in no longer makes every call re-mint: the cached lifetime floors at six minutes while staying a minute under the real expiry. - The connect modal shows the consent URL as a link with a copy button, and account_not_found says "pinned account" only when one was entered. * feat(credentials): Microsoft Entra app-only credentials for Entra ID, SharePoint, Dataverse, and Dynamics 365 A saved Microsoft app credential (OAuth 2.0 client credentials) as an additional option next to Microsoft OAuth, which is unchanged. One app registration serves the four services whose tools run without a signed-in user; Outlook, OneDrive, Excel, Word, Planner, and Teams never offer it and token resolution refuses it for them (provider mismatch). - Modes: client secret; certificate (PS256 client assertion with the certificate's x5t#S256 thumbprint, aud = the tenant token endpoint, 5-minute lifetime; key/certificate pairing, RSA size, and expiry checked before any request); keyless federated credential (a Sim workload-identity token for the credential's own subject, audience api://AzureADTokenExchange, subject bound to the saving user, refused if the app also accepts an unheld subject). - The token resource comes from the tool's service, passed from the server-validated tool policy: Graph for Entra ID and SharePoint, the stored environment for Dataverse and Dynamics 365. Any other service is refused. - The environment URL is stored on the credential (public-cloud Dynamics hosts, https root only). Dataverse tools take credentialType and instanceUrl as authoritative params; an app credential's request goes only to its own environment and a block environment that names another is refused. OAuth requests keep the block environment exactly as before. Dynamics 365 already matched instanceUrl against the block environment. - Save check: a Graph token reading the app's own service principal (no permission needed), plus Dataverse WhoAmI when an environment is set. Entra AADSTS codes map to actionable copy; runtime failures keep the shared invalid_credentials / provider_unavailable split. Tokens cache per credential, resource, and stored-secret version in an LRU. - Azure AD Reset password refuses app-only credentials: Graph does not support application permissions for resetPassword. - Connect dialog with tenant ID, client ID, environment URL, and the issuer/audience/subject to paste; docs page with per-mode setup. * fix(credentials): close wave 3 review findings on Microsoft app credentials - SharePoint selectors (workspace and organization paths) and knowledge connectors now pass the service they resolve for (the selector's own serviceId, the connector's declared auth provider), so a Microsoft app credential browses SharePoint with a Graph token instead of being refused. The resolution option is renamed from toolService to service; it is only ever set from server-side policy. - AADSTS700211 and 700212 are no longer mapped: Microsoft documents only 70021 and 700213 for federated credential mismatches. Other keyless refusals still name the mismatch. - DocuSign minter test mocks carry account_name, and the connector access-token test narrows its tokens with a guard instead of non-null assertions. * feat(credentials): keyless Google Cloud credentials via Workload Identity Federation A keyless mode of the existing Google service account credential (google-service-account) for Google Cloud APIs. JSON-key credentials, their connect flow, and their token minting are unchanged. - Flow: Sim signs a short-lived token for the credential's own subject with aud = the customer's provider resource name (https://iam.googleapis.com/projects/<number>/locations/global/ workloadIdentityPools/<pool>/providers/<provider>), exchanges it at sts.googleapis.com/v1/token (token-exchange, jwt subject token, cloud-platform scope, audience //iam.googleapis.com/...), then calls iamcredentials generateAccessToken for the service account with the tool's scopes and a 1h lifetime. Impersonation rather than direct federated access: some Cloud APIs reject federated tokens, and the service account keeps the same identity and roles a JSON key uses. - Inputs validated against Google's documented formats before any request: numeric project number, pool/provider IDs (4-32 [a-z0-9-], no gcp-), and a user-managed *.iam.gserviceaccount.com email, so nothing can steer the STS audience or IAM URL. Requests never follow redirects. - Scope: refuses domain-wide delegation (an impersonated user) and any service but BigQuery and Vertex AI before reading further or contacting Google, with a new shared unsupported_use code and copy pointing to a JSON key. Workspace blocks never offer the mode. - Save check: STS exchange, impersonation, and tokeninfo (no IAM role or enabled API needed), plus a probe that a subject no credential holds cannot impersonate the service account. Subject bound to the saving user with the signed proof; kept across reconnects. - STS/IAM failures map to actionable copy (provider settings, issuer reachability, the exact workloadIdentityUser binding) without Google's descriptions or any token; runtime keeps the invalid_credentials / provider_unavailable split. Tokens cache per credential, secret version, and scopes in an LRU. - Per-credential audiences: audiences.ts gains google without a fixed audience; the setup response omits audience for it and reports a keyless reconnect. Connect dialog shows the issuer, audience, subject, and filled-in gcloud commands (pool, OIDC provider with attribute condition on the subject, IAM binding); docs section added. * fix(credentials): close wave 4 review findings on keyless Google Cloud credentials - Drop the tokeninfo check: a token from generateAccessToken already proves the provider accepted Sim's token and the impersonation binding, and tokeninfo puts a live token in a query string. - Test that saving fails closed when the stray-subject pin probe hits an STS outage or an unreachable IAM endpoint. - Pass --project=<project number> on all three gcloud setup commands, drop the unused Resource Manager API from the docs, and raise the shared validation error for an empty scope list. * fix(credentials): keep Snowflake, Microsoft app, and Google keyless subjects unique The subject-uniqueness scan from #9866 covered only AWS and Databricks. It now also scans Snowflake, Microsoft app, and Google service account credentials, so no two live credentials of an owner hold one keyless subject. Their keyed secrets that carry no config (a Google JSON key, a Snowflake programmatic access token) hold no subject and no longer read as unreadable. The three keyless save paths report a newly bound subject so create checks it. * fix(credentials): close round-1 CI and review findings on alt auth - Knowledge connector tests expect the service now passed with Google service-account token requests; a new test proves a JSON-key mint signs the same request with or without it. - Re-record the tool-registry-boundary baseline: the keyless Snowflake, Microsoft app, and Google modules add 5 modules behind credential-service, which tipped credit-usage past its allowance on top of staging's drift. - Docs compatibility baseline: record the new code examples in the Google and Snowflake service account pages. - Generate the Microsoft certificate test fixture at run time instead of committing a PEM key and certificate. - A Microsoft app credential reconnect opens on keyless only when the stored credential is federated (the prepare step now reports it), like Snowflake; new connections still default to keyless. - TSDoc on the Google project number, pool/provider ID, and service account email validators. * fix(credentials): offer keyless Google setup only in a Google Cloud context Reconnecting a keyless Google service account from a Workspace integration (Gmail, Drive, ...) offered the keyless form, saving a credential that integration can never use. The dialog now offers keyless only for a Google Cloud service (new or reconnect) or on the credential's own page; from a Workspace integration it explains the credential works only with BigQuery and Vertex AI and does not save. The chat connect control passes its service so it gets the same gate. * test(credentials): match the stable part of the subject-in-use refusal
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 39921752 | Triggered | Generic High Entropy Secret | 9ab4e6f | apps/sim/lib/credentials/google-workload-identity.server.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
…d Sim MCP (#9875) Keyless (workload identity) credentials could only be set up in the web connect dialog. Platform teams scripting their cloud trust now get the same two steps as an API: 1. POST /api/v2/credentials/workload-identity/subjects (`sim credentials keyless-subject <providerId>`) issues a random, per-credential subject and a 24-hour proof bound to the caller, plus the keylessConfig to fill in and the provider's required fields. 2. The existing create (`sim credentials create … --credentials @keyless.json`) submits the completed config; Sim verifies the trust before saving. - The existing prepare use case now also admits personal API keys and OAuth tokens with api:write. Workspace keys and delegated callers stay refused, because the subject must belong to a person. - Every keyless refusal carries one stable `error.details.code` (WORKLOAD_IDENTITY_NOT_CONFIGURED, _PROOF_EXPIRED, _PROOF_INVALID, _SUBJECT_REQUIRED, _SUBJECT_IN_USE, _SUBJECT_UNVERIFIABLE) on a single refusal error, from create, reconnect and the subjects route alike. - The provider catalog advertises a `keyless` object (authType and required/optional config fields) only when the deployment can sign, and the CLI reads it instead of keeping its own provider table. Snowflake's keyless config is now accepted by the CLI. - Provider hints, OpenAPI, MCP tool descriptions, CLI help and the five credential docs pages describe the flow the same way. - AWS and Databricks keyless create and reconnect also refuse with WORKLOAD_IDENTITY_NOT_CONFIGURED when the deployment cannot sign, and their verification steps pass keyless refusals through unchanged. Each provider's refusal names a fallback credential type. - The Google Cloud keyless hint says it covers Cloud services (BigQuery, Vertex AI), not Google Workspace.
…anning stays quiet (#9876)
…saved-credential contract on every credential block (#9878) * fix(credentials): enforce the saved-credential contract on every credential block, reopen key-based reconnects on their mode, and tighten fixtures and skills - check-block-registry runs the saved-credential contract for every block with a saved-credential picker, not only successors; the per-block contract moves to saved-credential-contract.ts with tests. The host probe gains a path-shaped id and a per-param shape so mixed-validation builders (Jama, Higgsfield) are probed, not guessed. - Blocks the widened check caught: Coda, Harmonic, and Oracle Database tools declare credentialKind 'service-account'; NetSuite pins instanceUrl in authoritativeParams; Vanta's assetExternalAccountId is a filter, not a host. - prepareWorkloadIdentity covers every keyless provider (AWS, Databricks added) and reuses audiences.ts for the provider-id mapping; the AWS and Databricks dialogs reopen a reconnect on the stored mode. - Snowflake keyless verification maps an egress refusal to host_not_allowed. - Neutral token fixtures in new credential tests; subject uniqueness TSDoc; skills describe native token blocks, the picker shape, keyless setup, and the successor naming exception. * docs(credentials): fix keyless setup instructions and copy - AWS: enter the Role ARN before setting the trust policy, so it never carries the <AWS_ACCOUNT_ID> placeholder IAM rejects (dialog hint and docs). - Databricks: the federation-policy command needs an account-level CLI login. - Google: a valid sample pool ID, ID format hints, user-managed service accounts only, skip the pool command when the pool exists, and the API list from Google's guide (adds Resource Manager). - Bitbucket: workspace and project access tokens need Premium; repository tokens do not. - Snowflake: rename SIM_WORKFLOWS if it exists; USERADMIN runs the statement. - Microsoft keyless dialog says where the federated credential goes. - Server errors name the trust values for API and CLI callers too; Google Workspace and Account ID wording; AWS catalog hint mentions stsRegion; the CLI keyless example uses aws-service-account throughout. - Self-hosting env vars list every keyless provider. * fix(credentials): reopen every keyless-capable reconnect on its stored auth mode and reject native credential tools without a policy - prepareWorkloadIdentity reports the reconnected credential's stored authType (reconnectAuthType), for an admin of a credential in the same workspace, whether or not this deployment can sign. reconnectsKeyless is removed from the contract and hook. The AWS, Databricks, Snowflake, Microsoft and Google dialogs reopen on that mode, so an assume_role, personal_access_token or certificate credential keeps its auth. - The saved-credential contract fails a native credential block whose tool has no oauth policy: the executor would never fill its token. - The Snowflake hint and docs say where to change SIM_WORKFLOWS; the DocuSign account_not_found message covers a credential with no Account ID; the docs baseline's reviewed CLI example entries carry their new byte length; the contract test fixtures use a real OAuth service id.
Uh oh!
There was an error while loading. Please reload this page.