Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build_backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.24"
go-version-file: "go.mod"

- name: Install dependencies
run: |
Expand Down
27 changes: 23 additions & 4 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"test:security": "node --test tests/security-dependencies.test.mjs",
"lint": "next lint",
"format": "prettier --write .",
"format:check": "prettier --check .",
Expand Down Expand Up @@ -41,7 +42,7 @@
"@tabler/icons-react": "^3.33.0",
"@tanstack/react-table": "^8.21.3",
"@tanstack/react-virtual": "^3.13.12",
"axios": "^1.9.0",
"axios": "^1.16.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
Expand All @@ -50,7 +51,7 @@
"embla-carousel-react": "^8.6.0",
"lucide-react": "^1.8.0",
"motion": "^12.15.0",
"next": "15.3.8",
"next": "15.5.27",
"next-themes": "^0.4.6",
"radix-ui": "^1.4.2",
"react": "^19.0.0",
Expand All @@ -73,7 +74,7 @@
"@types/react-dom": "^19.1.6",
"eslint": "^9",
"eslint-config-google": "^0.14.0",
"eslint-config-next": "15.3.3",
"eslint-config-next": "15.5.27",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-prettier": "^5.4.1",
"prettier": "^3.5.3",
Expand All @@ -83,8 +84,26 @@
},
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
"pnpm": {
"overrides": {
"brace-expansion@>=1.0.0 <1.1.21": "1.1.21",
"brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
"flatted@>=3.0.0 <3.4.2": "3.4.2",
"form-data@>=4.0.0 <4.0.6": "4.0.6",
"js-yaml@>=4.0.0 <4.3.2": "4.3.2",
"lodash@>=4.0.0 <4.18.0": "4.18.0",
"minimatch@>=3.0.0 <3.1.4": "3.1.4",
"minimatch@>=9.0.0 <9.0.7": "9.0.7",
"nanoid@>=3.0.0 <3.3.18": "3.3.18",
"picomatch@>=2.0.0 <2.3.2": "2.3.2",
"picomatch@>=4.0.0 <4.0.4": "4.0.4",
"postcss@>=8.0.0 <8.5.23": "8.5.23",
"sharp@<0.35.5": "0.35.5",
"source-map-js@>=1.0.0 <1.2.2": "1.2.2",
"tar@>=7.0.0 <7.5.21": "7.5.21"
},
"patchedDependencies": {
"mdast-util-gfm-autolink-literal@2.0.1": "patches/mdast-util-gfm-autolink-literal@2.0.1.patch"
"mdast-util-gfm-autolink-literal@2.0.1": "patches/mdast-util-gfm-autolink-literal@2.0.1.patch",
"braces@3.0.3": "patches/braces@3.0.3.patch"
}
}
}
69 changes: 69 additions & 0 deletions frontend/patches/braces@3.0.3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
diff --git a/lib/compile.js b/lib/compile.js
index dce69beb90ece5c3b0ca234a949418f9f34eedbc..a3ee0c7b238c3c32525fadd3d2c227241562cdeb 100644
--- a/lib/compile.js
+++ b/lib/compile.js
@@ -4,6 +4,8 @@ const fill = require('fill-range');
const utils = require('./utils');

const compile = (ast, options = {}) => {
+ utils.checkDepth(ast);
+
const walk = (node, parent = {}) => {
const invalidBlock = utils.isInvalidBrace(parent);
const invalidNode = node.invalid === true && options.escapeInvalid === true;
diff --git a/lib/expand.js b/lib/expand.js
index 35b2c41d6afdb8f0197959e26079f266e48370d3..ebf565e374694ae42a3094fc6bfc569c789ad03b 100644
--- a/lib/expand.js
+++ b/lib/expand.js
@@ -31,6 +31,8 @@ const append = (queue = '', stash = '', enclose = false) => {
};

const expand = (ast, options = {}) => {
+ utils.checkDepth(ast);
+
const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit;

const walk = (node, parent = {}) => {
diff --git a/lib/stringify.js b/lib/stringify.js
index 8bcf872c31894f81a8c64d9202fd607e4fd7ea2b..886b39c7567207930d6ecbd7d99895c0f91313de 100644
--- a/lib/stringify.js
+++ b/lib/stringify.js
@@ -3,6 +3,8 @@
const utils = require('./utils');

module.exports = (ast, options = {}) => {
+ utils.checkDepth(ast);
+
const stringify = (node, parent = {}) => {
const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
const invalidNode = node.invalid === true && options.escapeInvalid === true;
diff --git a/lib/utils.js b/lib/utils.js
index d19311fe044ad5157624077670dc297e8b53da49..513e98b59a4976031bb596a08a029a7bbaa36b28 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -1,5 +1,25 @@
'use strict';

+const MAX_DEPTH = 128;
+
+exports.checkDepth = ast => {
+ const stack = [{ node: ast, depth: 0 }];
+
+ while (stack.length > 0) {
+ const { node, depth } = stack.pop();
+
+ if (depth > MAX_DEPTH) {
+ throw new SyntaxError(`AST depth exceeds maximum nesting depth (${MAX_DEPTH})`);
+ }
+
+ if (node.nodes) {
+ for (const child of node.nodes) {
+ stack.push({ node: child, depth: depth + 1 });
+ }
+ }
+ }
+};
+
exports.isInteger = num => {
if (typeof num === 'number') {
return Number.isInteger(num);
Loading
Loading