@tinacms/graphql 2.1.2 → 2.1.3

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.
@@ -3,6 +3,10 @@ import type { Bridge } from './index';
3
3
  * This is the bridge from whatever datasource we need for I/O.
4
4
  * The basic example here is for the filesystem, one is needed
5
5
  * for GitHub has well.
6
+ *
7
+ * @security All public methods validate their `filepath` / `pattern`
8
+ * argument via `assertWithinBase` before performing any I/O. If you add a
9
+ * new method that accepts a path, you MUST validate it the same way.
6
10
  */
7
11
  export declare class FilesystemBridge implements Bridge {
8
12
  rootPath: string;
@@ -1,8 +1,36 @@
1
+ /**
2
+ * I/O abstraction layer for reading/writing content files.
3
+ *
4
+ * @security **Path traversal (CWE-22):** All `filepath` and `pattern`
5
+ * parameters may originate from user input (e.g. GraphQL mutations or media
6
+ * API requests). Implementations MUST validate that resolved paths stay
7
+ * within their root/output directory before performing any filesystem
8
+ * operation. See `FilesystemBridge.assertWithinBase` and
9
+ * `IsomorphicBridge.assertWithinBase` for reference implementations.
10
+ *
11
+ * The recommended validation pattern is:
12
+ * ```ts
13
+ * const resolved = path.resolve(path.join(baseDir, filepath));
14
+ * if (!resolved.startsWith(path.resolve(baseDir) + path.sep)) {
15
+ * throw new Error('Path traversal detected');
16
+ * }
17
+ * ```
18
+ *
19
+ * If you are adding a new Bridge implementation, add path traversal
20
+ * validation to every method that accepts a filepath from the caller.
21
+ */
1
22
  export interface Bridge {
2
23
  rootPath: string;
24
+ /**
25
+ * @param pattern - Glob pattern prefix (untrusted — validate before use).
26
+ * @param extension - File extension to match.
27
+ */
3
28
  glob(pattern: string, extension: string): Promise<string[]>;
29
+ /** @param filepath - Relative path to delete (untrusted — validate before use). */
4
30
  delete(filepath: string): Promise<void>;
31
+ /** @param filepath - Relative path to read (untrusted — validate before use). */
5
32
  get(filepath: string): Promise<string>;
33
+ /** @param filepath - Relative path to write (untrusted — validate before use). */
6
34
  put(filepath: string, data: string): Promise<void>;
7
35
  /**
8
36
  * Optionally, the bridge can perform
@@ -18,6 +18,11 @@ export type IsomorphicGitBridgeOptions = {
18
18
  };
19
19
  /**
20
20
  * Bridge backed by isomorphic-git
21
+ *
22
+ * @security All public methods (glob, get, put, delete) validate their
23
+ * `filepath` / `pattern` argument via `assertWithinBase` before performing
24
+ * any git operations. If you add a new method that accepts a path, you
25
+ * MUST validate it the same way.
21
26
  */
22
27
  export declare class IsomorphicBridge implements Bridge {
23
28
  rootPath: string;
package/dist/index.js CHANGED
@@ -45,8 +45,8 @@ var btoa = (string2) => {
45
45
  var lastItem = (arr) => {
46
46
  return arr[arr.length - 1];
47
47
  };
48
- var get = (obj, path8, defaultValue = void 0) => {
49
- const travel = (regexp) => String.prototype.split.call(path8, regexp).filter(Boolean).reduce(
48
+ var get = (obj, path9, defaultValue = void 0) => {
49
+ const travel = (regexp) => String.prototype.split.call(path9, regexp).filter(Boolean).reduce(
50
50
  (res, key) => res !== null && res !== void 0 ? res[key] : res,
51
51
  obj
52
52
  );
@@ -3026,7 +3026,7 @@ var validateField = async (field) => {
3026
3026
  var package_default = {
3027
3027
  name: "@tinacms/graphql",
3028
3028
  type: "module",
3029
- version: "2.1.2",
3029
+ version: "2.1.3",
3030
3030
  main: "dist/index.js",
3031
3031
  module: "./dist/index.js",
3032
3032
  files: [
@@ -3662,17 +3662,17 @@ var scanAllContent = async (tinaSchema, bridge, callback) => {
3662
3662
  const documentPaths = await bridge.glob(normalPath, format);
3663
3663
  const matches = tinaSchema.getMatches({ collection });
3664
3664
  const filteredPaths = matches.length > 0 ? micromatch(documentPaths, matches) : documentPaths;
3665
- filteredPaths.forEach((path8) => {
3666
- if (filesSeen.has(path8)) {
3667
- filesSeen.get(path8).push(collection.name);
3668
- duplicateFiles.add(path8);
3665
+ filteredPaths.forEach((path9) => {
3666
+ if (filesSeen.has(path9)) {
3667
+ filesSeen.get(path9).push(collection.name);
3668
+ duplicateFiles.add(path9);
3669
3669
  } else {
3670
- filesSeen.set(path8, [collection.name]);
3670
+ filesSeen.set(path9, [collection.name]);
3671
3671
  }
3672
3672
  });
3673
- duplicateFiles.forEach((path8) => {
3673
+ duplicateFiles.forEach((path9) => {
3674
3674
  warnings.push(
3675
- `"${path8}" Found in multiple collections: ${filesSeen.get(path8).map((collection2) => `"${collection2}"`).join(
3675
+ `"${path9}" Found in multiple collections: ${filesSeen.get(path9).map((collection2) => `"${collection2}"`).join(
3676
3676
  ", "
3677
3677
  )}. This can cause unexpected behavior. We recommend updating the \`match\` property of those collections so that each file is in only one collection.
3678
3678
  This will be an error in the future. See https://tina.io/docs/errors/file-in-mutpliple-collections/
@@ -4235,9 +4235,9 @@ var makeFilterSuffixes = (filterChain, index) => {
4235
4235
  }
4236
4236
  };
4237
4237
  var FOLDER_ROOT = "~";
4238
- var stripCollectionFromPath = (collectionPath, path8) => {
4238
+ var stripCollectionFromPath = (collectionPath, path9) => {
4239
4239
  const collectionPathParts = collectionPath.split("/");
4240
- const pathParts = path8.split("/");
4240
+ const pathParts = path9.split("/");
4241
4241
  const strippedPathParts = pathParts.slice(collectionPathParts.length);
4242
4242
  return strippedPathParts.join("/");
4243
4243
  };
@@ -4293,13 +4293,13 @@ var makeFolderOpsForCollection = (folderTree, collection, indexDefinitions, opTy
4293
4293
  SUBLEVEL_OPTIONS
4294
4294
  );
4295
4295
  let folderSortingIdx = 0;
4296
- for (const path8 of Array.from(folder).sort()) {
4296
+ for (const path9 of Array.from(folder).sort()) {
4297
4297
  for (const [sort] of Object.entries(indexDefinitions)) {
4298
4298
  const indexSublevel = folderCollectionSublevel.sublevel(
4299
4299
  sort,
4300
4300
  SUBLEVEL_OPTIONS
4301
4301
  );
4302
- const subFolderKey = sha.hex(path8);
4302
+ const subFolderKey = sha.hex(path9);
4303
4303
  if (sort === DEFAULT_COLLECTION_SORT_KEY) {
4304
4304
  result.push({
4305
4305
  type: opType,
@@ -4381,8 +4381,8 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
4381
4381
  SUBLEVEL_OPTIONS
4382
4382
  );
4383
4383
  const references2 = {};
4384
- for (const path8 of referencePaths) {
4385
- const ref = JSONPath({ path: path8, json: data });
4384
+ for (const path9 of referencePaths) {
4385
+ const ref = JSONPath({ path: path9, json: data });
4386
4386
  if (!ref) {
4387
4387
  continue;
4388
4388
  }
@@ -4392,24 +4392,24 @@ var makeRefOpsForDocument = (filepath, collection, references, data, opType, lev
4392
4392
  continue;
4393
4393
  }
4394
4394
  if (references2[r]) {
4395
- references2[r].push(path8);
4395
+ references2[r].push(path9);
4396
4396
  } else {
4397
- references2[r] = [path8];
4397
+ references2[r] = [path9];
4398
4398
  }
4399
4399
  }
4400
4400
  } else {
4401
4401
  if (references2[ref]) {
4402
- references2[ref].push(path8);
4402
+ references2[ref].push(path9);
4403
4403
  } else {
4404
- references2[ref] = [path8];
4404
+ references2[ref] = [path9];
4405
4405
  }
4406
4406
  }
4407
4407
  }
4408
4408
  for (const ref of Object.keys(references2)) {
4409
- for (const path8 of references2[ref]) {
4409
+ for (const path9 of references2[ref]) {
4410
4410
  result.push({
4411
4411
  type: opType,
4412
- key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path8}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4412
+ key: `${ref}${INDEX_KEY_FIELD_SEPARATOR}${path9}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
4413
4413
  sublevel: refSublevel,
4414
4414
  value: opType === "put" ? {} : void 0
4415
4415
  });
@@ -4676,9 +4676,9 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
4676
4676
  return value;
4677
4677
  }
4678
4678
  };
4679
- var cleanUpSlashes = (path8) => {
4680
- if (path8) {
4681
- return `/${path8.replace(/^\/+|\/+$/gm, "")}`;
4679
+ var cleanUpSlashes = (path9) => {
4680
+ if (path9) {
4681
+ return `/${path9.replace(/^\/+|\/+$/gm, "")}`;
4682
4682
  }
4683
4683
  return "";
4684
4684
  };
@@ -4888,17 +4888,17 @@ var transformDocumentIntoPayload = async (fullPath, rawData, tinaSchema, config,
4888
4888
  throw e;
4889
4889
  }
4890
4890
  };
4891
- var updateObjectWithJsonPath = (obj, path8, oldValue, newValue) => {
4891
+ var updateObjectWithJsonPath = (obj, path9, oldValue, newValue) => {
4892
4892
  let updated = false;
4893
- if (!path8.includes(".") && !path8.includes("[")) {
4894
- if (path8 in obj && obj[path8] === oldValue) {
4895
- obj[path8] = newValue;
4893
+ if (!path9.includes(".") && !path9.includes("[")) {
4894
+ if (path9 in obj && obj[path9] === oldValue) {
4895
+ obj[path9] = newValue;
4896
4896
  updated = true;
4897
4897
  }
4898
4898
  return { object: obj, updated };
4899
4899
  }
4900
- const parentPath = path8.replace(/\.[^.\[\]]+$/, "");
4901
- const keyToUpdate = path8.match(/[^.\[\]]+$/)[0];
4900
+ const parentPath = path9.replace(/\.[^.\[\]]+$/, "");
4901
+ const keyToUpdate = path9.match(/[^.\[\]]+$/)[0];
4902
4902
  const parents = JSONPath2({
4903
4903
  path: parentPath,
4904
4904
  json: obj,
@@ -5322,10 +5322,10 @@ var Resolver = class {
5322
5322
  )) {
5323
5323
  let docWithRef = await this.getRaw(pathToDocWithRef);
5324
5324
  let hasUpdate = false;
5325
- for (const path8 of referencePaths) {
5325
+ for (const path9 of referencePaths) {
5326
5326
  const { object: object2, updated } = updateObjectWithJsonPath(
5327
5327
  docWithRef,
5328
- path8,
5328
+ path9,
5329
5329
  realPath,
5330
5330
  newRealPath
5331
5331
  );
@@ -5390,10 +5390,10 @@ var Resolver = class {
5390
5390
  )) {
5391
5391
  let refDoc = await this.getRaw(pathToDocWithRef);
5392
5392
  let hasUpdate = false;
5393
- for (const path8 of referencePaths) {
5393
+ for (const path9 of referencePaths) {
5394
5394
  const { object: object2, updated } = updateObjectWithJsonPath(
5395
5395
  refDoc,
5396
- path8,
5396
+ path9,
5397
5397
  realPath,
5398
5398
  null
5399
5399
  );
@@ -5660,7 +5660,7 @@ var Resolver = class {
5660
5660
  first: -1
5661
5661
  },
5662
5662
  collection: referencedCollection,
5663
- hydrator: (path8) => path8
5663
+ hydrator: (path9) => path9
5664
5664
  // just return the path
5665
5665
  }
5666
5666
  );
@@ -6101,8 +6101,8 @@ async function handleUpdatePassword({
6101
6101
  // src/error.ts
6102
6102
  import { GraphQLError as GraphQLError3 } from "graphql";
6103
6103
  var NotFoundError = class extends GraphQLError3 {
6104
- constructor(message, nodes, source, positions, path8, originalError, extensions) {
6105
- super(message, nodes, source, positions, path8, originalError, extensions);
6104
+ constructor(message, nodes, source, positions, path9, originalError, extensions) {
6105
+ super(message, nodes, source, positions, path9, originalError, extensions);
6106
6106
  this.name = "NotFoundError";
6107
6107
  }
6108
6108
  };
@@ -7364,21 +7364,21 @@ var Database = class {
7364
7364
  edges,
7365
7365
  async ({
7366
7366
  cursor,
7367
- path: path8,
7367
+ path: path9,
7368
7368
  value
7369
7369
  }) => {
7370
7370
  try {
7371
- const node = await hydrator(path8, value);
7371
+ const node = await hydrator(path9, value);
7372
7372
  return {
7373
7373
  node,
7374
7374
  cursor: btoa(cursor)
7375
7375
  };
7376
7376
  } catch (error) {
7377
7377
  console.log(error);
7378
- if (error instanceof Error && (!path8.includes(".tina/__generated__/_graphql.json") || !path8.includes("tina/__generated__/_graphql.json"))) {
7378
+ if (error instanceof Error && (!path9.includes(".tina/__generated__/_graphql.json") || !path9.includes("tina/__generated__/_graphql.json"))) {
7379
7379
  throw new TinaQueryError({
7380
7380
  originalError: error,
7381
- file: path8,
7381
+ file: path9,
7382
7382
  collection: collection.name
7383
7383
  });
7384
7384
  }
@@ -7666,8 +7666,8 @@ var Database = class {
7666
7666
  return { warnings };
7667
7667
  };
7668
7668
  };
7669
- var hashPasswordVisitor = async (node, path8) => {
7670
- const passwordValuePath = [...path8, "value"];
7669
+ var hashPasswordVisitor = async (node, path9) => {
7670
+ const passwordValuePath = [...path9, "value"];
7671
7671
  const plaintextPassword = get(node, passwordValuePath);
7672
7672
  if (plaintextPassword) {
7673
7673
  set2(
@@ -7677,10 +7677,10 @@ var hashPasswordVisitor = async (node, path8) => {
7677
7677
  );
7678
7678
  }
7679
7679
  };
7680
- var visitNodes = async (node, path8, callback) => {
7681
- const [currentLevel, ...remainingLevels] = path8;
7680
+ var visitNodes = async (node, path9, callback) => {
7681
+ const [currentLevel, ...remainingLevels] = path9;
7682
7682
  if (!remainingLevels?.length) {
7683
- return callback(node, path8);
7683
+ return callback(node, path9);
7684
7684
  }
7685
7685
  if (Array.isArray(node[currentLevel])) {
7686
7686
  for (const item of node[currentLevel]) {
@@ -8009,10 +8009,20 @@ var shaExists = async ({
8009
8009
  }) => git.readCommit({ fs: fs4, dir, oid: sha3 }).then(() => true).catch(() => false);
8010
8010
 
8011
8011
  // src/database/bridge/filesystem.ts
8012
- import fs2 from "fs-extra";
8013
- import fg from "fast-glob";
8014
8012
  import path7 from "path";
8013
+ import fg from "fast-glob";
8014
+ import fs2 from "fs-extra";
8015
8015
  import normalize from "normalize-path";
8016
+ function assertWithinBase(filepath, baseDir) {
8017
+ const resolvedBase = path7.resolve(baseDir);
8018
+ const resolved = path7.resolve(path7.join(baseDir, filepath));
8019
+ if (resolved !== resolvedBase && !resolved.startsWith(resolvedBase + path7.sep)) {
8020
+ throw new Error(
8021
+ `Path traversal detected: "${filepath}" escapes the base directory`
8022
+ );
8023
+ }
8024
+ return resolved;
8025
+ }
8016
8026
  var FilesystemBridge = class {
8017
8027
  rootPath;
8018
8028
  outputPath;
@@ -8021,7 +8031,7 @@ var FilesystemBridge = class {
8021
8031
  this.outputPath = outputPath ? path7.resolve(outputPath) : this.rootPath;
8022
8032
  }
8023
8033
  async glob(pattern, extension) {
8024
- const basePath = path7.join(this.outputPath, ...pattern.split("/"));
8034
+ const basePath = assertWithinBase(pattern, this.outputPath);
8025
8035
  const items = await fg(
8026
8036
  path7.join(basePath, "**", `/*.${extension}`).replace(/\\/g, "/"),
8027
8037
  {
@@ -8035,14 +8045,17 @@ var FilesystemBridge = class {
8035
8045
  );
8036
8046
  }
8037
8047
  async delete(filepath) {
8038
- await fs2.remove(path7.join(this.outputPath, filepath));
8048
+ const resolved = assertWithinBase(filepath, this.outputPath);
8049
+ await fs2.remove(resolved);
8039
8050
  }
8040
8051
  async get(filepath) {
8041
- return (await fs2.readFile(path7.join(this.outputPath, filepath))).toString();
8052
+ const resolved = assertWithinBase(filepath, this.outputPath);
8053
+ return (await fs2.readFile(resolved)).toString();
8042
8054
  }
8043
8055
  async put(filepath, data, basePathOverride) {
8044
8056
  const basePath = basePathOverride || this.outputPath;
8045
- await fs2.outputFile(path7.join(basePath, filepath), data);
8057
+ const resolved = assertWithinBase(filepath, basePath);
8058
+ await fs2.outputFile(resolved, data);
8046
8059
  }
8047
8060
  };
8048
8061
  var AuditFileSystemBridge = class extends FilesystemBridge {
@@ -8062,12 +8075,21 @@ var AuditFileSystemBridge = class extends FilesystemBridge {
8062
8075
  };
8063
8076
 
8064
8077
  // src/database/bridge/isomorphic.ts
8065
- import git2 from "isomorphic-git";
8078
+ import path8, { dirname } from "path";
8066
8079
  import fs3 from "fs-extra";
8067
8080
  import globParent from "glob-parent";
8068
- import normalize2 from "normalize-path";
8069
8081
  import { GraphQLError as GraphQLError6 } from "graphql";
8070
- import { dirname } from "path";
8082
+ import git2 from "isomorphic-git";
8083
+ import normalize2 from "normalize-path";
8084
+ function assertWithinBase2(filepath, relativePath) {
8085
+ const qualified = relativePath ? `${relativePath}/${filepath}` : filepath;
8086
+ const normalized = path8.normalize(qualified);
8087
+ if (normalized.startsWith("..") || normalized.startsWith("/") || path8.isAbsolute(normalized) || relativePath && normalized !== relativePath && !normalized.startsWith(relativePath + "/")) {
8088
+ throw new Error(
8089
+ `Path traversal detected: "${filepath}" escapes the content root`
8090
+ );
8091
+ }
8092
+ }
8071
8093
  var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
8072
8094
  var toUint8Array = (buf) => {
8073
8095
  const ab = new ArrayBuffer(buf.length);
@@ -8146,7 +8168,7 @@ var IsomorphicBridge = class {
8146
8168
  async listEntries({
8147
8169
  pattern,
8148
8170
  entry,
8149
- path: path8,
8171
+ path: path9,
8150
8172
  results
8151
8173
  }) {
8152
8174
  const treeResult = await git2.readTree({
@@ -8156,7 +8178,7 @@ var IsomorphicBridge = class {
8156
8178
  });
8157
8179
  const children = [];
8158
8180
  for (const childEntry of treeResult.tree) {
8159
- const childPath = path8 ? `${path8}/${childEntry.path}` : childEntry.path;
8181
+ const childPath = path9 ? `${path9}/${childEntry.path}` : childEntry.path;
8160
8182
  if (childEntry.type === "tree") {
8161
8183
  children.push(childEntry);
8162
8184
  } else {
@@ -8166,7 +8188,7 @@ var IsomorphicBridge = class {
8166
8188
  }
8167
8189
  }
8168
8190
  for (const childEntry of children) {
8169
- const childPath = path8 ? `${path8}/${childEntry.path}` : childEntry.path;
8191
+ const childPath = path9 ? `${path9}/${childEntry.path}` : childEntry.path;
8170
8192
  await this.listEntries({
8171
8193
  pattern,
8172
8194
  entry: childEntry,
@@ -8184,17 +8206,17 @@ var IsomorphicBridge = class {
8184
8206
  * @param ref - ref to resolve path entries for
8185
8207
  * @private
8186
8208
  */
8187
- async resolvePathEntries(path8, ref) {
8188
- let pathParts = path8.split("/");
8209
+ async resolvePathEntries(path9, ref) {
8210
+ let pathParts = path9.split("/");
8189
8211
  const result = await git2.walk({
8190
8212
  ...this.isomorphicConfig,
8191
8213
  map: async (filepath, [head]) => {
8192
8214
  if (head._fullpath === ".") {
8193
8215
  return head;
8194
8216
  }
8195
- if (path8.startsWith(filepath)) {
8196
- if (dirname(path8) === dirname(filepath)) {
8197
- if (path8 === filepath) {
8217
+ if (path9.startsWith(filepath)) {
8218
+ if (dirname(path9) === dirname(filepath)) {
8219
+ if (path9 === filepath) {
8198
8220
  return head;
8199
8221
  }
8200
8222
  } else {
@@ -8225,7 +8247,7 @@ var IsomorphicBridge = class {
8225
8247
  * @param pathParts - parent path parts
8226
8248
  * @private
8227
8249
  */
8228
- async updateTreeHierarchy(existingOid, updatedOid, path8, type, pathEntries, pathParts) {
8250
+ async updateTreeHierarchy(existingOid, updatedOid, path9, type, pathEntries, pathParts) {
8229
8251
  const lastIdx = pathEntries.length - 1;
8230
8252
  const parentEntry = pathEntries[lastIdx];
8231
8253
  const parentPath = pathParts[lastIdx];
@@ -8240,7 +8262,7 @@ var IsomorphicBridge = class {
8240
8262
  cache: this.cache
8241
8263
  });
8242
8264
  tree = existingOid ? treeResult.tree.map((entry) => {
8243
- if (entry.path === path8) {
8265
+ if (entry.path === path9) {
8244
8266
  entry.oid = updatedOid;
8245
8267
  }
8246
8268
  return entry;
@@ -8249,7 +8271,7 @@ var IsomorphicBridge = class {
8249
8271
  {
8250
8272
  oid: updatedOid,
8251
8273
  type,
8252
- path: path8,
8274
+ path: path9,
8253
8275
  mode
8254
8276
  }
8255
8277
  ];
@@ -8258,7 +8280,7 @@ var IsomorphicBridge = class {
8258
8280
  {
8259
8281
  oid: updatedOid,
8260
8282
  type,
8261
- path: path8,
8283
+ path: path9,
8262
8284
  mode
8263
8285
  }
8264
8286
  ];
@@ -8334,6 +8356,7 @@ var IsomorphicBridge = class {
8334
8356
  return ref;
8335
8357
  }
8336
8358
  async glob(pattern, extension) {
8359
+ assertWithinBase2(pattern, this.relativePath);
8337
8360
  const ref = await this.getRef();
8338
8361
  const parent = globParent(this.qualifyPath(pattern));
8339
8362
  const { pathParts, pathEntries } = await this.resolvePathEntries(
@@ -8367,9 +8390,10 @@ var IsomorphicBridge = class {
8367
8390
  path: parentPath,
8368
8391
  results
8369
8392
  });
8370
- return results.map((path8) => this.unqualifyPath(path8)).filter((path8) => path8.endsWith(extension));
8393
+ return results.map((path9) => this.unqualifyPath(path9)).filter((path9) => path9.endsWith(extension));
8371
8394
  }
8372
8395
  async delete(filepath) {
8396
+ assertWithinBase2(filepath, this.relativePath);
8373
8397
  const ref = await this.getRef();
8374
8398
  const { pathParts, pathEntries } = await this.resolvePathEntries(
8375
8399
  this.qualifyPath(filepath),
@@ -8441,6 +8465,7 @@ var IsomorphicBridge = class {
8441
8465
  return this.relativePath ? filepath.slice(this.relativePath.length + 1) : filepath;
8442
8466
  }
8443
8467
  async get(filepath) {
8468
+ assertWithinBase2(filepath, this.relativePath);
8444
8469
  const ref = await this.getRef();
8445
8470
  const oid = await git2.resolveRef({
8446
8471
  ...this.isomorphicConfig,
@@ -8455,6 +8480,7 @@ var IsomorphicBridge = class {
8455
8480
  return Buffer.from(blob).toString("utf8");
8456
8481
  }
8457
8482
  async put(filepath, data) {
8483
+ assertWithinBase2(filepath, this.relativePath);
8458
8484
  const ref = await this.getRef();
8459
8485
  const { pathParts, pathEntries } = await this.resolvePathEntries(
8460
8486
  this.qualifyPath(filepath),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tinacms/graphql",
3
3
  "type": "module",
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "main": "dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "files": [
@@ -43,8 +43,8 @@
43
43
  "normalize-path": "^3.0.0",
44
44
  "readable-stream": "^4.7.0",
45
45
  "yup": "^1.6.1",
46
- "@tinacms/schema-tools": "2.6.0",
47
- "@tinacms/mdx": "2.0.6"
46
+ "@tinacms/mdx": "2.0.6",
47
+ "@tinacms/schema-tools": "2.6.0"
48
48
  },
49
49
  "publishConfig": {
50
50
  "registry": "https://registry.npmjs.org"
@@ -71,8 +71,8 @@
71
71
  "vite": "^4.5.9",
72
72
  "vitest": "^0.32.4",
73
73
  "zod": "^3.24.2",
74
- "@tinacms/schema-tools": "2.6.0",
75
- "@tinacms/scripts": "1.5.0"
74
+ "@tinacms/scripts": "1.5.0",
75
+ "@tinacms/schema-tools": "2.6.0"
76
76
  },
77
77
  "scripts": {
78
78
  "types": "pnpm tsc",