can1357/oh-my-pi · error

Security scan authentication provider mismatch

Error message

Security scan authentication provider mismatch

What it means

createExactSecurityOAuthResolver() returns a getApiKey hook that throws immediately if the requested model's provider does not match the pinned SecurityAccountRef provider. It guarantees the security scan never uses credentials for one provider to authenticate requests against another.

Source

Thrown at packages/coding-agent/src/security/auth.ts:86

	assertSecurityIdentityMatches(account, resolution);
	if (!resolution.ok) throw new Error("The pinned security OAuth credential could not be resolved");
	return resolution;
}

/**
 * Build a request credential resolver pinned to one durable OAuth row.
 *
 * Initial resolution and refresh both target the same row. The auth driver's
 * final sibling-rotation step returns `undefined`, so an unavailable account
 * fails the scan rather than crossing an account/workspace boundary.
 */
export function createExactSecurityOAuthResolver(
	options: ExactSecurityOAuthOptions,
): NonNullable<AgentOptions["getApiKey"]> {
	const { account, authStorage } = options;
	return model => {
		if (model.provider !== account.provider) {
			throw new Error("Security scan authentication provider mismatch");
		}
		const resolver: ApiKeyResolver = async context => {
			if (context.lastChance) return undefined;
			const resolution = await resolveExactSecurityOAuthAccess(authStorage, account, {
				forceRefresh: context.error !== undefined,
				signal: context.signal,
			});
			return resolution.accessToken;
		};
		return resolver;
	};
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Make the scan session use a model whose provider matches account.provider
  2. Recreate the resolver with a SecurityAccountRef for the provider the model actually uses
  3. Fix the pinned account provider value (e.g. "openai-codex" vs "openai" mixups)

Example fix

// before
createExactSecurityOAuthResolver({ account: { provider: "openai-codex", credentialId }, authStorage })
// used with an anthropic model -> mismatch
// after
createExactSecurityOAuthResolver({ account: { provider: model.provider, credentialId }, authStorage })
Defensive patterns

Strategy: validation

Validate before calling

if (model.provider !== account.provider) {
  throw new Error(`Scan requires a ${account.provider} model, got ${model.provider}`);
}

Type guard

const matchesAccount = (model: { provider: string }, account: { provider: string }): boolean =>
  model.provider === account.provider;

Try / catch

try {
  await runScan(session);
} catch (err) {
  if (err.message === "Security scan authentication provider mismatch") {
    // rebuild resolver/agent with a model matching account.provider
  } else throw err;
}

Prevention

When it happens

Trigger: An agent run configured with an exact security OAuth resolver for provider X encounters a model whose provider is Y (e.g. pinned an openai-codex account but the run selects an anthropic model), so the model=>... guard throws.

Common situations: Model misconfiguration in the scan session (wrong default model/provider); multi-provider model lists where a non-pinned provider model gets picked; copy-pasting a resolver config across providers.

Understand the failure class

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b801a8de590a8eba. Report an issue: GitHub.