Skip to content

Commit d6f01fe

Browse files
committed
fix(lambda): match twelve digits in the layer ARN pattern
The account-ID segment was written as `\d{12}` inside a template literal, so the emitted regex carried a literal `d{12}` and rejected every real layer ARN. The existing test only covered an over-long name, which is why it passed. Escapes the backslash and adds the coverage that would have caught it: a real layer ARN and a bare layer name are both accepted, and an ARN whose account segment is not twelve digits is rejected.
1 parent 12ec194 commit d6f01fe

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

apps/sim/lib/api/contracts/tools/aws/lambda-get-layer-version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const GetLayerVersionSchema = z.object({
1717
.min(1, 'layerName is required')
1818
.max(140, 'layerName cannot exceed 140 characters')
1919
.regex(
20-
/^(arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:d{12}:layer:[a-zA-Z0-9-_]+)$|^[a-zA-Z0-9-_]+$/,
20+
/^(arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-_]+)$|^[a-zA-Z0-9-_]+$/,
2121
'layerName must be a layer name or a layer ARN'
2222
),
2323
versionNumber: z.number().int().min(1, 'versionNumber must be at least 1'),

apps/sim/lib/api/contracts/tools/aws/lambda-list-layer-versions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const ListLayerVersionsSchema = z.object({
1919
.min(1, 'layerName is required')
2020
.max(140, 'layerName cannot exceed 140 characters')
2121
.regex(
22-
/^(arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:d{12}:layer:[a-zA-Z0-9-_]+)$|^[a-zA-Z0-9-_]+$/,
22+
/^(arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-_]+)$|^[a-zA-Z0-9-_]+$/,
2323
'layerName must be a layer name or a layer ARN'
2424
),
2525
compatibleRuntime: z.string().optional(),

apps/sim/lib/internal/lambda/execute-tool.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,42 @@ describe('executeLambdaTool', () => {
605605
expect(long.status).toBe(400)
606606
})
607607

608+
it('accepts a layer ARN as well as a bare layer name', async () => {
609+
mockOperations.executeLambdaListLayerVersions.mockResolvedValue({ success: true, output: {} })
610+
mockOperations.executeLambdaGetLayerVersion.mockResolvedValue({ success: true, output: {} })
611+
612+
const arn = await executeLambdaTool(
613+
createRequest({
614+
toolId: 'lambda_list_layer_versions',
615+
input: {
616+
...CONNECTION,
617+
layerName: 'arn:aws:lambda:us-east-1:123456789012:layer:my-layer',
618+
},
619+
})
620+
)
621+
const bare = await executeLambdaTool(
622+
createRequest({
623+
toolId: 'lambda_get_layer_version',
624+
input: { ...CONNECTION, layerName: 'my-layer', versionNumber: 1 },
625+
})
626+
)
627+
628+
expect(arn.status).toBe(200)
629+
expect(bare.status).toBe(200)
630+
})
631+
632+
it('rejects a layer ARN whose account segment is not twelve digits', async () => {
633+
const response = await executeLambdaTool(
634+
createRequest({
635+
toolId: 'lambda_list_layer_versions',
636+
input: { ...CONNECTION, layerName: 'arn:aws:lambda:us-east-1:notanaccount:layer:my-layer' },
637+
})
638+
)
639+
640+
expect(response.status).toBe(400)
641+
expect(mockOperations.executeLambdaListLayerVersions).not.toHaveBeenCalled()
642+
})
643+
608644
it('rejects a layer name longer than the documented maximum', async () => {
609645
const response = await executeLambdaTool(
610646
createRequest({

0 commit comments

Comments
 (0)