Skip to content

Conversation

@Falcion
Copy link
Owner

@Falcion Falcion commented Nov 4, 2025

PRs: update OBSIDIAN API, add "forced" modes and fix settings

Before writing anything about your changes in this PR, checklist this items:

By agreeding and following this project's documentation, you are reminded that your's commit and styling of changes must follow this project's documentation, in case of “de-followization”, there are two ways before you make sure to publishing your PR:

  1. In case of “de-followization” of commit's styling convention, you can amend them (change their message and description signatures):
git commit --amend -m "MESSAGE" -m "DESCRIPTION"

For amending old commit, see the stackoverflow question1, more about changing commits in official docs for github:
https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message/

  1. In case of “de-followization” of coding, documentation and etc. files, you can just refactor everything you need by following styling guidelines of project.

Changes with that PR

Please, write below every changes you made:

  1. updated "obsidian" (Obsidian's API) to last version (1.10*);
  2. updated "obsidian-typings" (typing of Obsidian's API) to last version (2.44*);
  3. fix issue, where "use default extensions" feature lagged and displayed input incorrectly (fix of #158);
  4. make "silence errors" feature true by default;

Process of testing for that PR

  • Was testing process initiated via this PR?
    answer (y/n): (n);
  • If testing was done, type below the procedures you make:
    ...

Additional context for that PR

Closes #160
Closes #159
Closes #158

Footnotes

  1. https://stackoverflow.com/questions/17338792/amending-old-commit/

dependabot bot and others added 7 commits September 30, 2025 16:23
Bumps the npm_and_yarn group with 1 update in the / directory: [axios](https://github.com/axios/axios).


Updates `axios` from 1.8.2 to 1.12.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.8.2...v1.12.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.12.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Fixed an issue, where input for code editor extensions was incorrectly
displayed within the toggle value of "use default extensions" feature.

Closes #158
…s/setup-node-6

build(deps): bump actions/setup-node from 5 to 6
…/codeql-action-4

build(deps): bump github/codeql-action from 3 to 4
…yarn-16c0b19af7

build(deps-dev): bump axios from 1.8.2 to 1.12.0 in the npm_and_yarn group across 1 directory
@Falcion Falcion linked an issue Nov 4, 2025 that may be closed by this pull request
2 tasks
1) update "obsidian" package;
2) update "obsidian-typings" package;
Delete deprecated parts of project for
more clean build output.
1) create debounce function for future inputs
2) create obsidian theme getter function
3) declare required types
4) create deep read/write functions for nested settings
1) use bundler as module resolution param;
2) delete root path and implement main;
1) now using data variants for light/dark theme
adaptations;
2) create special styles for new settings and adapt,
fix them for correct work;
1) add CSS styling support for input components;
2) update and correct icons for tabs and settings;
1) implement new dynamic method for
loading settings tab;
2) deep read/write now works with
original array, not copy;
3) create new type definition for
settings tab factory;
cursor = cursor[p];
}
if (!Object.prototype.hasOwnProperty.call(cursor, parts[parts.length - 1]) || typeof cursor[parts[parts.length - 1]] !== 'object')
cursor[parts[parts.length - 1]] = value;

Check warning

Code scanning / CodeQL

Prototype-polluting function Medium

The property chain
here
is recursively assigned to
cursor
without guarding against prototype pollution.

Copilot Autofix

AI 7 days ago

In general, a safe deep-assignment function that receives untrusted paths must either (a) block dangerous property names such as __proto__, constructor, and prototype, or (b) ensure that it never operates on objects that could end up in any prototype chain. Since we cannot change how setDeep is used, the robust fix is to add explicit checks that prevent traversing or creating these dangerous properties anywhere along the path.

The best targeted fix here is: when iterating parts in setDeep, skip or reject any segment that equals "__proto__", "constructor", or "prototype". If such a key is encountered either in the loop (for intermediates) or for the final segment, we should stop and return obj without creating or modifying anything. This preserves all existing behavior for legitimate keys while preventing pollution. Concretely:

  • After computing parts = path.split('.'), we can either (1) scan parts once and early-return if any forbidden key is present, or (2) check each segment just before using it (p inside the loop and parts[parts.length - 1] for the final write). To keep the change minimal and localized, we can add a small helper isUnsafeKey in this file and use it where keys are read.
  • All changes occur in source/settings/utils/functions/deep.ts, only inside the shown code. No behavior changes for safe keys; dangerous keys now cause setDeep to do nothing.
