eslint-plugin-chrome-extensions 2.7.0 → 2.8.1

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.
Files changed (42) hide show
  1. package/README.md +272 -44
  2. package/package.json +13 -10
  3. package/src/data/apis.js +74 -88
  4. package/src/data/manifest.js +3 -1
  5. package/src/data/regex.js +2 -1
  6. package/src/index.d.ts +42 -0
  7. package/src/rules/css-spacing.js +29 -21
  8. package/src/rules/manifest-key-order.js +1 -1
  9. package/src/rules/manifest-spacing.js +1 -1
  10. package/src/rules/no-content-style-leak.js +12 -11
  11. package/src/rules/no-deprecated-apis.js +2 -2
  12. package/src/rules/no-host-page-selectors.js +5 -6
  13. package/src/rules/no-inline-event-handlers.js +116 -0
  14. package/src/rules/no-inline-scripts.js +65 -0
  15. package/src/rules/no-insecure-fetch.js +7 -6
  16. package/src/rules/no-insecure-messaging.js +4 -4
  17. package/src/rules/no-invalid-locales.js +3 -5
  18. package/src/rules/no-missing-default-locale.js +1 -1
  19. package/src/rules/no-missing-permissions.js +2 -3
  20. package/src/rules/no-missing-web-accessible-resources.js +2 -2
  21. package/src/rules/no-remote-code.js +77 -28
  22. package/src/rules/no-remote-objects.js +55 -0
  23. package/src/rules/no-remote-urls.js +20 -20
  24. package/src/rules/no-scrollbar-styling.js +8 -10
  25. package/src/rules/no-unrestricted-host-permissions.js +1 -1
  26. package/src/rules/no-unused-permissions.js +5 -4
  27. package/src/rules/require-license-file.js +1 -1
  28. package/src/rules/require-mv3.js +3 -2
  29. package/src/rules/valid-filenames.js +3 -3
  30. package/src/rules/valid-manifest-icons.js +2 -2
  31. package/src/rules/valid-mv3-schema.js +5 -5
  32. package/src/rules/valid-url-fields.js +2 -2
  33. package/src/rules/valid-version-field.js +2 -2
  34. package/src/utils/api.js +20 -0
  35. package/src/utils/extension.js +1 -3
  36. package/src/utils/html.js +29 -0
  37. package/src/utils/i18n.js +2 -2
  38. package/src/utils/init.js +11 -3
  39. package/src/utils/license.js +1 -1
  40. package/src/utils/node.js +3 -1
  41. package/src/utils/pkg.js +19 -2
  42. package/src/utils/rules.js +1 -1
package/README.md CHANGED
@@ -8,8 +8,8 @@
8
8
  <img alt="[License: MIT]" src="https://img.shields.io/badge/License-MIT-f1f20a.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
9
9
  <a target="_blank" href="https://getnpmstats.com/?package=eslint-plugin-chrome-extensions&range=last-year&interval=monthly">
10
10
  <img src="https://img.shields.io/npm/dm/eslint-plugin-chrome-extensions?style=for-the-badge&logo=npm&color=black"></a>
11
- <a target="_blank" href="https://eslint.org/">
12
- <img alt="[Requires ESLint >=9.6.0]" src="https://img.shields.io/badge/Requires-ESLint_%3E%3D9.6.0-4B32C3?style=for-the-badge&logo=eslint"></a>
11
+ <a href="#usage">
12
+ <img alt="[Supports ESLint >=9.6.0 / Oxlint >=1.65.0]" src="https://img.shields.io/badge/Supports-ESLint_%3E%3D9.6.0_%2F_Oxlint_%3E%3D1.65.0-4B32C3?style=for-the-badge&logo=eslint"></a>
13
13
  <br><br>
14
14
 
15
15
  ESLint rules for Chrome extensions.
@@ -33,6 +33,8 @@ npm i -D eslint-plugin-chrome-extensions
33
33
  Usage
