From de540ac6b4a6b3244653855397fdc25087d7b506 Mon Sep 17 00:00:00 2001 From: oxc-bot <176400334+oxc-bot@users.noreply.github.com> Date: Mon, 23 Sep 2024 07:03:02 +0000 Subject: [PATCH] Release 0.9.7 --- src/docs/guide/usage/linter/generated-cli.md | 2 + .../guide/usage/linter/generated-config.md | 8 +++ .../guide/usage/linter/generated-rules.md | 17 +++-- .../linter/rules/eslint/no-extend-native.md | 53 ++++++++++++++ .../linter/rules/eslint/no-regex-spaces.md | 3 + .../rules/eslint/no-unexpected-multiline.md | 55 ++++++++++++++ .../usage/linter/rules/promise/avoid-new.md | 26 +++++-- .../linter/rules/promise/catch-or-return.md | 10 +-- .../usage/linter/rules/security/api-keys.md | 72 +++++++++++++++++++ 9 files changed, 229 insertions(+), 17 deletions(-) create mode 100644 src/docs/guide/usage/linter/rules/eslint/no-extend-native.md create mode 100644 src/docs/guide/usage/linter/rules/eslint/no-unexpected-multiline.md create mode 100644 src/docs/guide/usage/linter/rules/security/api-keys.md diff --git a/src/docs/guide/usage/linter/generated-cli.md b/src/docs/guide/usage/linter/generated-cli.md index 9ce07466fa..ad1d791dbc 100644 --- a/src/docs/guide/usage/linter/generated-cli.md +++ b/src/docs/guide/usage/linter/generated-cli.md @@ -65,6 +65,8 @@ Arguments: Enable the promise plugin and detect promise usage problems - **` --node-plugin`** — Enable the node plugin and detect node usage problems +- **` --security-plugin`** — + Enable the security plugin and detect security problems ## Fix Problems diff --git a/src/docs/guide/usage/linter/generated-config.md b/src/docs/guide/usage/linter/generated-config.md index 2e27198895..b92598d8d9 100644 --- a/src/docs/guide/usage/linter/generated-config.md +++ b/src/docs/guide/usage/linter/generated-config.md @@ -61,6 +61,14 @@ Globals can be disabled by setting their value to `"off"`. For example, in an en You may also use `"readable"` or `false` to represent `"readonly"`, and `"writeable"` or `true` to represent `"writable"`. +## plugins + +type: `array` + +### plugins[n] + +type: `string` + ## rules type: `object` diff --git a/src/docs/guide/usage/linter/generated-rules.md b/src/docs/guide/usage/linter/generated-rules.md index 21c03ccebb..81ca2bd103 100644 --- a/src/docs/guide/usage/linter/generated-rules.md +++ b/src/docs/guide/usage/linter/generated-rules.md @@ -2,10 +2,10 @@ The progress of all rule implementations is tracked [here](https://github.com/oxc-project/oxc/issues/481). -- Total number of rules: 429 +- Total number of rules: 432 - Rules turned on by default: 96 -## Correctness (169): +## Correctness (170): Code that is outright wrong or useless. | Rule name | Source | Default | Fixable? | @@ -154,6 +154,7 @@ Code that is outright wrong or useless. | [no-render-return-value](/docs/guide/usage/linter/rules/react/no-render-return-value.html) | react | ✅ | | | [no-string-refs](/docs/guide/usage/linter/rules/react/no-string-refs.html) | react | ✅ | | | [void-dom-elements-no-children](/docs/guide/usage/linter/rules/react/void-dom-elements-no-children.html) | react | ✅ | | +| [api-keys](/docs/guide/usage/linter/rules/security/api-keys.html) | security | | | | [no-duplicate-enum-values](/docs/guide/usage/linter/rules/typescript/no-duplicate-enum-values.html) | typescript | ✅ | | | [no-extra-non-null-assertion](/docs/guide/usage/linter/rules/typescript/no-extra-non-null-assertion.html) | typescript | ✅ | | | [no-misused-new](/docs/guide/usage/linter/rules/typescript/no-misused-new.html) | typescript | ✅ | | @@ -192,7 +193,7 @@ Code that can be written to run faster. | [jsx-no-new-function-as-prop](/docs/guide/usage/linter/rules/react_perf/jsx-no-new-function-as-prop.html) | react_perf | | | | [jsx-no-new-object-as-prop](/docs/guide/usage/linter/rules/react_perf/jsx-no-new-object-as-prop.html) | react_perf | | | -## Restriction (58): +## Restriction (57): Lints which prevent the use of language and library features. Must not be enabled as a whole, should be considered on a case-by-case basis before enabling. | Rule name | Source | Default | Fixable? | @@ -209,7 +210,7 @@ Lints which prevent the use of language and library features. Must not be enable | [no-iterator](/docs/guide/usage/linter/rules/eslint/no-iterator.html) | eslint | | 🚧 | | [no-plusplus](/docs/guide/usage/linter/rules/eslint/no-plusplus.html) | eslint | | 🚧 | | [no-proto](/docs/guide/usage/linter/rules/eslint/no-proto.html) | eslint | | 🚧 | -| [no-regex-spaces](/docs/guide/usage/linter/rules/eslint/no-regex-spaces.html) | eslint | | | +| [no-regex-spaces](/docs/guide/usage/linter/rules/eslint/no-regex-spaces.html) | eslint | | 🚧 | | [no-restricted-globals](/docs/guide/usage/linter/rules/eslint/no-restricted-globals.html) | eslint | | | | [no-undefined](/docs/guide/usage/linter/rules/eslint/no-undefined.html) | eslint | | | | [no-unsafe-optional-chaining](/docs/guide/usage/linter/rules/eslint/no-unsafe-optional-chaining.html) | eslint | | | @@ -229,7 +230,6 @@ Lints which prevent the use of language and library features. Must not be enable | [no-const-enum](/docs/guide/usage/linter/rules/oxc/no-const-enum.html) | oxc | | 🛠️ | | [no-optional-chaining](/docs/guide/usage/linter/rules/oxc/no-optional-chaining.html) | oxc | | | | [no-rest-spread-properties](/docs/guide/usage/linter/rules/oxc/no-rest-spread-properties.html) | oxc | | | -| [avoid-new](/docs/guide/usage/linter/rules/promise/avoid-new.html) | promise | | | | [catch-or-return](/docs/guide/usage/linter/rules/promise/catch-or-return.html) | promise | | | | [spec-only](/docs/guide/usage/linter/rules/promise/spec-only.html) | promise | | | | [button-has-type](/docs/guide/usage/linter/rules/react/button-has-type.html) | react | | | @@ -256,12 +256,14 @@ Lints which prevent the use of language and library features. Must not be enable | [prefer-node-protocol](/docs/guide/usage/linter/rules/unicorn/prefer-node-protocol.html) | unicorn | | 🛠️ | | [prefer-number-properties](/docs/guide/usage/linter/rules/unicorn/prefer-number-properties.html) | unicorn | | 🚧 | -## Suspicious (18): +## Suspicious (20): code that is most likely wrong or useless. | Rule name | Source | Default | Fixable? | | ------------------------------- | ---------- | ------- | -------- | +| [no-extend-native](/docs/guide/usage/linter/rules/eslint/no-extend-native.html) | eslint | | | | [no-new](/docs/guide/usage/linter/rules/eslint/no-new.html) | eslint | | | +| [no-unexpected-multiline](/docs/guide/usage/linter/rules/eslint/no-unexpected-multiline.html) | eslint | | ⚠️🛠️️ | | [no-useless-concat](/docs/guide/usage/linter/rules/eslint/no-useless-concat.html) | eslint | | | | [no-useless-constructor](/docs/guide/usage/linter/rules/eslint/no-useless-constructor.html) | eslint | | 🛠️ | | [no-duplicates](/docs/guide/usage/linter/rules/import/no-duplicates.html) | import | | | @@ -355,7 +357,7 @@ Lints which are rather strict or have occasional false positives. | [prefer-type-error](/docs/guide/usage/linter/rules/unicorn/prefer-type-error.html) | unicorn | | 🛠️ | | [require-number-to-fixed-digits-argument](/docs/guide/usage/linter/rules/unicorn/require-number-to-fixed-digits-argument.html) | unicorn | | 🛠️ | -## Style (99): +## Style (100): Code that should be written in a more idiomatic way. | Rule name | Source | Default | Fixable? | @@ -413,6 +415,7 @@ Code that should be written in a more idiomatic way. | [require-hook](/docs/guide/usage/linter/rules/jest/require-hook.html) | jest | | | | [require-top-level-describe](/docs/guide/usage/linter/rules/jest/require-top-level-describe.html) | jest | | | | [no-exports-assign](/docs/guide/usage/linter/rules/node/no-exports-assign.html) | node | | 🛠️ | +| [avoid-new](/docs/guide/usage/linter/rules/promise/avoid-new.html) | promise | | | | [param-names](/docs/guide/usage/linter/rules/promise/param-names.html) | promise | | | | [prefer-await-to-then](/docs/guide/usage/linter/rules/promise/prefer-await-to-then.html) | promise | | | | [jsx-boolean-value](/docs/guide/usage/linter/rules/react/jsx-boolean-value.html) | react | | 🛠️ | diff --git a/src/docs/guide/usage/linter/rules/eslint/no-extend-native.md b/src/docs/guide/usage/linter/rules/eslint/no-extend-native.md new file mode 100644 index 0000000000..dc0a01ce2a --- /dev/null +++ b/src/docs/guide/usage/linter/rules/eslint/no-extend-native.md @@ -0,0 +1,53 @@ + + +# eslint/no-extend-native + +
+
+ +### What it does + +Prevents extending native global objects such as `Object`, `String`, or `Array` with new +properties. + +### Why is this bad? + +Extending native objects can cause unexpected behavior and conflicts with other code. + +For example: + +```js +// Adding a new property, which might seem okay +Object.prototype.extra = 55; + +// Defining a user object +const users = { + 1: "user1", + 2: "user2", +}; + +for (const id in users) { + // This will print "extra" as well as "1" and "2": + console.log(id); +} +``` + +### Examples + +Examples of **incorrect** code for this rule: + +```js +Object.prototype.p = 0; +Object.defineProperty(Array.prototype, "p", { value: 0 }); +``` + +Examples of **correct** code for this rule: + +```js +x.prototype.p = 0; +Object.defineProperty(x.prototype, "p", { value: 0 }); +``` + +## References + +- [Rule Source](https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/rules/eslint/no_extend_native.rs) diff --git a/src/docs/guide/usage/linter/rules/eslint/no-regex-spaces.md b/src/docs/guide/usage/linter/rules/eslint/no-regex-spaces.md index b2a71e6f15..5c9a715b5c 100644 --- a/src/docs/guide/usage/linter/rules/eslint/no-regex-spaces.md +++ b/src/docs/guide/usage/linter/rules/eslint/no-regex-spaces.md @@ -3,6 +3,9 @@ # eslint/no-regex-spaces
+ +🚧 An auto-fix is still under development. +
### What it does diff --git a/src/docs/guide/usage/linter/rules/eslint/no-unexpected-multiline.md b/src/docs/guide/usage/linter/rules/eslint/no-unexpected-multiline.md new file mode 100644 index 0000000000..1bcccebd45 --- /dev/null +++ b/src/docs/guide/usage/linter/rules/eslint/no-unexpected-multiline.md @@ -0,0 +1,55 @@ + + +# eslint/no-unexpected-multiline + +
+ +⚠️🛠️️ A dangerous auto-fix is available for this rule. + +
+ +### What it does + +In most cases, semicolons are not required in JavaScript in order for code to be parsed +and executed as expected. Typically this occurs because semicolons are automatically +inserted based on a fixed set of rules. This rule exists to detect those cases where a semicolon +is NOT inserted automatically, and may be parsed differently than expected. + +### Why is this bad? + +Code that has unexpected newlines may be parsed and executed differently than what the +developer intended. This can lead to bugs that are difficult to track down. + +### Examples + +Examples of **incorrect** code for this rule: + +```js +var a = b(x || y).doSomething(); + +var a = b[(a, b, c)].forEach(doSomething); + +let x = (function () {})`hello`; + +foo / bar / g.test(baz); +``` + +Examples of **correct** code for this rule: + +```js +var a = b; +(x || y).doSomething(); + +var a = b; +[a, b, c].forEach(doSomething); + +let x = function () {}; +`hello`; + +foo; +/bar/g.test(baz); +``` + +## References + +- [Rule Source](https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/rules/eslint/no_unexpected_multiline.rs) diff --git a/src/docs/guide/usage/linter/rules/promise/avoid-new.md b/src/docs/guide/usage/linter/rules/promise/avoid-new.md index ef57bcbcab..b5aa419730 100644 --- a/src/docs/guide/usage/linter/rules/promise/avoid-new.md +++ b/src/docs/guide/usage/linter/rules/promise/avoid-new.md @@ -1,24 +1,38 @@ -# promise/avoid-new +# promise/avoid-new
### What it does -Disallow creating new promises outside of utility libs. +Disallow creating promises with `new Promise()`. ### Why is this bad? -If you dislike the new promise style promises. +Many cases that use `new Promise()` could be refactored to use an +`async` function. `async` is considered more idiomatic in modern JavaScript. ### Example +Examples of **incorrect** code for this rule: + +```javascript +function foo() { + return new Promise((resolve, reject) => { + /* ... */ + }); +} +``` + +Examples of **correct** code for this rule: + ```javascript -new Promise((resolve, reject) => { - /* ... */ -}); +async function foo() { + // ... +} +const bar = await Promise.all([baz(), bang()]); ``` ## References diff --git a/src/docs/guide/usage/linter/rules/promise/catch-or-return.md b/src/docs/guide/usage/linter/rules/promise/catch-or-return.md index 6c4a920783..3a076bf128 100644 --- a/src/docs/guide/usage/linter/rules/promise/catch-or-return.md +++ b/src/docs/guide/usage/linter/rules/promise/catch-or-return.md @@ -7,13 +7,15 @@ ### What it does -Ensure that each time a then() is applied to a promise, a catch() is applied as well. -Exceptions are made if you are returning that promise. +Ensure that each time a `then()` is applied to a promise, a `catch()` +must be applied as well. Exceptions are made for promises returned from +a function. ### Why is this bad? -Not catching errors in a promise can cause hard to debug problems or missing handling of -error conditions. +Not catching errors in a promise can cause hard to debug problems or +missing handling of error conditions. In the worst case, unhandled +promise rejections can cause your application to crash. ### Example diff --git a/src/docs/guide/usage/linter/rules/security/api-keys.md b/src/docs/guide/usage/linter/rules/security/api-keys.md new file mode 100644 index 0000000000..13dbad6fbe --- /dev/null +++ b/src/docs/guide/usage/linter/rules/security/api-keys.md @@ -0,0 +1,72 @@ + + +# security/api-keys + +
+
+ +### What it does + +Disallows hard-coded API keys and other credentials. + +### Why is this bad? + +Hard-coding API keys and committing them to source control is a serious +security risk. + +1. If your code is leaked, attackers can use your API keys to access your + services and data. +2. Accidental bundling of API keys can lead them to be exposed publicly + in your website, compriming your services. +3. Any developer or contractor you hire will have access to your + services, even after they lose access to your codebase. +4. Even after being deleted, they will be visible in your git repo's + commit history. +5. Key rotation requires a code change and redeployment, and can + therefore not be handled by security teams or by automated systems. +6. Many, many more reasons. + +```ts +const API_KEY = "abcdef123456"; +const data = await fetch("/api/some/endpoint", { + headers: { + Authorization: `Bearer ${API_KEY}`, + }, +}); +``` + +### What To Do Instead + +:::warning +The Oxc team are not security experts. We do not endorse any particular +key management service or strategy. Do your research and choose the best +solution/architecture for your use case. +::: + +One possible alternative is to store secrets in a secure secrets manager +(such as [AWS +KMS](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/kms/), +[HashiCorp Vault](https://github.com/nodevault/node-vault/tree/master), +[Pangea](https://pangea.cloud/docs/sdk/js/vault#retrieve), etc.) and +request them when your application starts (e.g. a Docker container, an +EC2). + +### Examples + +Examples of **incorrect** code for this rule: + +```js +const AWS_ACCESS_KEY_ID = "AKIA1234X678C123B567"; +const OPENAI_API_KEY = "sk_test_1234567890"; +``` + +Examples of **correct** code for this rule: + +```js +const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID; +const OPENAI_API_KEY = await getSecret("open-ai-api-key"); +``` + +## References + +- [Rule Source](https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/rules/security/api_keys/mod.rs)