Skip to content

Commit f44c4b0

Browse files
David RuzickaAgent
andcommitted
test(profile-index): add regression tests for no-auth proxy profiles
Verify that upstream_mcp proxy profiles without interceptors.auth are presented with authTabs=[{key:'none'}] and never leak an OAuth or bearer auth tab from upstream_mcp.auth env vars. Co-authored-by: Agent <noreply@agent>
1 parent 5ffcd83 commit f44c4b0

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

src/profile/profile-resolver.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,27 @@ describe('profile-resolver', () => {
193193
expect(profiles[0].envVars).toContain('LEGACY_UPSTREAM_TOKEN');
194194
});
195195

196+
it('reports authMethods=[] and envVars=[] for upstream_mcp proxy with no auth anywhere', async () => {
197+
const root = await createTempDir();
198+
const profilesDir = path.join(root, 'profiles');
199+
200+
await writeJson(path.join(profilesDir, 'no-auth-proxy.json'), {
201+
profile_name: 'seznam-scif',
202+
profile_id: 'seznam-scif',
203+
tools: [],
204+
upstream_mcp: {
205+
name: 'scif',
206+
transport: { type: 'http-streamable', url: 'https://scif.example.com/mcp' },
207+
},
208+
});
209+
210+
const profiles = await listProfilesDetailed(profilesDir);
211+
expect(profiles).toHaveLength(1);
212+
expect(profiles[0].authMethods).toEqual([]);
213+
expect(profiles[0].envVars).toEqual([]);
214+
expect(profiles[0].oauthEnvVars).toEqual([]);
215+
});
216+
196217
it('returns specPath=undefined for upstream_mcp proxy profile with no openapi_spec_path', async () => {
197218
const root = await createTempDir();
198219
const profilesDir = path.join(root, 'profiles');

src/transport/profile-index.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ describe('profile index helpers', () => {
429429
{ key: 'local', label: 'Local stdio' },
430430
]);
431431
expect(profile.authTabs[0].label).toBe('Session cookie');
432+
expect(profile.authTabs.every(t => t.key !== 'oauth')).toBe(true);
432433
expect(profile.snippets.find(s => s.key === 'vscode-session-cookie')).toBeUndefined();
433434
expect(profile.snippets.find(s => s.key === 'cursor-session-cookie')).toBeUndefined();
434435

@@ -447,6 +448,68 @@ describe('profile index helpers', () => {
447448
expect(codexLocalToml?.content).toContain('N8N_NODES_BASE_URL = "https://admin.isatky.cz"');
448449
});
449450

451+
it('emits authTabs=[none] for proxy profile with no interceptors.auth (regression: no OAuth leak)', () => {
452+
const profiles: ListedProfileDetails[] = [
453+
{
454+
profileId: 'seznam-scif',
455+
profileName: 'seznam-scif',
456+
profileAliases: [],
457+
description: 'MCP proxy profile for Seznam SCIF',
458+
envVars: [],
459+
authMethods: [],
460+
},
461+
];
462+
463+
const { payload } = buildProfileIndexPayload(profiles, 'https://mcp.example.com', 'en');
464+
const [profile] = payload.profiles;
465+
expect(profile.authTabs).toHaveLength(1);
466+
expect(profile.authTabs[0].key).toBe('none');
467+
expect(profile.authTabs[0].label).toBe('No auth');
468+
expect(profile.authTabs.every(t => t.key !== 'oauth')).toBe(true);
469+
});
470+
471+
it('emits authTabs=[none] with Czech label for no-auth proxy profile', () => {
472+
const profiles: ListedProfileDetails[] = [
473+
{
474+
profileId: 'seznam-ai-adoption',
475+
profileName: 'seznam-ai-adoption',
476+
profileAliases: [],
477+
description: 'MCP proxy profile for Seznam AI Adoption',
478+
envVars: [],
479+
authMethods: [],
480+
},
481+
];
482+
483+
const { payload } = buildProfileIndexPayload(profiles, 'https://mcp.example.com', 'cs');
484+
const [profile] = payload.profiles;
485+
expect(profile.authTabs).toHaveLength(1);
486+
expect(profile.authTabs[0].key).toBe('none');
487+
expect(profile.authTabs[0].label).toBe('Bez autentizace');
488+
expect(profile.authTabs.every(t => t.key !== 'oauth')).toBe(true);
489+
});
490+
491+
it('does not include oauth authTab even when upstream_mcp env vars are present', () => {
492+
// Regression: upstream_mcp.auth env vars appear in profile.envVars but must NOT
493+
// create an oauth auth tab — authMethods reflects only interceptors.auth.
494+
const profiles: ListedProfileDetails[] = [
495+
{
496+
profileId: 'proxy-with-upstream-auth',
497+
profileName: 'proxy-with-upstream-auth',
498+
profileAliases: [],
499+
description: 'Proxy with server-to-server upstream auth',
500+
envVars: ['UPSTREAM_TOKEN'],
501+
authMethods: [],
502+
},
503+
];
504+
505+
const { payload } = buildProfileIndexPayload(profiles, 'https://mcp.example.com', 'en');
506+
const [profile] = payload.profiles;
507+
expect(profile.authTabs).toHaveLength(1);
508+
expect(profile.authTabs[0].key).toBe('none');
509+
expect(profile.authTabs.every(t => t.key !== 'oauth')).toBe(true);
510+
expect(profile.authTabs.every(t => t.key !== 'bearer')).toBe(true);
511+
});
512+
450513
it('renders template placeholders', () => {
451514
const profiles: ListedProfileDetails[] = [
452515
{

0 commit comments

Comments
 (0)