Skip to content

Commit bdbe302

Browse files
committed
test(service-automation): sealed-envelope pin no longer matches short fixture strings against random ciphertext
The pin asserted that the JSON-stringified envelope did not contain each plaintext fixture value; with the connector fixture 'crm', random base64url ciphertext contained it about once in 1,100 runs. Every value the pin looks for now carries a '.', which neither base64url nor the envelope's JSON frame emits, and the pin also asserts the stored envelope holds no '.' at all. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibyj2zTjgu4ZNg8WmHE
1 parent acd190b commit bdbe302

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

‎packages/services/service-automation/src/oauth2-grant/authorization.test.ts‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,30 @@ describe('ADR-0143 D5 — a begun connect is taken once', () => {
126126
});
127127

128128
describe('ADR-0143 D5 — a begun connect is held sealed (the KV trust boundary)', () => {
129-
const begun = pending({ verifier: 'dummy-verifier-7Qx', redirectUri: 'https://app.example.com/cb-sealed' });
129+
// Every plaintext value the pin below looks for carries a `.`, a character
130+
// neither base64url nor the envelope's JSON frame ever emits, so the random
131+
// `iv` / `ct` / `tag` can never contain one by chance: only a store that
132+
// writes the field itself turns the pin red. (A short value such as `crm`
133+
// turns up in random base64url about once in a thousand runs.)
134+
const begun = pending({
135+
connector: 'connector.sealed-fixture',
136+
organizationId: 'org.sealed-fixture',
137+
userId: 'usr.sealed-fixture',
138+
verifier: 'dummy-verifier.sealed-fixture',
139+
redirectUri: 'https://app.example.com/cb-sealed',
140+
});
141+
const sealedState = 'st.sealed-fixture';
130142
const keyOf = (state: string) => `connector-oauth2:pending:${createHash('sha256').update(state).digest('hex')}`;
131143

132144
it('the KV holds no verifier, user, organization, instance or redirect URI — only an envelope', async () => {
133145
const { kv, held } = fakeKv();
134-
await kvPendingAuthorizationStore(kv).put('st-sealed', begun);
146+
await kvPendingAuthorizationStore(kv).put(sealedState, begun);
135147
const [, entry] = [...held][0];
136148
const stored = JSON.stringify(entry.value);
137-
for (const plain of [begun.verifier, begun.userId, begun.organizationId, begun.connector, begun.redirectUri, 'st-sealed']) {
149+
const plains = [begun.verifier, begun.userId, begun.organizationId, begun.connector, begun.redirectUri, sealedState];
150+
for (const plain of plains) expect(plain).toContain('.');
151+
expect(stored).not.toContain('.');
152+
for (const plain of plains) {
138153
expect(stored).not.toContain(plain);
139154
}
140155
expect(Object.keys(entry.value as object).sort()).toEqual(['ct', 'iv', 'tag', 'v']);

0 commit comments

Comments
 (0)