Skip to content

Commit

Permalink
Fix page tree node slug validation to prevent URL encoded characters (#…
Browse files Browse the repository at this point in the history
…2229)

Co-authored-by: Johannes Obermair <48853629+johnnyomair@users.noreply.github.com>
Co-authored-by: Daniel Karnutsch <dkarnutsch@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 15, 2025
1 parent 27d784a commit 64173b5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/blue-flies-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@comet/cms-admin": patch
"@comet/cms-api": patch
---

Fix page tree node slug validation to prevent URL encoded characters
2 changes: 1 addition & 1 deletion packages/admin/cms-admin/src/pages/createEditPageNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ const transformToSlug = (name: string, locale: string) => {
};

const isValidSlug = (value: string) => {
return /^([a-zA-Z0-9-._~]|%[0-9a-fA-F]{2})+$/.test(value);
return /^[a-zA-Z0-9][a-zA-Z0-9-_]*$/.test(value);
};

interface InitialValues {
Expand Down
28 changes: 28 additions & 0 deletions packages/api/cms-api/src/common/validators/is-slug.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ describe("IsSlug", () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("comet")).toBe(true);
});
it("should accept a valid slug with numbers", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("comet--2")).toBe(true);
});
it("should accept a valid slug with special char at the end", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("abc-")).toBe(true);
});
it("should accept a valid slug with uppercase characters", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("Comet")).toBe(true);
});
it("should not accept space", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("com et")).toBe(false);
Expand All @@ -14,5 +26,21 @@ describe("IsSlug", () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("comät")).toBe(false);
});
it("should not allow url encoded characters", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("slug%2F2")).toBeFalsy();
});
it("should not allow percent encoded special characters ../", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("%2E%2E%2Ftest")).toBeFalsy();
});
it("should not allow special characters ../", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("../test")).toBeFalsy();
});
it("should not allow special character / ", async () => {
const validator = new IsSlugConstraint();
expect(await validator.validate("slug/")).toBeFalsy();
});
});
});
4 changes: 2 additions & 2 deletions packages/api/cms-api/src/common/validators/is-slug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export const IsSlug = (validationOptions?: ValidationOptions) => {
@ValidatorConstraint({ name: "IsSlug", async: true })
export class IsSlugConstraint implements ValidatorConstraintInterface {
async validate(value: string): Promise<boolean> {
// Regex matches unreserved characters and percent encoding (see https://tools.ietf.org/html/rfc3986#section-2.1)
return /^([a-zA-Z0-9-._~]|%[0-9a-fA-F]{2})+$/.test(value);
// Regex matches unreserved characters
return /^[a-zA-Z0-9][a-zA-Z0-9-_]*$/.test(value);
}

defaultMessage(): string {
Expand Down

0 comments on commit 64173b5

Please sign in to comment.