Skip to main content

OAuth scope and third-party integrations

Every Connected App, OAuth scope, and named-credential callout is a door into the org for a third party. Vulkro inspects the OAuth scope grants on Connected Apps, the principal that backs each integration, and the data that flows out through named-credential callouts, then flags the configurations that hand a third party more reach than it needs.

The unifying principle is least privilege at the integration boundary: a scope grant should be as narrow as the integration's job, gated by an admin approval step, and tied to a principal whose blast radius is bounded.

SF-OAUTH-SCOPE-001: over-broad scope with no IP constraint

Triggers when a Connected App requests the full, refresh_token, or api OAuth scope and has no IP relaxation constraint (no IP allowlist or login-IP range bounding where the token can be used).

Why it matters: the full scope grants the integration everything the authorizing user can do, and refresh_token lets it keep that access indefinitely without a fresh login. With no IP constraint, a stolen token works from anywhere on the internet.

How to fix: replace full with the narrowest scope set the integration actually needs, and bind the Connected App to an IP allowlist so tokens only work from the integration's known egress addresses.

SF-OAUTH-SCOPE-002: named-credential callout forwarding request-tainted data

Triggers when a callout through a Named Credential forwards data that originates from an inbound request (request parameters, inbound REST body, or other caller-controlled input) into the outbound call to the external provider.

Why it matters: forwarding request-tainted data to a third party can leak internal identifiers or sensitive values to an external system, and in the worst case lets a caller steer the outbound request (server-side request forgery shape) by controlling what the integration sends.

How to fix: validate and allowlist the values that flow into the callout. Never pass raw caller-controlled input straight into the outbound request path; map it to a known-safe set of values first.

SF-OAUTH-SCOPE-003: refresh_token to an unverified provider

Triggers when a Connected App or OAuth flow grants refresh_token to a provider whose identity is not verified (no pinned, trusted endpoint or verified publisher for the destination).

Why it matters: a refresh token is a long-lived credential. Handing one to a provider you cannot positively identify means a long-lived grant to an endpoint that could be swapped or impersonated.

How to fix: drop refresh_token unless the integration genuinely needs offline access, and only grant it to a provider whose endpoint is pinned and verified. Prefer short-lived access tokens where the integration can re-authenticate.

SF-OAUTH-SCOPE-004: broad Connected App scope with no admin gate

Triggers when a Connected App carries a broad scope (for example full or api) but its authorization policy allows self-authorization rather than requiring admin pre-approval.

Why it matters: without an admin gate, any user can authorize the app and grant it the broad scope under their own access. That bypasses the review step where an administrator would otherwise catch an over-privileged integration.

How to fix: set the Connected App to require admin-approved users, so a human reviews and assigns the integration before it can act on anyone's behalf.

SF-OAUTH-SCOPE-005: broad scope under a shared principal

Triggers when a broad OAuth scope is granted to an integration that runs under a shared or generic principal (a single integration user that many callers or systems authenticate through) rather than a dedicated, narrowly scoped identity.

Why it matters: a shared principal collapses the audit trail and widens the blast radius. A broad scope on that one identity becomes a broad scope for every system funneled through it, and a single compromise exposes all of them.

How to fix: give each integration its own dedicated principal with the minimum scope it needs, so access and audit are isolated per integration.

SF-OAUTH-SCOPE-006: rollup

SF-OAUTH-SCOPE-006 is the rollup finding for the OAuth-scope surface. It aggregates the individual scope and integration findings above into a single summary entry so a reviewer can see the overall OAuth posture of the project at a glance before drilling into each specific finding.

Why it matters: integration risk is cumulative. A project with several moderately broad grants can carry more aggregate exposure than one with a single loud finding, and the rollup makes that total visible.

How to read it: use the rollup as the headline for the OAuth-integration section of a review, then work through the underlying SF-OAUTH-SCOPE-001 through -005 findings it references to remediate each contributing issue.