Skip to content

Upgrade to MM eslint-config-* v15 + ESLint 9#168

Open
mcmire wants to merge 15 commits intomainfrom
eslint-9
Open

Upgrade to MM eslint-config-* v15 + ESLint 9#168
mcmire wants to merge 15 commits intomainfrom
eslint-9

Conversation

@mcmire
Copy link
Copy Markdown
Contributor

@mcmire mcmire commented Feb 26, 2025

The ESLint configuration is behind for this package. Keeping up to date with our current lint rules and lint config format helps to debug issues with ESLint now and in the future, and aligns this repo with our other repos.

A list of changes:

  • Upgrade @metamask/eslint-config and @metamask/eslint-config-* packages to 15.0.0
  • Upgrade ESLint to 9.x
  • Upgrade TypeScript ESLint packages to 8.25.x
  • Upgrade other ESLint packages to fulfill peer dependencies
  • Fix lint violations as a result of the upgrade
  • Ensure that all configuration files are being linted (some, such as the Babel config file, were being excluded)

Note that the rules for jsdoc/require-jsdoc have been refined. In performing this upgrade, many violations appeared that I thought didn't help readability. We may consider porting these back to the eslint-config repo.


Note

Medium Risk
Moderate risk because it upgrades the linting toolchain/config format (ESLint 9, TypeScript-ESLint 8, import plugin swap), which can change CI lint results and required code patterns, plus it includes small type/signature tweaks across core modules.

Overview
Upgrades the linting stack to ESLint 9 and @metamask/eslint-config-* v15, migrating from .eslintrc.cjs to a new flat config in eslint.config.mjs with updated overrides (Node/Jest/Browser/React) and refined JSDoc requirements/restrictions.

Updates package.json lint scripts/dependencies (including moving to eslint-plugin-import-x and related peers) and adds targeted code changes to satisfy new rules: explicit return types, safer error stringification via getErrorMessage, IncrementableVersionParts changed from enum to as const + union type, SemVer string usage standardized to .version, and various small async/typing/refactor tweaks across CLI/UI/tests.

Written by Cursor Bugbot for commit 2b2bb0a. This will update automatically on new commits. Configure here.

@socket-security
Copy link
Copy Markdown

socket-security bot commented Dec 10, 2025

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Block High
High CVE: npm @isaacs/brace-expansion has Uncontrolled Resource Consumption

CVE: GHSA-7h2j-956f-4vf2 @isaacs/brace-expansion has Uncontrolled Resource Consumption (HIGH)

Affected versions: < 5.0.1

Patched version: 5.0.1

From: ?npm/eslint-plugin-import-x@4.16.1npm/@isaacs/brace-expansion@5.0.0

ℹ Read more on: This package | This alert | What is a CVE?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Remove or replace dependencies that include known high severity CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@isaacs/brace-expansion@5.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm eslint-plugin-n in module dns

Module: dns

Location: Package overview

From: package.jsonnpm/eslint-plugin-n@17.23.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/eslint-plugin-n@17.23.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm eslint-plugin-n in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/eslint-plugin-n@17.23.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/eslint-plugin-n@17.23.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm @napi-rs/wasm-runtime is 100.0% likely to have a medium risk anomaly

Notes: The fragment appears to implement a substantial WASI/N-API bridge with comprehensive memory and filesystem interfacing. There is no concrete evidence of malicious payloads such as data exfiltration, backdoors, or remote command execution in this snippet. The primary concerns relate to the unusual in-browser input path (readStdin) and the large surface area for data flows across threads and FFI boundaries. A targeted, broader audit of the complete module and any wasm payloads loaded through these bindings is recommended to ensure rights enforcement and memory safety. Overall risk is moderate but current evidence does not indicate active malware.

Confidence: 1.00

Severity: 0.60

From: ?npm/eslint-import-resolver-typescript@3.10.1npm/eslint-plugin-import-x@4.16.1npm/@napi-rs/wasm-runtime@0.2.12

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@napi-rs/wasm-runtime@0.2.12. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm acorn is 100.0% likely to have a medium risk anomaly

Notes: Overall, the analyzed code is a legitimate, well-structured Acorn 8.x parser fragment with robust handling for ES2020+ features. There is no direct malicious payload, backdoor, or exfiltration mechanism within this fragment. The primary security considerations relate to safe handling of untrusted input to avoid DoS via complex/ pathological RegExp usage or verbose error reporting. In a typical extension usage, isolate parsing to a sandbox and limit resource usage to mitigate potential abuse.

Confidence: 1.00

Severity: 0.60

From: ?npm/eslint@9.39.2npm/eslint-plugin-jsdoc@50.8.0npm/acorn@8.15.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/acorn@8.15.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm flat-cache is 100.0% likely to have a medium risk anomaly

