Skip to content

Commit 9075a3c

Browse files
committed
fix(aws): add validateAwsRegion to all AWS route schemas to prevent SSRF
1 parent 34cfc26 commit 9075a3c

61 files changed

Lines changed: 488 additions & 61 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/sim/app/api/tools/cloudwatch/describe-alarms/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@ import { toError } from '@sim/utils/errors'
99
import { type NextRequest, NextResponse } from 'next/server'
1010
import { z } from 'zod'
1111
import { checkInternalAuth } from '@/lib/auth/hybrid'
12+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
1213
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1314

1415
const logger = createLogger('CloudWatchDescribeAlarms')
1516

1617
const DescribeAlarmsSchema = z.object({
17-
region: z.string().min(1, 'AWS region is required'),
18+
region: z
19+
.string()
20+
.min(1, 'AWS region is required')
21+
.refine(
22+
(v) => validateAwsRegion(v).isValid,
23+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
24+
),
1825
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1926
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
2027
alarmNamePrefix: z.string().optional(),

apps/sim/app/api/tools/cloudwatch/describe-log-groups/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@ import { toError } from '@sim/utils/errors'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { z } from 'zod'
66
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
7+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
78
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
89
import { createCloudWatchLogsClient } from '@/app/api/tools/cloudwatch/utils'
910

1011
const logger = createLogger('CloudWatchDescribeLogGroups')
1112

1213
const DescribeLogGroupsSchema = z.object({
13-
region: z.string().min(1, 'AWS region is required'),
14+
region: z
15+
.string()
16+
.min(1, 'AWS region is required')
17+
.refine(
18+
(v) => validateAwsRegion(v).isValid,
19+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
20+
),
1421
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1522
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1623
prefix: z.string().optional(),

apps/sim/app/api/tools/cloudwatch/describe-log-streams/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { toError } from '@sim/utils/errors'
33
import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
6+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
78
import { createCloudWatchLogsClient, describeLogStreams } from '@/app/api/tools/cloudwatch/utils'
89

910
const logger = createLogger('CloudWatchDescribeLogStreams')
1011

1112
const DescribeLogStreamsSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
logGroupName: z.string().min(1, 'Log group name is required'),

apps/sim/app/api/tools/cloudwatch/get-log-events/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { toError } from '@sim/utils/errors'
33
import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { checkInternalAuth } from '@/lib/auth/hybrid'
6+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
78
import { createCloudWatchLogsClient, getLogEvents } from '@/app/api/tools/cloudwatch/utils'
89

910
const logger = createLogger('CloudWatchGetLogEvents')
1011

1112
const GetLogEventsSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
logGroupName: z.string().min(1, 'Log group name is required'),

apps/sim/app/api/tools/cloudwatch/get-metric-statistics/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@ import { toError } from '@sim/utils/errors'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { z } from 'zod'
66
import { checkInternalAuth } from '@/lib/auth/hybrid'
7+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
78
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
89

910
const logger = createLogger('CloudWatchGetMetricStatistics')
1011

1112
const GetMetricStatisticsSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
namespace: z.string().min(1, 'Namespace is required'),

apps/sim/app/api/tools/cloudwatch/list-metrics/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@ import { toError } from '@sim/utils/errors'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { z } from 'zod'
66
import { checkInternalAuth } from '@/lib/auth/hybrid'
7+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
78
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
89

910
const logger = createLogger('CloudWatchListMetrics')
1011

1112
const ListMetricsSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
namespace: z.string().optional(),

apps/sim/app/api/tools/cloudwatch/put-metric-data/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { toError } from '@sim/utils/errors'
88
import { type NextRequest, NextResponse } from 'next/server'
99
import { z } from 'zod'
1010
import { checkInternalAuth } from '@/lib/auth/hybrid'
11+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
1112
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1213

1314
const logger = createLogger('CloudWatchPutMetricData')
@@ -43,7 +44,13 @@ const VALID_UNITS = [
4344
] as const
4445

4546
const PutMetricDataSchema = z.object({
46-
region: z.string().min(1, 'AWS region is required'),
47+
region: z
48+
.string()
49+
.min(1, 'AWS region is required')
50+
.refine(
51+
(v) => validateAwsRegion(v).isValid,
52+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
53+
),
4754
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
4855
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
4956
namespace: z.string().min(1, 'Namespace is required'),

apps/sim/app/api/tools/cloudwatch/query-logs/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@ import { toError } from '@sim/utils/errors'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { z } from 'zod'
66
import { checkInternalAuth } from '@/lib/auth/hybrid'
7+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
78
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
89
import { createCloudWatchLogsClient, pollQueryResults } from '@/app/api/tools/cloudwatch/utils'
910

1011
const logger = createLogger('CloudWatchQueryLogs')
1112

1213
const QueryLogsSchema = z.object({
13-
region: z.string().min(1, 'AWS region is required'),
14+
region: z
15+
.string()
16+
.min(1, 'AWS region is required')
17+
.refine(
18+
(v) => validateAwsRegion(v).isValid,
19+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
20+
),
1421
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1522
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1623
logGroupNames: z.array(z.string().min(1)).min(1, 'At least one log group name is required'),

apps/sim/app/api/tools/dynamodb/delete/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { toError } from '@sim/utils/errors'
33
import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { checkInternalAuth } from '@/lib/auth/hybrid'
6+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
78
import { createDynamoDBClient, deleteItem } from '@/app/api/tools/dynamodb/utils'
89

910
const logger = createLogger('DynamoDBDeleteAPI')
1011

1112
const DeleteSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
tableName: z.string().min(1, 'Table name is required'),

apps/sim/app/api/tools/dynamodb/get/route.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { toError } from '@sim/utils/errors'
33
import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { checkInternalAuth } from '@/lib/auth/hybrid'
6+
import { validateAwsRegion } from '@/lib/core/security/input-validation'
67
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
78
import { createDynamoDBClient, getItem } from '@/app/api/tools/dynamodb/utils'
89

910
const logger = createLogger('DynamoDBGetAPI')
1011

1112
const GetSchema = z.object({
12-
region: z.string().min(1, 'AWS region is required'),
13+
region: z
14+
.string()
15+
.min(1, 'AWS region is required')
16+
.refine(
17+
(v) => validateAwsRegion(v).isValid,
18+
(v) => validateAwsRegion(v).error ?? 'Invalid AWS region'
19+
),
1320
accessKeyId: z.string().min(1, 'AWS access key ID is required'),
1421
secretAccessKey: z.string().min(1, 'AWS secret access key is required'),
1522
tableName: z.string().min(1, 'Table name is required'),

0 commit comments

Comments
 (0)