Skip to content

Commit af60dea

Browse files
authored
escape shell metacharacters (#640)
1 parent c4d278e commit af60dea

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

.changeset/deep-nails-behave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/cloudflare": patch
3+
---
4+
5+
fix: escape shell arguments when populating the cache

packages/cloudflare/src/cli/commands/populate-cache.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ async function populateR2IncrementalCache(
122122

123123
runWrangler(
124124
options,
125-
["r2 object put", JSON.stringify(path.join(bucket, cacheKey)), `--file ${JSON.stringify(fullPath)}`],
125+
["r2 object put", quoteShellMeta(path.join(bucket, cacheKey)), `--file ${quoteShellMeta(fullPath)}`],
126126
// NOTE: R2 does not support the environment flag and results in the following error:
127127
// Incorrect type for the 'cacheExpiry' field on 'HttpMetadata': the provided value is not of type 'date'.
128128
{ target: populateCacheOptions.target, excludeRemoteFlag: true, logging: "error" }
@@ -168,11 +168,10 @@ async function populateKVIncrementalCache(
168168

169169
writeFileSync(chunkPath, JSON.stringify(kvMapping));
170170

171-
runWrangler(
172-
options,
173-
["kv bulk put", JSON.stringify(chunkPath), `--binding ${JSON.stringify(KV_CACHE_BINDING_NAME)}`],
174-
{ ...populateCacheOptions, logging: "error" }
175-
);
171+
runWrangler(options, ["kv bulk put", quoteShellMeta(chunkPath), `--binding ${KV_CACHE_BINDING_NAME}`], {
172+
...populateCacheOptions,
173+
logging: "error",
174+
});
176175

177176
rmSync(chunkPath);
178177
}
@@ -197,7 +196,7 @@ function populateD1TagCache(
197196
options,
198197
[
199198
"d1 execute",
200-
JSON.stringify(D1_TAG_BINDING_NAME),
199+
D1_TAG_BINDING_NAME,
201200
`--command "CREATE TABLE IF NOT EXISTS revalidations (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE);"`,
202201
],
203202
{ ...populateCacheOptions, logging: "error" }
@@ -258,3 +257,23 @@ export async function populateCache(
258257
}
259258
}
260259
}
260+
261+
/**
262+
* Escape shell metacharacters.
263+
*
264+
* When `spawnSync` is invoked with `shell: true`, metacharacters need to be escaped.
265+
*
266+
* Based on https://github.com/ljharb/shell-quote/blob/main/quote.js
267+
*
268+
* @param arg
269+
* @returns escaped arg
270+
*/
271+
function quoteShellMeta(arg: string) {
272+
if (/["\s]/.test(arg) && !/'/.test(arg)) {
273+
return `'${arg.replace(/(['\\])/g, "\\$1")}'`;
274+
}
275+
if (/["'\s]/.test(arg)) {
276+
return `"${arg.replace(/(["\\$`!])/g, "\\$1")}"`;
277+
}
278+
return arg.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
279+
}

0 commit comments

Comments
 (0)