Notes: The code implements a filesystem-backed cache with potential path traversal vulnerabilities due to unvalidated docId/cacheDir inputs that influence file paths. While not inherently malicious, the lack of input sanitization creates risk of reading/writing/deleting arbitrary files, especially in a public package context where inputs could be user-controlled. No evidence of deliberate malware or obfuscated logic is present, but the security risk due to path handling is non-trivial and should be mitigated by validating and constraining input paths, using safe defaults, and isolating cache storage.

Confidence: 1.00

Severity: 0.60

From: ?npm/eslint@9.39.2npm/flat-cache@4.0.1

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/flat-cache@4.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm ignore is 100.0% likely to have a medium risk anomaly

Notes: The code fragment represents a conventional, well-structured path-ignore utility with caching and recursive parent-directory evaluation. Windows path normalization is present for compatibility but does not indicate malicious intent. No indicators of data leakage, external communication, or covert backdoors were found. Security impact primarily revolves around correct ignore semantics rather than intrinsic vulnerabilities. The component remains appropriate for use in a broader security-conscious pipeline if used with careful awareness of what is being ignored.

Confidence: 1.00

Severity: 0.60

From: ?npm/@typescript-eslint/eslint-plugin@8.52.0npm/ignore@7.0.5

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ignore@7.0.5. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Ignoring alerts on:

  • unrs-resolver@1.11.1
  • @unrs/resolver-binding-wasm32-wasi@1.11.1
  • napi-postinstall@0.3.4
  • @emnapi/core@1.8.1
  • @tybys/wasm-util@0.10.1

View full report

@mcmire mcmire changed the title WIP - Upgrade to ESLint 9 Upgrade to MM eslint-config-* v15 + ESLint 9 Dec 11, 2025
@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/@emnapi/core@1.7.1

This package is used to read WASM files, which require the use of fetch.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/@tybys/wasm-util@0.10.1

This package is also used to read WASM files, which requires the use of fetch.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/unrs-resolver@1.11.1

This PR disables the post-install script for this package.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/@unrs/resolver-binding-wasm32-wasi@1.11.1

This package is also used to read WASM files, which requires the use of fetch.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/@typescript-eslint/typescript-estree@8.49.0

This is a known false positive.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/@typescript-eslint/utils@8.49.0

This is a known false positive.

The ESLint configuration is behind for this package. Keeping up to date
with our current lint rules and lint config format helps to debug issues
with ESLint now and in the future, and aligns this repo with our other
repos.

A list of changes:

- Upgrade `@metamask/eslint-config` and `@metamask/eslint-config-*`
  packages to 15.0.0
- Upgrade ESLint to 9.x
- Upgrade TypeScript ESLint packages to 8.25.x
- Upgrade other ESLint packages to fulfill peer dependencies
- Fix lint violations as a result of the upgrade

Note that the rules for `jsdoc/require-jsdoc` have been refined. In
performing this upgrade, many violations appeared that I thought didn't
help readability.
@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Dec 11, 2025

@SocketSecurity ignore npm/napi-postinstall@0.3.4

This package seems to download packages from the NPM registry as one of its tasks.

It is used by unrs-resolver, which calls napi-postinstall in its postinstall script: https://socket.dev/npm/package/unrs-resolver/files/1.11.1/package.json#T551-596. But we have disabled that script, so no network access should be occurring.

@mcmire mcmire marked this pull request as ready for review December 11, 2025 19:49
@mcmire mcmire requested a review from a team as a code owner December 11, 2025 19:49
src/editor.ts Outdated
* @property path - The path to the executable representing the editor.
* @property args - Command-line arguments to pass to the executable when
* calling it.
* Properties:
Copy link
Copy Markdown
Contributor Author

@mcmire mcmire Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@property is now no longer allowed as a tag. I wanted a consistent way that we could document properties going forward, accounting for intersections or unions, so I made up this format. Let me know what you think.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the way to do it is to add inline comments?

