Skip to content

Commit 467ee97

Browse files
authored
Merge pull request #953 from Dstack-TEE/codex/fix-kms-auth-boot-schema
[STACKED on #941] fix(kms): bound the authorization boot schema
2 parents 8dfbdb0 + e538613 commit 467ee97

2 files changed

Lines changed: 34 additions & 12 deletions

File tree

dstack/kms/auth-eth-bun/index.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,21 @@ describe('API Compatibility Tests', () => {
197197

198198
expect(response.status).toBe(400);
199199
});
200-
});
200+
201+
202+
it('should reject oversized and non-hex measurements before backend use', async () => {
203+
for (const mrAggregated of ['0x' + 'ab'.repeat(33), 'not-hex']) {
204+
const response = await appFetch(new Request('http://localhost:3001/bootAuth/app', {
205+
method: 'POST',
206+
headers: { 'Content-Type': 'application/json' },
207+
body: JSON.stringify({ ...validBootInfo, mrAggregated }),
208+
}));
209+
210+
expect(response.status).toBe(400);
211+
}
212+
expect(mockReadContract).not.toHaveBeenCalled();
213+
});
214+
});
201215

202216
describe('POST /bootAuth/kms', () => {
203217
const validBootInfo = {

dstack/kms/auth-eth-bun/index.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,26 @@ import { z } from 'zod';
88
import { createPublicClient, http, type Address, type Hex } from 'viem';
99

1010
// zod schemas for validation - compatible with original fastify implementation
11+
const boundedHex = (bytes: number, description: string) =>
12+
z.string()
13+
.regex(/^(?:0x)?[0-9a-fA-F]*$/, `${description} must be hexadecimal`)
14+
.refine(
15+
(value) => value.replace(/^0x/, '').length <= bytes * 2,
16+
`${description} exceeds ${bytes} bytes`,
17+
);
18+
1119
const BootInfoSchema = z.object({
12-
// required fields (matching original fastify schema)
13-
mrAggregated: z.string().describe('aggregated MR measurement'),
14-
osImageHash: z.string().describe('OS Image hash'),
15-
appId: z.string().describe('application ID'),
16-
composeHash: z.string().describe('compose hash'),
17-
instanceId: z.string().describe('instance ID'),
18-
deviceId: z.string().describe('device ID'),
19-
// optional fields (for full compatibility with BootInfo interface)
20-
tcbStatus: z.string().optional().default(''),
21-
advisoryIds: z.array(z.string()).optional().default([]),
22-
mrSystem: z.string().optional().default('')
20+
// Short hexadecimal values remain compatible with the original backend,
21+
// which left-pads them before making the contract call.
22+
mrAggregated: boundedHex(32, 'aggregated MR measurement'),
23+
osImageHash: boundedHex(32, 'OS Image hash'),
24+
appId: boundedHex(20, 'application ID'),
25+
composeHash: boundedHex(32, 'compose hash'),
26+
instanceId: boundedHex(20, 'instance ID'),
27+
deviceId: boundedHex(32, 'device ID'),
28+
tcbStatus: z.string().max(128).optional().default(''),
29+
advisoryIds: z.array(z.string().max(256)).max(128).optional().default([]),
30+
mrSystem: boundedHex(32, 'system MR measurement').optional().default('')
2331
});
2432

2533
const BootResponseSchema = z.object({

0 commit comments

Comments
 (0)