can1357/oh-my-pi · error

Security scan authentication identity mismatch

Error message

Security scan authentication identity mismatch

What it means

assertSecurityIdentityMatches verifies that a resolved OAuth credential's identity (credentialId, accountId, email, organizationId, organizationName) matches the account reference supplied for a security scan. Any field present on both sides that disagrees causes a throw, preventing scans from running under a different identity than requested.

Source

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

export function assertSecurityIdentityMatches(
	account: SecurityAccountRef,
	resolution: {
		credentialId?: number;
		accountId?: string;
		email?: string;
		orgId?: string;
		orgName?: string;
	},
): void {
	if (
		account.credentialId !== resolution.credentialId ||
		(account.accountId !== undefined && account.accountId !== resolution.accountId) ||
		(account.email !== undefined && account.email !== resolution.email) ||
		(account.organizationId !== undefined && account.organizationId !== resolution.orgId) ||
		(account.organizationName !== undefined && account.organizationName !== resolution.orgName)
	) {
		throw new Error("Security scan authentication identity mismatch");
	}
}

export function selectSecurityAccount(
	authStorage: AuthStorage,
	provider: string,
	requestedCredentialId?: number,
	sessionId?: string,
): SecurityAccountRef {
	const accounts = authStorage.listOAuthAccounts(provider, sessionId);
	const selected =
		requestedCredentialId !== undefined
			? accounts.find(account => account.credentialId === requestedCredentialId)
			: (accounts.find(account => account.active) ?? (accounts.length === 1 ? accounts[0] : undefined));
	if (!selected) {
		if (accounts.length === 0) throw new Error(`Security scans require a stored OAuth account for ${provider}`);
		if (requestedCredentialId !== undefined) {
			throw new Error(`Security OAuth credential ${requestedCredentialId} is not available for ${provider}`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-select the account via selectSecurityAccount so the ref is derived from current auth-storage data
  2. Re-authenticate with the OAuth provider to refresh account metadata
  3. Update the caller to pass the correct credentialId/account identity

Example fix

// before
assertSecurityIdentityMatches({ credentialId: "old-cred", email: "a@x.com" }, resolution);
// after
const account = selectSecurityAccount(authStorage, provider, undefined, sessionId);
assertSecurityIdentityMatches(account, resolution);
Defensive patterns

Strategy: validation

Validate before calling

const accounts = authStorage.listOAuthAccounts(provider, sessionId);
const account = requestedCredentialId
  ? accounts.find(a => a.credentialId === requestedCredentialId)
  : accounts.find(a => a.active);
if (!account) throw new Error("no matching stored OAuth account for security scan");

Type guard

null

Try / catch

try {
  assertSecurityIdentityMatches(account, resolution);
} catch (err) {
  if (err instanceof Error && err.message === "Security scan authentication identity mismatch") {
    // refresh account ref from auth storage and re-authenticate
    account = selectSecurityAccount(authStorage, provider, undefined, sessionId);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the security-scan auth path with an account ref whose credentialId/accountId/email/org fields do not match what the auth storage resolution returns.

Common situations: Stale cached account metadata after re-authenticating with a different account; org name changed server-side; passing a credentialId belonging to another user/org.

Understand the failure class

Related errors


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