{
  /**
   * The foo property.
   */
  foo: string;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would work for properties that appear because of object types. But if you bring in other properties via unions or intersections, then those properties won't be documented. I figured it was helpful to document all properties of a type, not ones that are "uninherited" — is that a desire?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but in this case all properties can be documended inline, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure I'm following. Properties that are inherited cannot be documented inline. For instance, when hovering over this type or generating docs for this type, only bar will show up as a property, but foo will be hidden.

type Base = {
  /**
   * The 'foo' property.
   */
  foo: 'bar'
}

/**
 * The Foo type.
 */
type Foo = Base & {
  /**
   * The 'bar' property.
   */
  bar: 'baz'
}

What I am proposing is a way to consistently document all properties of a type, e.g.:

/**
 * The Foo type.
 *
 * Properties:
 *
 * - `foo` - The 'foo' property.
 * - `bar` - The 'bar' property.
 */
type Foo = Base & {
  bar: 'baz'
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that would make more sense to use @property. I believe a while back I tried to propose this, but I don't remember what the argument against it was.

I know that the jsdoc plugin has a rule check-tag-names
that prohibits this, but we could disable it.

@Gudahtt Do you have an opinion on this?

Copy link
Copy Markdown
Member

@Gudahtt Gudahtt Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hesitant about @property because it's not supported by TSDoc, so some tooling might not work with it. But if Intellisense supports it, it sounds like a good alternative when inline blocks aren't feasible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit confusing; there's typedoc and then there's TSDoc, which is a standard that Microsoft made (as a TypeScript-specific version of JSDoc, presumably). TSDoc doesn't support @property, but you can also add custom tags: https://tsdoc.org/pages/packages/tsdoc-config/

We don't need to worry about TSDoc yet, but it's a good point to keep it in mind.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I replaced these with the use of @property: 4331589. I had to disable the check-tag-names rule (or rather, disable the type-aware checks within this rule) because it doesn't allow us to disable checking @property, it will complain. I used no-restricted-syntax to get around this.

*
* @returns The corresponding mock functions for each of the dependencies.
*/
function getDependencySpies() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing out the return type for this function was going to be a huge chore, so I refactored the setup of these mocks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntelliJ has a quick option for it to add the return type explicitly which mostly works, with small modifications sometimes. But your refactor looks good to me too.

minor = 'minor',
patch = 'patch',
}
export const IncrementableVersionParts = {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to convert this to a "quasi-enum" as it made it easier to adapt to the new lint violations.


rules: {
// Consider copying this to @metamask/eslint-config
'jsdoc/require-jsdoc': [
Copy link
Copy Markdown
Contributor Author

@mcmire mcmire Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated in the PR description, I found the new changes to this rule in MetaMask/eslint-config#394 rather strict. I removed TSPropertySignature as it began asking that properties in adhoc object types were documented. For instance:

function foo(): {
  // This is now required to be documented
  bar: string;
} {
  // ...
}

I also found a similar thing for arrow functions:

// The arrow function here is now required to be documented
foo(() => {
  // ...
})


foo({
  // The arrow function here is now required to be documented
  bar: () => {
    // ...
  }
})

So, I amended what this rule is looking for, which is explained in the comments below. I feel like this makes more sense, but happy to know y'all's thoughts.

Copy link
Copy Markdown
Contributor Author

@mcmire mcmire Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference, I used https://astexplorer.net/ to test out the selectors (make sure to select @typescript-eslint/parser and Transform > ESLint v8).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this makes a lot of sense to me. We should definitely upstream this.

},
],
// Consider copying this to @metamask/eslint-config
'jsdoc/no-blank-blocks': 'error',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that this existed and I found this to be a helpful rule. It seemed that with the new JSDoc rules, running yarn eslint --fix added a bunch of empty JSDoc blocks to various symbols. With this enabled, I was able to quickly find those and fill them in.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, definitely in favour of moving this to eslint-config, but maybe release a fix with non-breaking changes first.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point.

'@typescript-eslint/explicit-function-return-type': [
'error',
{
allowExpressions: true,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I found that this new rule was too strict. For instance:

return {
  // A return type is now required for this function
  message: () => 'foo',
  pass: false,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know there was an option for this. It definitely was a bit too strict in these cases, so this looks great.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered suggesting this option as well. I didn't ultimately because there are some function expressions that are complex where a return type would be useful, so I wasn't sure it was what we wanted.

But still, while imperfect, it seems like a good compromise.

Mrtenz
Mrtenz previously approved these changes Jan 9, 2026
]);

// Consider copying this to @metamask/eslint-config
const requireJsdocOverride = {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated these rules again. Now we don't require JSDoc for type interfaces, type aliases, enums, or classes defined within other scopes. The selector for ArrowFunctionExpression and FunctionExpression are also fixed as they had bugs.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Jan 9, 2026

@SocketSecurity ignore npm/globals@14.0.0

This just exports a JSON file, it does not make fetch calls.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Jan 9, 2026

@SocketSecurity ignore npm/@emnapi/core@1.8.1

This package loads WASM code and requires the use of fetch to do this.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Jan 9, 2026

@SocketSecurity ignore npm/globals@15.15.0

This just exports a JSON file, it does not make fetch calls.

@mcmire
Copy link
Copy Markdown
Contributor Author

mcmire commented Jan 9, 2026

Updated to fix merge conflicts.

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.

3 participants