@yawlabs/postgres-mcp 0.6.13 → 0.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.js +23 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.14] - 2026-05-16
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
- `paramValue` (used by `pg_query`, `pg_readonly`, `pg_explain` for positional
|
|
14
|
+
parameters) was unbounded recursive via `z.lazy`. A pathologically nested
|
|
15
|
+
request body could surface a `Maximum call stack size exceeded` RangeError
|
|
16
|
+
out of the request path instead of a clear validation error. The new
|
|
17
|
+
`paramsArray` schema wraps the top-level params array with an iterative
|
|
18
|
+
depth check capped at 32 levels (arrays and objects each count as one
|
|
19
|
+
level). Closes #7.
|
|
20
|
+
|
|
10
21
|
## [0.6.13] - 2026-05-16
|
|
11
22
|
|
|
12
23
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -36353,6 +36353,25 @@ async function shutdown() {
|
|
|
36353
36353
|
var paramValue = external_exports.lazy(
|
|
36354
36354
|
() => external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null(), external_exports.array(paramValue), external_exports.record(external_exports.string(), paramValue)])
|
|
36355
36355
|
);
|
|
36356
|
+
var MAX_PARAM_DEPTH = 32;
|
|
36357
|
+
function isWithinDepth(value, maxDepth) {
|
|
36358
|
+
const stack = [[value, 0]];
|
|
36359
|
+
while (stack.length > 0) {
|
|
36360
|
+
const next = stack.pop();
|
|
36361
|
+
if (!next) break;
|
|
36362
|
+
const [v, d] = next;
|
|
36363
|
+
if (d > maxDepth) return false;
|
|
36364
|
+
if (Array.isArray(v)) {
|
|
36365
|
+
for (const item of v) stack.push([item, d + 1]);
|
|
36366
|
+
} else if (v !== null && typeof v === "object") {
|
|
36367
|
+
for (const item of Object.values(v)) stack.push([item, d + 1]);
|
|
36368
|
+
}
|
|
36369
|
+
}
|
|
36370
|
+
return true;
|
|
36371
|
+
}
|
|
36372
|
+
var paramsArray = external_exports.array(paramValue).refine((arr) => arr.every((v) => isWithinDepth(v, MAX_PARAM_DEPTH)), {
|
|
36373
|
+
message: `Parameter value exceeds maximum nesting depth of ${MAX_PARAM_DEPTH}`
|
|
36374
|
+
});
|
|
36356
36375
|
var identSchema = external_exports.string().min(1).max(63).refine((v) => Buffer.byteLength(v, "utf8") <= 63, {
|
|
36357
36376
|
message: "Identifier exceeds PostgreSQL's 63-byte NAMEDATALEN limit (multi-byte characters count as multiple bytes)."
|
|
36358
36377
|
});
|
|
@@ -36833,7 +36852,7 @@ var explainTools = [
|
|
|
36833
36852
|
sql: external_exports.string().min(1).max(1e6).describe("The SQL statement to explain. Do NOT prefix with EXPLAIN."),
|
|
36834
36853
|
analyze: external_exports.boolean().default(false).describe("Run EXPLAIN ANALYZE (actually executes the query)."),
|
|
36835
36854
|
format: external_exports.enum(["text", "json"]).default("text").describe("Output format."),
|
|
36836
|
-
params:
|
|
36855
|
+
params: paramsArray.optional().describe("Positional parameters referenced as $1, $2, ... in the SQL."),
|
|
36837
36856
|
hypothetical_indexes: external_exports.array(hypotheticalIndex).optional().describe(
|
|
36838
36857
|
"List of indexes the planner should pretend exist for this EXPLAIN. Requires the HypoPG extension. Indexes are session-scoped and reset at the end of the call."
|
|
36839
36858
|
)
|
|
@@ -36985,7 +37004,7 @@ var queryTools = [
|
|
|
36985
37004
|
},
|
|
36986
37005
|
inputSchema: external_exports.object({
|
|
36987
37006
|
sql: external_exports.string().min(1).max(1e6).describe("The SQL statement to execute. Hard cap of 1 MB."),
|
|
36988
|
-
params:
|
|
37007
|
+
params: paramsArray.optional().describe("Positional parameters referenced as $1, $2, ... in the SQL.")
|
|
36989
37008
|
}),
|
|
36990
37009
|
handler: async (input) => {
|
|
36991
37010
|
const { sql, params } = input;
|
|
@@ -37005,7 +37024,7 @@ var queryTools = [
|
|
|
37005
37024
|
},
|
|
37006
37025
|
inputSchema: external_exports.object({
|
|
37007
37026
|
sql: external_exports.string().min(1).max(1e6).describe("The SQL statement to execute. Hard cap of 1 MB."),
|
|
37008
|
-
params:
|
|
37027
|
+
params: paramsArray.optional().describe("Positional parameters referenced as $1, $2, ... in the SQL.")
|
|
37009
37028
|
}),
|
|
37010
37029
|
handler: async (input) => {
|
|
37011
37030
|
const { sql, params } = input;
|
|
@@ -37591,7 +37610,7 @@ function compareVersions(a, b) {
|
|
|
37591
37610
|
}
|
|
37592
37611
|
|
|
37593
37612
|
// src/index.ts
|
|
37594
|
-
var version2 = true ? "0.6.
|
|
37613
|
+
var version2 = true ? "0.6.14" : (await null).createRequire(import.meta.url)("../package.json").version;
|
|
37595
37614
|
var subcommand = process.argv[2];
|
|
37596
37615
|
if (subcommand === "version" || subcommand === "--version") {
|
|
37597
37616
|
console.log(version2);
|
package/package.json
CHANGED