fix(19): WR-05 add no-echo tests for admin create-member and me password hook sites
This commit is contained in:
@@ -1036,4 +1036,29 @@ describe('POST /api/admin/members', () => {
|
|||||||
expect(adminRow).toBeDefined();
|
expect(adminRow).toBeDefined();
|
||||||
expect(adminRow!.hasLocalCredential).toBe(false);
|
expect(adminRow!.hasLocalCredential).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('WR-05 (no-echo): malformed create-member body never echoes the submitted password or Zod received field', async () => {
|
||||||
|
const adminId = await seedUser('admin-create-noecho', true);
|
||||||
|
currentDevUserId = adminId;
|
||||||
|
const app = await getApp();
|
||||||
|
|
||||||
|
// initialPassword too short (< 8) → Zod rejects. The noEchoHook must return only
|
||||||
|
// { error: 'Invalid request' } and NEVER leak the submitted password or Zod's
|
||||||
|
// issues[].received field (T-19-06 / the T-19-14 leak this guards against).
|
||||||
|
const submittedPassword = 'shortpw-secret';
|
||||||
|
const res = await app.fetch(
|
||||||
|
jsonRequest('POST', '/api/admin/members', {
|
||||||
|
displayName: 'No Echo',
|
||||||
|
username: `noecho-${randomUUID()}`,
|
||||||
|
initialPassword: submittedPassword.slice(0, 3), // 3 chars — fails min(8)
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
const bodyText = await res.text();
|
||||||
|
expect(bodyText).not.toContain('received');
|
||||||
|
expect(bodyText).not.toContain('issues');
|
||||||
|
expect(bodyText).not.toContain(submittedPassword.slice(0, 3));
|
||||||
|
const parsed = JSON.parse(bodyText) as { error: string };
|
||||||
|
expect(parsed.error).toBe('Invalid request');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -403,6 +403,27 @@ describe('POST /api/me/password — self-change password (AUTH-LOCAL-09)', () =>
|
|||||||
|
|
||||||
expect(res.status).toBe(404);
|
expect(res.status).toBe(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Test 4 (WR-05 no-echo): malformed body never echoes the submitted password or Zod received field', async () => {
|
||||||
|
// newPassword too short (< 8) → Zod rejects via meNoEchoHook. The response must be
|
||||||
|
// ONLY { error: 'Invalid request' } and must NOT leak the submitted password or the
|
||||||
|
// Zod issues[].received field (T-19-06).
|
||||||
|
const { app } = await import('../../src/index.js');
|
||||||
|
const submitted = 'my-secret-current-pw';
|
||||||
|
const res = await app.request('/api/me/password', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ currentPassword: submitted, newPassword: 'short' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
const bodyText = await res.text();
|
||||||
|
expect(bodyText).not.toContain(submitted);
|
||||||
|
expect(bodyText).not.toContain('received');
|
||||||
|
expect(bodyText).not.toContain('issues');
|
||||||
|
const parsed = JSON.parse(bodyText) as { error: string };
|
||||||
|
expect(parsed.error).toBe('Invalid request');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user