Suggested changeset 1
source/settings/utils/functions/deep.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/source/settings/utils/functions/deep.ts b/source/settings/utils/functions/deep.ts
--- a/source/settings/utils/functions/deep.ts
+++ b/source/settings/utils/functions/deep.ts
@@ -3,17 +3,33 @@
     return path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj);
 }
 
+function isUnsafeKey(key: string): boolean {
+    return key === '__proto__' || key === 'constructor' || key === 'prototype';
+}
+
 export function setDeep<T = any>(obj: T, path: string, value: any): T {
     const parts = path.split('.');
     let cursor = obj as any;
     for (let i = 0; i < parts.length - 1; i++) {
         const p = parts[i];
-        if (!Object.prototype.hasOwnProperty.call(cursor, p) || typeof cursor[p] !== 'object')
+        if (isUnsafeKey(p)) {
+            return obj;
+        }
+        if (!Object.prototype.hasOwnProperty.call(cursor, p) || typeof cursor[p] !== 'object') {
             cursor[p] = Object.create(null);
+        }
         cursor = cursor[p];
     }
-    if (!Object.prototype.hasOwnProperty.call(cursor, parts[parts.length - 1]) || typeof cursor[parts[parts.length - 1]] !== 'object')
-        cursor[parts[parts.length - 1]] = value;
+    const lastKey = parts[parts.length - 1];
+    if (isUnsafeKey(lastKey)) {
+        return obj;
+    }
+    if (
+        !Object.prototype.hasOwnProperty.call(cursor, lastKey) ||
+        typeof cursor[lastKey] !== 'object'
+    ) {
+        cursor[lastKey] = value;
+    }
 
     return obj;
 }
EOF
@@ -3,17 +3,33 @@
return path.split('.').reduce((o, k) => (o == null ? undefined : o[k]), obj);
}

function isUnsafeKey(key: string): boolean {
return key === '__proto__' || key === 'constructor' || key === 'prototype';
}

export function setDeep<T = any>(obj: T, path: string, value: any): T {
const parts = path.split('.');
let cursor = obj as any;
for (let i = 0; i < parts.length - 1; i++) {
const p = parts[i];
if (!Object.prototype.hasOwnProperty.call(cursor, p) || typeof cursor[p] !== 'object')
if (isUnsafeKey(p)) {
return obj;
}
if (!Object.prototype.hasOwnProperty.call(cursor, p) || typeof cursor[p] !== 'object') {
cursor[p] = Object.create(null);
}
cursor = cursor[p];
}
if (!Object.prototype.hasOwnProperty.call(cursor, parts[parts.length - 1]) || typeof cursor[parts[parts.length - 1]] !== 'object')
cursor[parts[parts.length - 1]] = value;
const lastKey = parts[parts.length - 1];
if (isUnsafeKey(lastKey)) {
return obj;
}
if (
!Object.prototype.hasOwnProperty.call(cursor, lastKey) ||
typeof cursor[lastKey] !== 'object'
) {
cursor[lastKey] = value;
}

return obj;
}
Copilot is powered by AI and may make mistakes. Always verify output.
// eslint-disable-next-line no-undef
const cli = parseCliArgs(process.argv) ?? {};
const rawFilter = opts.filter ?? cli["worker-filter"] ?? DEFAULT_FILTER;
const filter = typeof rawFilter === "string" ? new RegExp(rawFilter) : rawFilter;

Check failure

Code scanning / CodeQL

Regular expression injection High

This regular expression is constructed from a
command-line argument
.

Copilot Autofix

AI about 20 hours ago

In general, to fix regex injection from command-line or other untrusted input, avoid passing the raw string directly to new RegExp and either (a) escape regex metacharacters so the string is treated as a literal, or (b) strictly validate or whitelist permitted patterns. In this case, the most conservative and backwards-compatible approach is: keep accepting RegExp objects from opts.filter (for intentional complex patterns), but treat the CLI string --worker-filter as a literal substring to match in filenames, escaping regex metacharacters before constructing the RegExp.

Concretely for build/plugin-workers.mjs, we should change the logic on lines 21–23 so that:

  • We distinguish whether the filter originates from opts.filter or from the CLI.
  • If it is a string from the CLI, we escape regex metacharacters before constructing the RegExp.
  • If it is already a RegExp, or a string passed via opts.filter (which is programmatic and presumably trusted), we keep the existing behavior.