34
34
  </h2>
35
35
 
36
+ ### <img height=15 width=auto src="https://www.google.com/s2/favicons?domain=eslint.org&sz=64"> ESLint
37
+
36
38
  Add bundled configs to your `eslint.config.*js` for each file type you need:
37
39
 
38
40
  ```js
@@ -46,31 +48,60 @@ export default [
46
48
  plugins: { 'chrome-extensions': chromeExtensions },
47
49
  rules: {
48
50
  ...chromeExtensions.configs.recommended.rules,
49
- 'chrome-extensions/no-deprecated-apis': 'off' // selectively disable rule
50
- }
51
- },
52
- {
53
- files: ['**/manifest.json'], ...chromeExtensions.configs.manifest,
54
- rules: {
55
- ...chromeExtensions.configs.manifest.rules,
56
- 'chrome-extensions/manifest-spacing': ['warn', { spaces: 4 }] // selectively tweak rule
51
+ 'chrome-extensions/no-deprecated-apis': 'off', // selectively disable rule
52
+ 'chrome-extensions/valid-version-field': ['error', { versionType: 'date' }] // selectively tweak rule
57
53
  }
58
54
  },
59
- { files: ['**/*LICENSE*'], ...chromeExtensions.configs.license },
60
- { files: ['**/extension/**/*.css'], ...chromeExtensions.configs.css },
61
- { files: ['**/extension/**/*.html'], ...chromeExtensions.configs.html },
62
- { files: ['**/extension/**/*.json'], ...chromeExtensions.configs.json },
63
- { files: ['**/extension/**/*.json5'], ...chromeExtensions.configs.json5 },
64
- { files: ['**/extension/**/*.jsonc'], ...chromeExtensions.configs.jsonc }
55
+ { files: ['**/*LICENSE*'], ...chromeExtensions.configs.license },
56
+ { files: ['**/manifest.json'], ...chromeExtensions.configs.manifest },
57
+ { files: ['**/extension/**/*.css'], ...chromeExtensions.configs.css },
58
+ { files: ['**/extension/**/*.html'], ...chromeExtensions.configs.html },
59
+ { files: ['**/extension/**/*.json'], ...chromeExtensions.configs.json },
60
+ { files: ['**/extension/**/*.json5'], ...chromeExtensions.configs.json5 },
61
+ { files: ['**/extension/**/*.jsonc'], ...chromeExtensions.configs.jsonc }
65
62
  ]
66
63
  ```
67
64
 
68
- Available bundles: `recommended`, `strict` (everything), `problem` (deterministic bugs only), `security`, `manifest`, `license`, `css`, `html`, `json`, `json5`, `jsonc`
69
-
70
65
  **Note:** Rule config is either a severity string (`'off'`, `'warn'`, `'error'`) or an array `[severity, options]` when the rule accepts options.
71
66
 
72
67
  ---
73
68
 
69
+ ### <img height=15 width=auto src="https://www.google.com/s2/favicons?domain=oxc.rs&sz=64"> Oxlint
70
+
71
+ Add a JS bundle to your `oxlint.config.ts` (non-JS parsing is unsupported by Oxlint):
72
+
73
+ ```ts
74
+ ...
75
+ import chromeExtensions from 'eslint-plugin-chrome-extensions'
76
+
77
+ export default defineConfig({
78
+ overrides: [
79
+ // other configs
80
+ {
81
+ files: ['**/extension/**/*.{cjs,js,jsx,mjs,ts,tsx}'],
82
+ jsPlugins: ['eslint-plugin-chrome-extensions'],
83
+ rules: {
84
+ ...chromeExtensions.configs.recommended.rules,
85
+ 'chrome-extensions/no-deprecated-apis': 'allow', // selectively disable rule
86
+ 'chrome-extensions/no-insecure-messaging': ['deny', { disallowWildcardTarget: false }] // selectively tweak rule
87
+ }
88
+ }
89
+ ]
90
+ })
91
+ ```
92
+
93
+ **Note:** Rule config is either a severity string (`'allow'`, `'warn'`, `'deny'`) or an array `[severity, options]` when the rule accepts options.
94
+
95
+ **Note:** Oxlint is typically **6-20× faster than ESLint** w/ this plugin (due to its Rust core and parallel file processing).
96
+
97
+ ---
98
+
99
+ *Available JS bundles:* `recommended`, `strict` (everything), `problem` (deterministic bugs only), `security`
100
+
101
+ *Available filetype bundles (ESLint only):* `manifest`, `license`, `css`, `html`, `json`, `json5`, `jsonc`
102
+
103
+ ---
104
+
74
105
  <h2 id="supported-rules">
