Skip to content

Commit d6648d7

Browse files
authored
fix(cli): escape backslashes in inspect schema patterns (#5568)
## Summary Escapes backslashes when building SQL LIKE patterns for legacy `inspect db` internal schema filters. ## Context Code scanning flagged the previous sanitizer because it escaped underscores without escaping existing backslashes, which could let a backslash alter the meaning of the following pattern character. ## Impact Backslash-containing schema names now produce literal LIKE patterns while existing internal schema wildcard behavior stays unchanged.
1 parent 055065d commit d6648d7

2 files changed

Lines changed: 28 additions & 11 deletions

File tree

apps/cli/src/legacy/commands/inspect/db/legacy-inspect-schemas.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
* Internal Postgres schemas the `inspect db` queries exclude, and the LIKE-escape
33
* helper that turns them into `LIKE ANY($1)` exclusion patterns.
44
*
5-
* 1:1 port of Go's `utils.InternalSchemas` (`apps/cli-go/pkg/migration/dump.go:21-53`)
6-
* and `reset.LikeEscapeSchema` (`apps/cli-go/internal/db/reset/reset.go:259-266`).
7-
* The order is preserved verbatim because the escaped array is passed straight
8-
* through to `LIKE ANY($1)`, where order is observable in nothing but is kept
9-
* identical to avoid any drift from the Go source.
5+
* The schema list is a 1:1 port of Go's `utils.InternalSchemas`
6+
* (`apps/cli-go/pkg/migration/dump.go:21-53`). The order is preserved verbatim
7+
* because the escaped array is passed straight through to `LIKE ANY($1)`, where
8+
* order is observable in nothing but is kept identical to avoid any drift from
9+
* the Go source.
1010
*/
1111
export const LEGACY_INTERNAL_SCHEMAS: ReadonlyArray<string> = [
1212
"information_schema",
@@ -43,12 +43,20 @@ export const LEGACY_INTERNAL_SCHEMAS: ReadonlyArray<string> = [
4343
];
4444

4545
/**
46-
* Escapes each schema name into a SQL `LIKE` pattern, treating `_` as a literal
47-
* underscore (`\_`) and `*` as the any-character wildcard (`%`). Mirrors Go's
48-
* `strings.NewReplacer("_", "\\_", "*", "%")` — both replacements are applied to
49-
* the original string, and since `_`→`\_` introduces only a backslash (not a `*`)
50-
* and `*`→`%` introduces only a `%`, sequential JS replaces are equivalent.
46+
* Escapes each schema name into a SQL `LIKE` pattern, treating `\` and `_` as
47+
* literals and `*` as the any-character wildcard (`%`).
5148
*/
5249
export function legacyLikeEscapeSchema(schemas: ReadonlyArray<string>): ReadonlyArray<string> {
53-
return schemas.map((schema) => schema.replace(/_/g, "\\_").replace(/\*/g, "%"));
50+
return schemas.map((schema) =>
51+
schema.replace(/[\\_*]/g, (char) => {
52+
switch (char) {
53+
case "*":
54+
return "%";
55+
case "\\":
56+
return "\\\\";
57+
default:
58+
return "\\_";
59+
}
60+
}),
61+
);
5462
}

apps/cli/src/legacy/commands/inspect/db/legacy-inspect-schemas.unit.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ describe("legacyLikeEscapeSchema", () => {
1010
expect(legacyLikeEscapeSchema(["supabase_functions"])).toEqual(["supabase\\_functions"]);
1111
});
1212

13+
it("escapes backslashes before LIKE metacharacters", () => {
14+
expect(legacyLikeEscapeSchema([String.raw`custom\schema`])).toEqual([
15+
String.raw`custom\\schema`,
16+
]);
17+
expect(legacyLikeEscapeSchema([String.raw`custom\_schema`])).toEqual([
18+
String.raw`custom\\\_schema`,
19+
]);
20+
});
21+
1322
it("leaves a plain schema name untouched", () => {
1423
expect(legacyLikeEscapeSchema(["auth"])).toEqual(["auth"]);
1524
});

0 commit comments

Comments
 (0)