Since we are allowed to add well-known dependencies, we can import escapeRegExp from lodash (or lodash.escaperegexp), but that’s not strictly required; we can also implement a simple escape function locally. To minimize changes and dependencies, we can define a small escapeRegExp helper in this file and use it only for CLI-derived string filters, leaving the rest of the functionality intact.

Steps:

  1. In build/plugin-workers.mjs, add a local escapeRegExp function near the top of the file.
  2. Replace the rawFilter / filter construction so that:
    • It first prefers opts.filter (which may be a RegExp or string).
    • If no opts.filter is given and cli["worker-filter"] is present:
      • If it’s a string, escape it and build new RegExp(escapedString).
    • Otherwise fall back to DEFAULT_FILTER.
  3. Ensure that at the end we always have filter as a RegExp (as before) so downstream code does not change behavior except for treating CLI strings as literals.
Suggested changeset 1
build/plugin-workers.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/build/plugin-workers.mjs b/build/plugin-workers.mjs
--- a/build/plugin-workers.mjs
+++ b/build/plugin-workers.mjs
@@ -8,6 +8,18 @@
  */
 
 /**
+ * Escape special characters in a string so it can be used safely inside a RegExp
+ * as a literal pattern.
+ *
+ * This follows the common pattern used by libraries like lodash's _.escapeRegExp.
+ * @param {string} str
+ * @returns {string}
+ */
+function escapeRegExp(str) {
+    return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+}
+
+/**
  * Worker loader plugin factory.
  * Accepts options and CLI override `--worker-filter`.
  * @param {MonacoWorkersOptions} [opts={}]
@@ -19,9 +31,21 @@
         setup(build) {
             // eslint-disable-next-line no-undef
             const cli = parseCliArgs(process.argv) ?? {};
-            const rawFilter = opts.filter ?? cli["worker-filter"] ?? DEFAULT_FILTER;
-            const filter = typeof rawFilter === "string" ? new RegExp(rawFilter) : rawFilter;
 
+            let filter = DEFAULT_FILTER;
+
+            if (opts.filter instanceof RegExp) {
+                // Programmatic RegExp filter is assumed to be trusted
+                filter = opts.filter;
+            } else if (typeof opts.filter === "string") {
+                // Programmatic string filter: preserve existing behavior
+                filter = new RegExp(opts.filter);
+            } else if (typeof cli["worker-filter"] === "string") {
+                // CLI string filter: treat as a literal pattern and escape meta-characters
+                const safeCliFilter = escapeRegExp(cli["worker-filter"]);
+                filter = new RegExp(safeCliFilter);
+            }
+
             build.onResolve({ filter }, (args) => ({ path: args.path, namespace: "worker" }));
 
             build.onLoad({ filter: /.*/, namespace: "worker" }, async (args) => ({
EOF
@@ -8,6 +8,18 @@
*/

/**
* Escape special characters in a string so it can be used safely inside a RegExp
* as a literal pattern.
*
* This follows the common pattern used by libraries like lodash's _.escapeRegExp.
* @param {string} str
* @returns {string}
*/
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

/**
* Worker loader plugin factory.
* Accepts options and CLI override `--worker-filter`.
* @param {MonacoWorkersOptions} [opts={}]
@@ -19,9 +31,21 @@
setup(build) {
// eslint-disable-next-line no-undef
const cli = parseCliArgs(process.argv) ?? {};
const rawFilter = opts.filter ?? cli["worker-filter"] ?? DEFAULT_FILTER;
const filter = typeof rawFilter === "string" ? new RegExp(rawFilter) : rawFilter;

let filter = DEFAULT_FILTER;

if (opts.filter instanceof RegExp) {
// Programmatic RegExp filter is assumed to be trusted
filter = opts.filter;
} else if (typeof opts.filter === "string") {
// Programmatic string filter: preserve existing behavior
filter = new RegExp(opts.filter);
} else if (typeof cli["worker-filter"] === "string") {
// CLI string filter: treat as a literal pattern and escape meta-characters
const safeCliFilter = escapeRegExp(cli["worker-filter"]);
filter = new RegExp(safeCliFilter);
}

build.onResolve({ filter }, (args) => ({ path: args.path, namespace: "worker" }));

build.onLoad({ filter: /.*/, namespace: "worker" }, async (args) => ({
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +28 to +30
contents: `export default function WorkerWrapper(options){ return new Worker(new URL(${JSON.stringify(
args.path
)}, import.meta.url), options); }`,

Check warning

Code scanning / CodeQL

Improper code sanitization Medium

Code construction depends on an
improperly sanitized value
.

Copilot Autofix

AI about 20 hours ago

In general, when constructing JavaScript source code that embeds stringified data, you should apply an additional escaping step to the JSON.stringify result to neutralize characters that can break out of <script> tags or otherwise alter the surrounding JavaScript/HTML context. This is particularly important for <, >, /, backslashes, control characters, and Unicode line/paragraph separators.

The single best fix here is to introduce a small helper function within build/plugin-workers.mjs that escapes unsafe characters in a string (following the pattern from the background example) and then wrap the existing JSON.stringify(args.path) call with this helper. This preserves existing functionality—the generated JavaScript still uses new URL(<string>, import.meta.url)—while ensuring that any unexpected characters in args.path cannot produce malformed or unsafe generated code.

Concretely:

  • Add a const charMap and function escapeUnsafeChars(str) near the top of build/plugin-workers.mjs (after the imports or after the JSDoc typedef, anywhere before use).
  • Change line 28 so that it reads escapeUnsafeChars(JSON.stringify(args.path)) instead of just JSON.stringify(args.path).
  • No new external imports are needed; the helper uses only built-in JavaScript features.
Suggested changeset 1
build/plugin-workers.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/build/plugin-workers.mjs b/build/plugin-workers.mjs
--- a/build/plugin-workers.mjs
+++ b/build/plugin-workers.mjs
@@ -7,7 +7,32 @@
  * @property {RegExp|string} [filter] - Match worker module filenames (RegExp or string pattern)
  */
 
+const charMap = {
+    '<': '\\u003C',
+    '>': '\\u003E',
+    '/': '\\u002F',
+    '\\': '\\\\',
+    '\b': '\\b',
+    '\f': '\\f',
+    '\n': '\\n',
+    '\r': '\\r',
+    '\t': '\\t',
+    '\0': '\\0',
+    '\u2028': '\\u2028',
+    '\u2029': '\\u2029'
+};
+
 /**
+ * Escape potentially unsafe characters in a string that will be embedded
+ * into generated JavaScript source code.
+ * @param {string} str
+ * @returns {string}
+ */
+function escapeUnsafeChars(str) {
+    return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029]/g, (x) => charMap[x] || x);
+}
+
+/**
  * Worker loader plugin factory.
  * Accepts options and CLI override `--worker-filter`.
  * @param {MonacoWorkersOptions} [opts={}]
@@ -25,9 +49,9 @@
             build.onResolve({ filter }, (args) => ({ path: args.path, namespace: "worker" }));
 
             build.onLoad({ filter: /.*/, namespace: "worker" }, async (args) => ({
-                contents: `export default function WorkerWrapper(options){ return new Worker(new URL(${JSON.stringify(
+                contents: `export default function WorkerWrapper(options){ return new Worker(new URL(${escapeUnsafeChars(JSON.stringify(
                     args.path
-                )}, import.meta.url), options); }`,
+                ))}, import.meta.url), options); }`,
                 loader: "js",
             }));
 
EOF
@@ -7,7 +7,32 @@
* @property {RegExp|string} [filter] - Match worker module filenames (RegExp or string pattern)
*/

const charMap = {
'<': '\\u003C',
'>': '\\u003E',
'/': '\\u002F',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};

/**
* Escape potentially unsafe characters in a string that will be embedded
* into generated JavaScript source code.
* @param {string} str
* @returns {string}
*/
function escapeUnsafeChars(str) {
return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029]/g, (x) => charMap[x] || x);
}

/**
* Worker loader plugin factory.
* Accepts options and CLI override `--worker-filter`.
* @param {MonacoWorkersOptions} [opts={}]
@@ -25,9 +49,9 @@
build.onResolve({ filter }, (args) => ({ path: args.path, namespace: "worker" }));

build.onLoad({ filter: /.*/, namespace: "worker" }, async (args) => ({
contents: `export default function WorkerWrapper(options){ return new Worker(new URL(${JSON.stringify(
contents: `export default function WorkerWrapper(options){ return new Worker(new URL(${escapeUnsafeChars(JSON.stringify(
args.path
)}, import.meta.url), options); }`,
))}, import.meta.url), options); }`,
loader: "js",
}));

Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: use default extensions settings are not synced

2 participants