make the notify identity rule testable, and fix what the test found
Extracting resolveNotifyUser into its own module immediately caught a hole in the fix from the previous commit: a header that was present but unparseable fell through to the body, so a browser could send junk in the header, name any user in the body and win. PRESENCE of X-Officer-User is the signal, not its validity — a malformed header means a proxied request went wrong, and falling through hands the decision back to the caller we just declined to trust. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import { resolveNotifyUser } from './resolve-user';
|
||||
|
||||
describe('resolveNotifyUser', () => {
|
||||
test('a loopback producer with no header is trusted with the body', () => {
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: 13 })).toBe(13);
|
||||
});
|
||||
|
||||
test('a proxied request uses the header the platform injected', () => {
|
||||
expect(resolveNotifyUser({ header: '1', bodyUserId: undefined })).toBe(1);
|
||||
});
|
||||
|
||||
// The regression this module exists for: `body.userId ?? header` let any account holding the
|
||||
// `notify` capability push to any other account's devices by naming them in a JSON body.
|
||||
test('the header beats a conflicting body userId', () => {
|
||||
expect(resolveNotifyUser({ header: '13', bodyUserId: 1 })).toBe(13);
|
||||
expect(resolveNotifyUser({ header: '1', bodyUserId: 13 })).toBe(1);
|
||||
});
|
||||
|
||||
test('neither claimant supplying an id is a 400, not a default', () => {
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: undefined })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: '', bodyUserId: null })).toBeNull();
|
||||
});
|
||||
|
||||
test('a malformed header does not silently fall through to the body', () => {
|
||||
// Otherwise a browser could send a junk header alongside a chosen body id and win.
|
||||
expect(resolveNotifyUser({ header: 'abc', bodyUserId: 13 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: '0', bodyUserId: 13 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: '-1', bodyUserId: 13 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: '1.5', bodyUserId: 13 })).toBeNull();
|
||||
});
|
||||
|
||||
test('a body userId that is not a positive integer is refused', () => {
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: '13' })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: 0 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: -3 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: 2.5 })).toBeNull();
|
||||
expect(resolveNotifyUser({ header: null, bodyUserId: { id: 1 } })).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user