75
106
  <img height=30 width=27 align="top" src="https://api.iconify.design/mdi/format-list-checks.svg?color=%232b2b2a">
76
107
  Supported rules
@@ -78,8 +109,6 @@ Available bundles: `recommended`, `strict` (everything), `problem` (deterministi
78
109
 
79
110
  <h3 id="css-spacing">
80
111
  <code>css-spacing</code>
81
- <a title="Introduced in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.7.0">
82
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
83
112
  <a title="Only works in 'css/css' config block" href="#usage">
84
113
  <img height=18 alt="[CSS only]" src="https://img.shields.io/badge/CSS_only-dcd6f7?style=flat-square" align="middle"></a>
85
114
  <a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
@@ -506,8 +535,6 @@ If you rely on a Chromium fork resolving duplicate keys in a specific order.
506
535
 
507
536
  <h3 id="no-global-keyframes">
508
537
  <code>no-global-keyframes</code>
509
- <a title="Introduced in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.7.0">
510
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
511
538
  <a title="Only works in 'css/css' config block" href="#usage">
512
539
  <img height=18 alt="[CSS only]" src="https://img.shields.io/badge/CSS_only-dcd6f7?style=flat-square" align="middle"></a>
513
540
  <a title="Accepts array w/ options" href="#usage">
@@ -568,10 +595,155 @@ If your CSS is scoped inside a Shadow DOM root.
568
595
 
569
596
  </details>
570
597
 
598
+ <h3 id="no-inline-event-handlers">
599
+ <code>no-inline-event-handlers</code>
600
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">
601
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
602
+ <a title="Only works in 'html/html' config block" href="#usage">
603
+ <img height=18 alt="[HTML only]" src="https://img.shields.io/badge/HTML_only-a8d8ea?style=flat-square" align="middle"></a>
604
+ <a title="Accepts array w/ options" href="#usage">
605
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
606
+ <a title="Copy rule URL" target="_blank"
607
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-inline-event-handlers">
608
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
609
+ </h3>
610
+
611
+ <details>
612
+
613
+ <summary>Disallows inline event handlers (e.g. <code>onclick</code>, <code>onload</code>) in HTML (blocked by MV3's <code>script-src 'self'</code> at runtime).</summary>
614
+
615
+ <h4 id="no-inline-event-handlers-options">Options</h4>
616
+
617
+ - `allowedAttributes` (default `[]`) – inline event handler attributes to permit (e.g. `['onafterprint']`), as a single string or array <a title="Introduced in v2.8.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0"><img height=14 alt="[Since v2.8.0]" src="https://img.shields.io/badge/since-v2.8.0-8a9199?style=flat-square" align="middle"></a>
618
+
619
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
620
+
621
+ ```diff
622
+ ! <button onclick="alert('hi')">Click</button>
623
+ ! <body onload="init()">
624
+ ! <img src="logo.png" onerror="this.hidden = true">
625
+ ```
626
+
627
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
628
+
629
+ ```diff
630
+ - <button onclick="alert('hi')">Click</button>
631
+ + <button id="myButton">Click</button>
632
+ - <body onload="init()">
633
+ + <body>
634
+ - <img src="logo.png" onerror="this.hidden = true">
635
+ + <img src="logo.png" id="logo">
636
+
637
+ // popup.js
638
+ + document.getElementById('myButton').addEventListener('click', () => alert('hi'))
639
+ + document.addEventListener('DOMContentLoaded', init)
640
+ + document.getElementById('logo').addEventListener('error', event => event.target.hidden = true)
641
+ ```
642
+
643
+ #### When not to use it
644
+
645
+ If your HTML is a <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/sandbox">sandbox page</a> (where the CSP is intentionally relaxed). For individual handlers you still need, prefer `allowedAttributes` over disabling the rule.
646
+
647
+ #### Introduced in
648
+
649
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">v2.8.0</a> (October 20, 2026)
650
+
651
+ #### See also
652
+
653
+ - [`no-inline-scripts`](#no-inline-scripts)
654
+ <a title="Only works in 'html/html' config block" href="#usage"><img height=14 alt="[HTML only]" src="https://img.shields.io/badge/HTML_only-a8d8ea?style=flat-square" align="middle"></a>
655
+ <a title="Accepts array w/ options" href="#no-inline-scripts-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
656
+ - [`no-remote-code`](#no-remote-code)
657
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
658
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
659
+ <a title="Accepts array w/ options" href="#no-remote-code-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
660
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/content-security-policy">Chrome for Developers — `content_security_policy`</a>
661
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src">MDN — CSP `script-src`</a>
662
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener">MDN — `addEventListener()`</a>
663
+
664
+ <div align="center">
665
+
666
+ [Back to index ↑][epce-rules]
667
+
668
+ </div>
669
+
670
+ ---
671
+
672
+ </details>
673
+
674
+ <h3 id="no-inline-scripts">
675
+ <code>no-inline-scripts</code>
676
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">
677
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
678
+ <a title="Only works in 'html/html' config block" href="#usage">
679
+ <img height=18 alt="[HTML only]" src="https://img.shields.io/badge/HTML_only-a8d8ea?style=flat-square" align="middle"></a>
680
+ <a title="Accepts array w/ options" href="#usage">
681
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
682
+ <a title="Copy rule URL" target="_blank"
683
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-inline-scripts">
684
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
685
+ </h3>
686
+
687
+ <details>
688
+
689
+ <summary>Disallows inline <code>&lt;script&gt;</code> bodies and remote <code>&lt;script src&gt;</code> in HTML (blocked by MV3's <code>script-src 'self'</code> at runtime).</summary>
690
+
691
+ <h4 id="no-inline-scripts-options">Options</h4>
692
+
693
+ - `allowedSrcPrefixes` (default `['chrome-extension://']`) – additional `src` prefixes to permit, as a single string or array <a title="Introduced in v2.8.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0"><img height=14 alt="[Since v2.8.0]" src="https://img.shields.io/badge/since-v2.8.0-8a9199?style=flat-square" align="middle"></a>
694
+
695
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
696
+
697
+ ```diff
698
+ ! <script>alert('hi')</script>
699
+ ! <script src="https://cdn.example.com/lib.js"></script>
700
+ ! <script src="//cdn.example.com/lib.js"></script>
701
+ ! <script src="data:text/javascript;base64,YWxlcnQoMSk="></script>
702
+ ```
703
+
704
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
705
+
706
+ ```diff
707
+ - <script>alert('hi')</script>
708
+ + <script src="popup.js"></script>
709
+ - <script src="https://cdn.example.com/lib.js"></script>
710
+ + <script src="./vendor/lib.js"></script>
711
+ - <script src="//cdn.example.com/lib.js"></script>
712
+ + <script type="module" src="popup.js"></script>
713
+ - <script src="data:text/javascript;base64,YWxlcnQoMSk="></script>
714
+ + <script src="chrome-extension://abc123/popup.js"></script>
715
+ ```
716
+
717
+ #### When not to use it
718
+
719
+ If your HTML is a <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/sandbox">sandbox page</a> (where the CSP is intentionally relaxed).
720
+
721
+ #### Introduced in
722
+
723
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">v2.8.0</a> (October 20, 2026)
724
+
725
+ #### See also
726
+
727
+ - [`no-remote-code`](#no-remote-code)
728
+ <a title="Included in recommended config" href="#usage"><img height=14 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
729
+ <a title="Included in security config" href="#usage"><img height=14 alt="[Security]" src="https://img.shields.io/badge/Security-e8357a?style=flat-square" align="middle"></a>
730
+ <a title="Accepts array w/ options" href="#no-remote-code-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
731
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/content-security-policy">Chrome for Developers — `content_security_policy`</a>
732
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src">MDN — CSP `script-src`</a>
733
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script">MDN — `<script>` element</a>
734
+
735
+ <div align="center">
736
+
737
+ [Back to index ↑][epce-rules]
738
+
739
+ </div>
740
+
741
+ ---
742
+
743
+ </details>
744
+
571
745
  <h3 id="no-host-page-selectors">
572
746
  <code>no-host-page-selectors</code>
573
- <a title="Introduced in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.7.0">
574
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
575
747
  <a title="Only works in 'css/css' config block" href="#usage">
576
748
  <img height=18 alt="[CSS only]" src="https://img.shields.io/badge/CSS_only-dcd6f7?style=flat-square" align="middle"></a>
577
749
  <a title="Accepts array w/ options" href="#usage">
@@ -681,7 +853,10 @@ If you intentionally target HTTP endpoints.
681
853
 
682
854
  #### See also
683
855
 
856
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=rfc-editor.org&sz=64">&ensp;<a target="_blank" href="https://www.rfc-editor.org/info/rfc9110/">RFC 9110 — HTTP Semantics</a>
684
857
  - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/develop/concepts/network-requests">Chrome for Developers — Cross-origin network requests</a>
858
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open">MDN — `XMLHttpRequest.open()`</a>
859
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch">MDN — `fetch()`</a>
685
860
 
686
861
  <div align="center">
687
862
 
@@ -929,8 +1104,6 @@ If you don't want permission validation at all. For custom permissions from a Ch
929
1104
 
930
1105
  <h3 id="no-missing-default-locale">
931
1106
  <code>no-missing-default-locale</code>
932
- <a title="JS support + new option added in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">
933
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
934
1107
  <a title="Included in recommended config" href="#usage">
935
1108
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
936
1109
  <a title="Works in 'json/json' config block" href="#usage">
@@ -1257,7 +1430,7 @@ If your paths are built at runtime.
1257
1430
 
1258
1431
  <h4 id="no-remote-code-options">Options</h4>
1259
1432
 
1260
- - `patterns` (default `['eval', 'new-function', 'string-timer', 'dynamic-import', 'remote-script-src', 'execute-script-url']`) – detection paths to enable, as a single string or array <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-8a9199?style=flat-square&labelColor=464646" align="middle"></a>
1433
+ - `patterns` (default `['dynamic-import', 'eval', 'execute-script-url', 'inline-event-handler', 'inline-script-body', 'new-function', 'remote-script-src', 'string-timer']`) – detection paths to enable, as a single string or array <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-8a9199?style=flat-square&labelColor=464646" align="middle"></a>
1261
1434
  - `checkExecuteScriptClosures` (default `true`) – additionally flag <code>chrome.scripting.executeScript({ func })</code> bodies that capture outer-scope variables <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0"><img height=14 alt="[Since v1.0.0]" src="https://img.shields.io/badge/since-v1.0.0-8a9199?style=flat-square&labelColor=464646" align="middle"></a>
1262
1435
 
1263
1436
  #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
@@ -1306,10 +1479,76 @@ If you intentionally target forks w/ relaxed CSPs. For individual patterns you s
1306
1479
 
1307
1480
  </details>
1308
1481
 
1482
+ <h3 id="no-remote-objects">
1483
+ <code>no-remote-objects</code>
1484
+ <a title="Introduced in latest minor release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">
1485
+ <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1486
+ <a title="Only works in 'html/html' config block" href="#usage">
1487
+ <img height=18 alt="[HTML only]" src="https://img.shields.io/badge/HTML_only-a8d8ea?style=flat-square" align="middle"></a>
1488
+ <a title="Accepts array w/ options" href="#usage">
1489
+ <img height=18 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1490
+ <a title="Copy rule URL" target="_blank"
1491
+ href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-chrome-extensions%2F%23no-remote-objects">
1492
+ <img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
1493
+ </h3>
1494
+
1495
+ <details>
1496
+
1497
+ <summary>Disallows remote <code>&lt;object data&gt;</code> and <code>&lt;embed src&gt;</code> in HTML (blocked by MV3's <code>object-src 'self'</code> at runtime).</summary>
1498
+
1499
+ <h4 id="no-remote-objects-options">Options</h4>
1500
+
1501
+ - `allowedPrefixes` (default `['chrome-extension://']`) – additional URL prefixes to permit, as a single string or array <a title="Introduced in v2.8.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0"><img height=14 alt="[Since v2.8.0]" src="https://img.shields.io/badge/since-v2.8.0-8a9199?style=flat-square" align="middle"></a>
1502
+
1503
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect code
1504
+
1505
+ ```diff
1506
+ ! <object data="https://cdn.example.com/report.pdf"></object>
1507
+ ! <embed src="http://cdn.example.com/game.swf">
1508
+ ! <object data="//cdn.example.com/chart.svg"></object>
1509
+ ```
1510
+
1511
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct code
1512
+
1513
+ ```diff
1514
+ - <object data="https://cdn.example.com/report.pdf"></object>
1515
+ + <object data="report.pdf"></object>
1516
+ - <embed src="http://cdn.example.com/game.swf">
1517
+ + <embed src="./vendor/game.swf">
1518
+ - <object data="//cdn.example.com/chart.svg"></object>
1519
+ + <object data="chrome-extension://abc123/chart.svg"></object>
1520
+ ```
1521
+
1522
+ #### When not to use it
1523
+
1524
+ If your HTML is a <a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/sandbox">sandbox page</a> (where the CSP is intentionally relaxed).
1525
+
1526
+ #### Introduced in
1527
+
1528
+ <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.8.0">v2.8.0</a> (October 20, 2026)
1529
+
1530
+ #### See also
1531
+
1532
+ - [`no-inline-scripts`](#no-inline-scripts)
1533
+ <a title="Only works in 'html/html' config block" href="#usage"><img height=14 alt="[HTML only]" src="https://img.shields.io/badge/HTML_only-a8d8ea?style=flat-square" align="middle"></a>
1534
+ <a title="Accepts array w/ options" href="#no-inline-scripts-options"><img height=14 alt="[Configurable]" src="https://img.shields.io/badge/Configurable-black?style=flat-square" align="middle"></a>
1535
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.chrome.com&sz=64">&ensp;<a target="_blank" href="https://developer.chrome.com/docs/extensions/reference/manifest/content-security-policy">Chrome for Developers — `content_security_policy`</a>
1536
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/object-src">MDN — CSP `object-src`</a>
1537
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/object">MDN — `<object>` element</a>
1538
+ - <img height=12 src="https://www.google.com/s2/favicons?domain=developer.mozilla.org&sz=64">&ensp;<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/embed">MDN — `<embed>` element</a>
1539
+
1540
+ <div align="center">
1541
+
1542
+ [Back to index ↑][epce-rules]
1543
+
1544
+ </div>
1545
+
1546
+ ---
1547
+
1548
+ </details>
1549
+
1309
1550
  <h3 id="no-remote-urls">
1310
1551
  <code>no-remote-urls</code>
1311
- <a title="Introduced in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.7.0">
1312
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1313
1552
  <a title="Only works in 'css/css' config block" href="#usage">
1314
1553
  <img height=18 alt="[CSS only]" src="https://img.shields.io/badge/CSS_only-dcd6f7?style=flat-square" align="middle"></a>
1315
1554
  <a title="Accepts array w/ options" href="#usage">
@@ -1386,8 +1625,6 @@ If you intentionally reference remote stylesheets, fonts, or images (e.g. Google
1386
1625
 
1387
1626
  <h3 id="no-scrollbar-styling">
1388
1627
  <code>no-scrollbar-styling</code>
1389
- <a title="Introduced in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.7.0">
1390
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1391
1628
  <a title="Only works in 'css/css' config block" href="#usage">
1392
1629
  <img height=18 alt="[CSS only]" src="https://img.shields.io/badge/CSS_only-dcd6f7?style=flat-square" align="middle"></a>
1393
1630
  <a title="Accepts array w/ options" href="#usage">
@@ -1530,8 +1767,6 @@ If you legitimately require sensitive permissions, or prefer manual security rev
1530
1767
 
1531
1768
  <h3 id="no-unrestricted-host-permissions">
1532
1769
  <code>no-unrestricted-host-permissions</code>
1533
- <a title="JS support added in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">
1534
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1535
1770
  <a title="Included in recommended config" href="#usage">
1536
1771
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1537
1772
  <a title="Included in security config" href="#usage">
@@ -1675,8 +1910,6 @@ If your i18n keys are referenced dynamically.
1675
1910
  <code>no-unused-permissions</code>
1676
1911
  <a title="Introduced in v1.0.0" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v1.0.0">
1677
1912
  <img height=18 align="middle" src="https://api.iconify.design/ph/flag-banner-fold-fill.svg?color=%234a4a4a"></a>
1678
- <a title="JS support added in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">
1679
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
1680
1913
  <a title="Included in recommended config" href="#usage">
1681
1914
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
1682
1915
  <a title="Works in 'json/json' config block" href="#usage">
@@ -1755,14 +1988,13 @@ If you access the granted API through an alias or computed property rather than
1755
1988
 
1756
1989
  <summary>Requires a license file.</summary>
1757
1990
 
1758
- #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect directory structure
1991
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/gray.svg" align="bottom"> Incorrect dir structure
1759
1992
 
1760
1993
  ```diff
1761
1994
  /extension/manifest.json
1762
- !
1763
1995
  ```
1764
1996
 
1765
- #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct directory structure
1997
+ #### <img width=13 height=13 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/99f14247b2/assets/images/icons/square/with-symbol/green.svg" align="bottom"> Correct dir structure
1766
1998
 
1767
1999
  ```diff
1768
2000
  /extension/manifest.json
@@ -2081,8 +2313,6 @@ If your license is injected at build time, or you use one w/ no existing SPDX id
2081
2313
 
2082
2314
  <h3 id="valid-manifest-icons">
2083
2315
  <code>valid-manifest-icons</code>
2084
- <a title="JS support added in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">
2085
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
2086
2316
  <a title="Included in recommended config" href="#usage">
2087
2317
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
2088
2318
  <a title="Works in 'json/json' config block" href="#usage">
@@ -2300,8 +2530,6 @@ If your background context isn't a service worker.
2300
2530
 
2301
2531
  <h3 id="valid-url-fields">
2302
2532
  <code>valid-url-fields</code>
2303
- <a title="JS support added in recent release" target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/releases/tag/v2.6.0">
2304
- <img height=16 align="middle" src="https://api.iconify.design/mdi/sprout.svg?color=%234a4a4a"></a>
2305
2533
  <a title="Included in recommended config" href="#usage">
2306
2534
  <img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
2307
2535
  <a title="Works in 'json/json' config block" href="#usage">
@@ -2467,8 +2695,8 @@ If you don't care about version format consistency, or your version is injected
2467
2695
 
2468
2696
  ## <img height=30 width=27 align="top" src="https://api.iconify.design/ic/baseline-account-balance.svg?color=%232b2b2a"> License
2469
2697
 
2470
- <a target="_blank" href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/src/branch/main/docs/LICENSE.md">
2471
- <img height=80 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-greasemonkey/9e820e5d51/assets/images/logos/mit-license/red-pixelated.png"></a>
2698
+ <a href="https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/src/branch/main/docs/LICENSE.md">
2699
+ <img height=88 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-chrome-extensions/d79e1db7e2/assets/images/banners/mit-license/banner.png"></a>
2472
2700
  <br><br>
2473
2701
 
2474
2702
  <details>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-chrome-extensions",
3
- "version": "2.7.0",
3
+ "version": "2.8.1",
4
4
  "description": "ESLint rules for Chrome extensions",
5
5
  "keywords": [
6
6
  "eslint",
@@ -8,6 +8,8 @@
8
8
  "eslintplugin",
9
9
  "chrome-extensions",
10
10
  "chromium",
11
+ "oxlint",
12
+ "oxlint-plugin",
11
13
  "security"
12
14
  ],
13
15
  "homepage": "https://codeberg.org/adamlui/eslint-plugin-chrome-extensions/#readme",
@@ -53,10 +55,10 @@
53
55
  "bump:major": "bash utils/bump.sh major",
54
56
  "bump:minor": "bash utils/bump.sh minor",
55
57
  "bump:patch": "bash utils/bump.sh patch",
56
- "demo": "node demo/run.js",
58
+ "demo": "eslint demo",
57
59
  "lint": "pre-commit run",
58
60
  "lint:all": "pre-commit run --all-files",
59
- "test": "node tests/run.js"
61
+ "test": "node tests/run"
60
62
  },
61
63
  "dependencies": {
62
64
  "globals": "^17.13.0",
@@ -65,24 +67,25 @@
65
67
  },
66
68
  "devDependencies": {
67
69
  "@e18e/eslint-plugin": "^0.8.1",
68
- "@eslint/css": "^2.0.0",
69
- "@eslint/js": "^10.0.1",
70
+ "@eslint/css": "^2.0.1",
70
71
  "@eslint/json": "^2.1.1",
71
72
  "@eslint/markdown": "^7.5.1",
72
73
  "@html-eslint/eslint-plugin": "^0.67.0",
73
74
  "@stylistic/eslint-plugin": "^5.10.0",
74
- "eslint": "^10.12.0",
75
- "eslint-plugin-constructors": "^1.4.3",
75
+ "eslint": "^10.13.0",
76
+ "eslint-plugin-constructors": "^1.5.1",
76
77
  "eslint-plugin-eslint-plugin": "^7.6.2",
77
78
  "eslint-plugin-import-x": "^4.17.1",
78
- "eslint-plugin-n": "^18.4.1",
79
+ "eslint-plugin-n": "^18.5.0",
79
80
  "eslint-plugin-no-secrets": "^2.3.3",
80
81
  "eslint-plugin-no-unsanitized": "^4.1.5",
81
- "eslint-plugin-package-json": "^1.10.1",
82
+ "eslint-plugin-package-json": "^1.11.0",
82
83
  "eslint-plugin-promise": "^7.3.0",
83
84
  "eslint-plugin-regexp": "^3.3.1",
84
85
  "eslint-plugin-security": "^4.2.0",
85
- "eslint-plugin-woodpecker": "^1.0.0"
86
+ "eslint-plugin-sonarjs": "^4.2.2",
87
+ "eslint-plugin-woodpecker": "^1.1.1",
88
+ "oxlint": "^1.89.0"
86
89
  },
87
90
  "peerDependencies": {
88
91
  "@eslint/css": ">=0.5.0",