Skip to content

Commit 547ba2d

Browse files
committed
feat(validation): enhance registry URL validation in schema
- Introduced a new validation schema for registry URLs, ensuring they conform to a specific format (hostname[:port]) and disallow shell metacharacters. - Updated the `createSchema`, `apiCreateRegistry`, and `apiTestRegistry` functions to utilize the new registry URL validation. - Improved security and input integrity for registry URL fields. - Updated the `removeRegistry` function to escape the registry URL during logout to prevent command injection vulnerabilities.
1 parent b9e97eb commit 547ba2d

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

packages/server/src/db/schema/registry.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,22 @@ export const registryRelations = relations(registry, ({ many }) => ({
4444
}),
4545
}));
4646

47+
// Registry URLs must be hostname[:port] only — no shell metacharacters
48+
// Empty string is allowed (means default/Docker Hub registry)
49+
const registryUrlSchema = z
50+
.string()
51+
.refine(
52+
(val) =>
53+
val === "" ||
54+
/^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?(:\d{1,5})?$/.test(val),
55+
"Registry URL must be a valid hostname or hostname:port (e.g. registry.example.com or localhost:5000)",
56+
);
57+
4758
const createSchema = createInsertSchema(registry, {
4859
registryName: z.string().min(1),
4960
username: z.string().min(1),
5061
password: z.string().min(1),
51-
registryUrl: z.string(),
62+
registryUrl: registryUrlSchema,
5263
organizationId: z.string().min(1),
5364
registryId: z.string().min(1),
5465
registryType: z.enum(["cloud"]),
@@ -61,7 +72,7 @@ export const apiCreateRegistry = createSchema
6172
registryName: z.string().min(1),
6273
username: z.string().min(1),
6374
password: z.string().min(1),
64-
registryUrl: z.string(),
75+
registryUrl: registryUrlSchema,
6576
registryType: z.enum(["cloud"]),
6677
imagePrefix: z.string().nullable().optional(),
6778
})
@@ -74,7 +85,7 @@ export const apiTestRegistry = createSchema.pick({}).extend({
7485
registryName: z.string().optional(),
7586
username: z.string().min(1),
7687
password: z.string().min(1),
77-
registryUrl: z.string(),
88+
registryUrl: registryUrlSchema,
7889
registryType: z.enum(["cloud"]),
7990
imagePrefix: z.string().nullable().optional(),
8091
serverId: z.string().optional(),

packages/server/src/services/registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export const removeRegistry = async (registryId: string) => {
8585
}
8686

8787
if (!IS_CLOUD) {
88-
await execAsync(`docker logout ${response.registryUrl}`);
88+
await execAsync(`docker logout ${shEscape(response.registryUrl)}`);
8989
}
9090

9191
return response;

0 commit comments

Comments
 (0)