Joshen/depr 253 tighten field validation for bucket name and table name (#40739)

* Update validation for analytics bucket name

* Update comment

* Update bucket name validation for vector buckets
This commit is contained in:
Joshen Lim authored and GitHub committed 2025-11-25 12:34:07 +08:00
1 parent 25cd2af2a5
commit 31a026e6f0
4 files changed
+104 -13

No files matched your search

@@ -38,17 +38,21 @@ import {
} from 'ui'
import { Admonition } from 'ui-patterns'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { inverseValidBucketNameRegex, validBucketNameRegex } from '../CreateBucketModal.utils'
import { BUCKET_TYPES } from '../Storage.constants'
import { useIcebergWrapperExtension } from './AnalyticsBucketDetails/useIcebergWrapper'
import {
reservedPrefixes,
reservedSuffixes,
validBucketNameRegex,
} from './CreateAnalyticsBucketModal.utils'
const FormSchema = z
.object({
name: z
.string()
.trim()
.min(1, 'Please provide a name for your bucket')
.max(100, 'Bucket name should be below 100 characters')
.min(3, 'Bucket name should be at least 3 characters')
.max(63, 'Bucket name should be up to 63 characters')
.refine(
(value) => !value.endsWith(' '),
'The name of the bucket cannot end with a whitespace'
@@ -59,9 +63,51 @@ const FormSchema = z
),
})
.superRefine((data, ctx) => {
if (reservedPrefixes.test(data.name)) {
const [match] = data.name.match(reservedPrefixes) ?? []
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: `Bucket name cannot start with "${match}"`,
})
}
if (reservedSuffixes.test(data.name)) {
const [match] = data.name.match(reservedSuffixes) ?? []
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: `Bucket name cannot end with "${match}"`,
})
}
if (/[A-Z]/.test(data.name)) {
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: 'Bucket name can only be lowercase characters',
})
}
if (!validBucketNameRegex.test(data.name)) {
const [match] = data.name.match(inverseValidBucketNameRegex) ?? []
ctx.addIssue({
if (!/^[a-z0-9]/.test(data.name)) {
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: 'Bucket name must start with a lowercase letter or number.',
})
}
if (!/[a-z0-9]$/.test(data.name)) {
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: 'Bucket name must end with a lowercase letter or number.',
})
}
const [match] = data.name.match(/[^a-z0-9-]/) ?? []
return ctx.addIssue({
path: ['name'],
code: z.ZodIssueCode.custom,
message: !!match
@@ -238,7 +284,7 @@ export const CreateAnalyticsBucketModal = ({
name="name"
label="Bucket name"
labelOptional="Cannot be changed after creation"
description="Must be between 3–63 characters. Only lowercase letters, numbers, dots, and hyphens are allowed."
description="Must be between 3–63 characters. Only lowercase letters, numbers, and hyphens are allowed."
>
<FormControl_Shadcn_>
<Input_Shadcn_
@@ -0,0 +1,14 @@
/**
* Rules: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-buckets-naming.html?i
* Bucket names must be between 3 and 63 characters long.
* Bucket names can consist only of lowercase letters, numbers, and hyphens (-).
* Bucket names must begin and end with a letter or number.
* Bucket names must not contain any underscores (_) or periods (.).
* Bucket names must not start with any of the following reserved prefixes: 
xn--, sthree-, amzn-s3-demo-, aws
* Bucket names must not end with any of the following reserved suffixes:
-s3alias, --ol-s3, --x-s3, --table-s3
*/
export const reservedPrefixes = /^(?:xn--|sthree-|amzn-s3-demo-|aws)/
export const reservedSuffixes = /(?:-s3alias|--ol-s3|--x-s3|--table-s3)$/
export const validBucketNameRegex = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/
@@ -1,11 +1,11 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Plus } from 'lucide-react'
import { parseAsBoolean, useQueryState } from 'nuqs'
import { useEffect, useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
import z from 'zod'
import { parseAsBoolean, useQueryState } from 'nuqs'
import { useParams } from 'common'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
@@ -36,7 +36,7 @@ import {
} from 'ui'
import { Admonition } from 'ui-patterns/admonition'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { inverseValidBucketNameRegex, validBucketNameRegex } from '../CreateBucketModal.utils'
import { validVectorBucketName } from './CreateVectorBucketDialog.utils'
import { useS3VectorsWrapperExtension } from './useS3VectorsWrapper'
import { getVectorBucketFDWSchemaName } from './VectorBuckets.utils'
@@ -44,12 +44,36 @@ const FormSchema = z.object({
name: z
.string()
.trim()
.min(1, 'Please provide a name for your bucket')
.max(100, 'Bucket name should be below 100 characters')
.min(3, 'Bucket name should be at least 3 characters')
.max(63, 'Bucket name should be up to 63 characters')
.superRefine((name, ctx) => {
if (!validBucketNameRegex.test(name)) {
const [match] = name.match(inverseValidBucketNameRegex) ?? []
ctx.addIssue({
if (!validVectorBucketName.test(name)) {
if (/[A-Z]/.test(name)) {
return ctx.addIssue({
path: [],
code: z.ZodIssueCode.custom,
message: 'Bucket name can only be lowercase characters',
})
}
if (!/^[a-z0-9]/.test(name)) {
return ctx.addIssue({
path: [],
code: z.ZodIssueCode.custom,
message: 'Bucket name must start with a lowercase letter or number.',
})
}
if (!/[a-z0-9]$/.test(name)) {
return ctx.addIssue({
path: [],
code: z.ZodIssueCode.custom,
message: 'Bucket name must end with a lowercase letter or number.',
})
}
const [match] = name.match(/[^a-z0-9-]/) ?? []
return ctx.addIssue({
path: [],
code: z.ZodIssueCode.custom,
message: !!match
@@ -0,0 +1,7 @@
/**
* Rules: https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-buckets-naming.html?icmpid=docs_amazons3_console
* Vector bucket names must be between 3 and 63 characters long.
* Vector bucket names can consist only of lowercase letters (a-z), numbers (0-9), and hyphens (-).
* Vector bucket names must begin and end with a letter or number.
*/
export const validVectorBucketName = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/