Apply prettier for consistent code formatting

This commit is contained in:
Martin Kačmar 2024-10-01 12:43:46 +02:00
Родитель 5b9b57b04a
Коммит 7a5a085e08
70 изменённых файлов: 1243 добавлений и 1215 удалений

24
.github/ISSUE_TEMPLATE/bug_report.md поставляемый
Просмотреть файл

@ -1,10 +1,9 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
title: ""
labels: ""
assignees: ""
---
**Describe the bug**
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

7
.github/ISSUE_TEMPLATE/feature_request.md поставляемый
Просмотреть файл

@ -1,10 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
title: ""
labels: ""
assignees: ""
---
**Is your feature request related to a problem? Please describe.**

26
.github/workflows/e2e-integration.yml поставляемый
Просмотреть файл

@ -40,7 +40,7 @@ jobs:
npm i typescript
npm i @microsoft/eslint-formatter-sarif
working-directory: ${{env.TEST_RUN_DIR}}
- uses: actions/checkout@v4
with:
repository: ${{env.GITHUB_REPO}}
@ -55,12 +55,12 @@ jobs:
- name: Install plugin dependencies
run: npm install --production
working-directory: ${{env.PLUGIN_DIR}}
- name: Link plugin
run: sudo npm link ../${{env.PLUGIN_DIR}}
working-directory: ${{env.TEST_RUN_DIR}}
if: runner.os == 'Linux'
- name: Link plugin
run: npm link ../${{env.PLUGIN_DIR}}
working-directory: ${{env.TEST_RUN_DIR}}
@ -69,18 +69,18 @@ jobs:
- name: Create ESLint config file
run: echo 'module.exports = [...require("@microsoft/eslint-plugin-sdl").configs.recommended];' > eslint.config.js
working-directory: ${{env.TEST_RUN_DIR}}
- name: Run ESLint
run: npx eslint
--config eslint.config.js
--no-config-lookup
${{env.TEST_TARGET_DIR}}/${{env.GITHUB_REPO_ESLINT_GLOB}}
--parser-options=project:${{env.TEST_TARGET_DIR}}/${{env.GITHUB_REPO_TSCONFIG}}
--format @microsoft/eslint-formatter-sarif
--output-file eslint-result-${{ matrix.os }}-${{github.run_id}}.sarif
run: npx eslint
--config eslint.config.js
--no-config-lookup
${{env.TEST_TARGET_DIR}}/${{env.GITHUB_REPO_ESLINT_GLOB}}
--parser-options=project:${{env.TEST_TARGET_DIR}}/${{env.GITHUB_REPO_TSCONFIG}}
--format @microsoft/eslint-formatter-sarif
--output-file eslint-result-${{ matrix.os }}-${{github.run_id}}.sarif
working-directory: ${{env.TEST_RUN_DIR}}
continue-on-error: true
continue-on-error: true
- name: Upload ESLint results as artifact
uses: actions/upload-artifact@v4
with:

Просмотреть файл

@ -11,7 +11,6 @@ on:
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
@ -20,10 +19,10 @@ jobs:
node-version: [18.x, 20.x, 22.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test

4
.prettierignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
SECURITY.md
CODE_OF_CONDUCT.md
package.json
package-lock.json

3
.prettierrc Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"printWidth": 100
}

Просмотреть файл

@ -12,7 +12,9 @@ Plugin is intended as a baseline for projects that follow [Microsoft Security De
```sh
npm install microsoft/eslint-plugin-sdl
```
or
```sh
yarn add microsoft/eslint-plugin-sdl
```
@ -24,9 +26,7 @@ Including an ESLint configuration file in your project allows you to customize h
```js
const pluginMicrosoftSdl = require("@microsoft/eslint-plugin-sdl");
module.exports = [
...pluginMicrosoftSdl.configs.recommended
];
module.exports = [...pluginMicrosoftSdl.configs.recommended];
```
ESLint will then only enforce rules you specify in the rules section of your configuration file at the [severity level](https://eslint.org/docs/latest/use/configure/rules) you designate. For example:
@ -39,9 +39,9 @@ module.exports = [
{
rules: {
"no-eval": "error",
"@microsoft/sdl/no-inner-html": "error"
}
}
"@microsoft/sdl/no-inner-html": "error",
},
},
];
```
@ -65,36 +65,36 @@ Where possible, we leverage existing rules from [ESLint](https://eslint.org/docs
We also implemented several [custom rules](./lib/rules) where we did not find sufficient alternative in the community.
| Name | Description |
| --- | --- |
| [no-caller](https://eslint.org/docs/rules/no-caller) | Bans usage of deprecated functions `arguments.caller()` and `arguments.callee` that could potentially allow access to call stack. |
| [no-delete-var](https://eslint.org/docs/rules/no-delete-var) | Bans usage of operator `delete` on variables as it can lead to unexpected behavior. |
| [no-eval](https://eslint.org/docs/rules/no-eval) | Bans usage of [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) that allows code execution from string argument. |
| [no-implied-eval](https://eslint.org/docs/rules/no-implied-eval) | Bans usage of `setTimeout()`, `setInterval()` and `execScript()`. These functions are similar to `eval()` and prone to code execution. |
| [no-new-func](https://eslint.org/docs/rules/no-new-func) | Bans calling `new Function()` as it's similar to `eval()` and prone to code execution. |
| [node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) | Bans usage of deprecated APIs in Node. |
| [@microsoft/sdl/no-angular-bypass-sanitizer](./docs/rules/no-angular-bypass-sanitizer.md) | Calls to bypassSecurityTrustHtml, bypassSecurityTrustScript and similar methods bypass [DomSanitizer](https://angular.io/api/platform-browser/DomSanitizer#security-risk) in Angular and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-bypass-sce](./docs/rules/no-angularjs-bypass-sce.md) | Calls to `$sceProvider.enabled(false)`, `$sceDelegate.trustAs()`, `$sce.trustAs()` and relevant shorthand methods (e.g. `trustAsHtml` or `trustAsJs`) bypass [Strict Contextual Escaping (SCE)](https://docs.angularjs.org/api/ng/service/$sce#strict-contextual-escaping) in AngularJS and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-enable-svg](./docs/rules/no-angularjs-enable-svg.md) | Calls to [`$sanitizeProvider.enableSvg(true)`](https://docs.angularjs.org/api/ngSanitize/provider/$sanitizeProvider#enableSvg) increase attack surface of the application by enabling SVG support in AngularJS sanitizer and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-sanitization-whitelist](./docs/rules/no-angularjs-sanitization-whitelist.md) | Calls to [`$compileProvider.aHrefSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist) or [`$compileProvider.imgSrcSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#imgSrcSanitizationWhitelist) configure whitelists in AngularJS sanitizer and need to be reviewed. |
| [@microsoft/sdl/no-cookies](./docs/rules/no-cookies.md) | HTTP cookies are an old client-side storage mechanism with inherent risks and limitations. Use Web Storage, IndexedDB or other modern methods instead. |
| [@microsoft/sdl/no-document-domain](./docs/rules/no-document-domain.md) | Writes to [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/Document/domain) property must be reviewed to avoid bypass of [same-origin checks](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin). Usage of top level domains such as `azurewebsites.net` is strictly prohibited. |
| [@microsoft/sdl/no-document-write](./docs/rules/no-document-write.md) | Calls to document.write or document.writeln manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-electron-node-integration](./docs/rules/no-electron-node-integration.md) | [Node.js Integration](https://www.electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) must not be enabled in any renderer that loads remote content to avoid remote code execution attacks. |
| [@microsoft/sdl/no-html-method](./docs/rules/no-html-method.md) | Direct calls to method `html()` often (e.g. in jQuery framework) manipulate DOM without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-inner-html](./docs/rules/no-inner-html.md) | Assignments to innerHTML or outerHTML properties manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-insecure-url](./docs/rules/no-insecure-url.md) | Insecure protocols such as [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) or [FTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol) should be replaced by their encrypted counterparts ([HTTPS](https://en.wikipedia.org/wiki/HTTPS), [FTPS](https://en.wikipedia.org/wiki/FTPS)) to avoid sending potentially sensitive data over untrusted networks in plaintext. |
| [@microsoft/sdl/no-msapp-exec-unsafe](./docs/rules/no-msapp-exec-unsafe.md) | Calls to [`MSApp.execUnsafeLocalFunction()`](https://docs.microsoft.com/en-us/previous-versions/hh772324(v=vs.85)) bypass script injection validation and should be avoided. |
| [@microsoft/sdl/no-postmessage-star-origin](./docs/rules/no-postmessage-star-origin.md) | Always provide specific target origin, not * when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary. |
| [@microsoft/sdl/no-unsafe-alloc](./docs/rules/no-unsafe-alloc.md) | When calling [`Buffer.allocUnsafe`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafe_size) and [`Buffer.allocUnsafeSlow`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafeslow_size), the allocated memory is not wiped-out and can contain old, potentially sensitive data. |
| [@microsoft/sdl/no-winjs-html-unsafe](./docs/rules/no-winjs-html-unsafe.md) | Calls to [`WinJS.Utilities.setInnerHTMLUnsafe()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)) and similar methods do not perform any input validation and should be avoided. Use [`WinJS.Utilities.setInnerHTML()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)) instead. |
| [@microsoft/sdl/react-iframe-missing-sandbox](./docs/rules/react-iframe-missing-sandbox.md) | The [sandbox](https://www.w3schools.com/tags/att_iframe_sandbox.asp) attribute enables an extra set of restrictions for the content in the iframe and should always be specified. |
| [react/no-danger](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md) | Bans usage of `dangerouslySetInnerHTML` property in React as it allows passing unsanitized HTML in DOM. |
| [@typescript-eslint/no-implied-eval](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-implied-eval.md) | Similar to built-in ESLint rule `no-implied-eval`. Bans usage of `setTimeout()`, `setInterval()`, `setImmediate()`, `execScript()` or `new Function()` as they are similar to `eval()` and allow code execution from string arguments. |
| Name | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [no-caller](https://eslint.org/docs/rules/no-caller) | Bans usage of deprecated functions `arguments.caller()` and `arguments.callee` that could potentially allow access to call stack. |
| [no-delete-var](https://eslint.org/docs/rules/no-delete-var) | Bans usage of operator `delete` on variables as it can lead to unexpected behavior. |
| [no-eval](https://eslint.org/docs/rules/no-eval) | Bans usage of [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) that allows code execution from string argument. |
| [no-implied-eval](https://eslint.org/docs/rules/no-implied-eval) | Bans usage of `setTimeout()`, `setInterval()` and `execScript()`. These functions are similar to `eval()` and prone to code execution. |
| [no-new-func](https://eslint.org/docs/rules/no-new-func) | Bans calling `new Function()` as it's similar to `eval()` and prone to code execution. |
| [node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) | Bans usage of deprecated APIs in Node. |
| [@microsoft/sdl/no-angular-bypass-sanitizer](./docs/rules/no-angular-bypass-sanitizer.md) | Calls to bypassSecurityTrustHtml, bypassSecurityTrustScript and similar methods bypass [DomSanitizer](https://angular.io/api/platform-browser/DomSanitizer#security-risk) in Angular and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-bypass-sce](./docs/rules/no-angularjs-bypass-sce.md) | Calls to `$sceProvider.enabled(false)`, `$sceDelegate.trustAs()`, `$sce.trustAs()` and relevant shorthand methods (e.g. `trustAsHtml` or `trustAsJs`) bypass [Strict Contextual Escaping (SCE)](https://docs.angularjs.org/api/ng/service/$sce#strict-contextual-escaping) in AngularJS and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-enable-svg](./docs/rules/no-angularjs-enable-svg.md) | Calls to [`$sanitizeProvider.enableSvg(true)`](https://docs.angularjs.org/api/ngSanitize/provider/$sanitizeProvider#enableSvg) increase attack surface of the application by enabling SVG support in AngularJS sanitizer and need to be reviewed. |
| [@microsoft/sdl/no-angularjs-sanitization-whitelist](./docs/rules/no-angularjs-sanitization-whitelist.md) | Calls to [`$compileProvider.aHrefSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist) or [`$compileProvider.imgSrcSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#imgSrcSanitizationWhitelist) configure whitelists in AngularJS sanitizer and need to be reviewed. |
| [@microsoft/sdl/no-cookies](./docs/rules/no-cookies.md) | HTTP cookies are an old client-side storage mechanism with inherent risks and limitations. Use Web Storage, IndexedDB or other modern methods instead. |
| [@microsoft/sdl/no-document-domain](./docs/rules/no-document-domain.md) | Writes to [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/Document/domain) property must be reviewed to avoid bypass of [same-origin checks](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin). Usage of top level domains such as `azurewebsites.net` is strictly prohibited. |
| [@microsoft/sdl/no-document-write](./docs/rules/no-document-write.md) | Calls to document.write or document.writeln manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-electron-node-integration](./docs/rules/no-electron-node-integration.md) | [Node.js Integration](https://www.electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) must not be enabled in any renderer that loads remote content to avoid remote code execution attacks. |
| [@microsoft/sdl/no-html-method](./docs/rules/no-html-method.md) | Direct calls to method `html()` often (e.g. in jQuery framework) manipulate DOM without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-inner-html](./docs/rules/no-inner-html.md) | Assignments to innerHTML or outerHTML properties manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead. |
| [@microsoft/sdl/no-insecure-url](./docs/rules/no-insecure-url.md) | Insecure protocols such as [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) or [FTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol) should be replaced by their encrypted counterparts ([HTTPS](https://en.wikipedia.org/wiki/HTTPS), [FTPS](https://en.wikipedia.org/wiki/FTPS)) to avoid sending potentially sensitive data over untrusted networks in plaintext. |
| [@microsoft/sdl/no-msapp-exec-unsafe](./docs/rules/no-msapp-exec-unsafe.md) | Calls to [`MSApp.execUnsafeLocalFunction()`](<https://docs.microsoft.com/en-us/previous-versions/hh772324(v=vs.85)>) bypass script injection validation and should be avoided. |
| [@microsoft/sdl/no-postmessage-star-origin](./docs/rules/no-postmessage-star-origin.md) | Always provide specific target origin, not \* when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary. |
| [@microsoft/sdl/no-unsafe-alloc](./docs/rules/no-unsafe-alloc.md) | When calling [`Buffer.allocUnsafe`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafe_size) and [`Buffer.allocUnsafeSlow`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafeslow_size), the allocated memory is not wiped-out and can contain old, potentially sensitive data. |
| [@microsoft/sdl/no-winjs-html-unsafe](./docs/rules/no-winjs-html-unsafe.md) | Calls to [`WinJS.Utilities.setInnerHTMLUnsafe()`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)>) and similar methods do not perform any input validation and should be avoided. Use [`WinJS.Utilities.setInnerHTML()`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)>) instead. |
| [@microsoft/sdl/react-iframe-missing-sandbox](./docs/rules/react-iframe-missing-sandbox.md) | The [sandbox](https://www.w3schools.com/tags/att_iframe_sandbox.asp) attribute enables an extra set of restrictions for the content in the iframe and should always be specified. |
| [react/no-danger](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-danger.md) | Bans usage of `dangerouslySetInnerHTML` property in React as it allows passing unsanitized HTML in DOM. |
| [@typescript-eslint/no-implied-eval](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-implied-eval.md) | Similar to built-in ESLint rule `no-implied-eval`. Bans usage of `setTimeout()`, `setInterval()`, `setImmediate()`, `execScript()` or `new Function()` as they are similar to `eval()` and allow code execution from string arguments. |
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
@ -104,4 +104,4 @@ provided by the bot. You will only need to do this once across all repos using o
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

12
config/angular.js поставляемый
Просмотреть файл

@ -3,16 +3,16 @@
"use strict";
// Generates shareable config for modern Angular (https://angular.dev/) apps.
// Generates shareable config for modern Angular (https://angular.dev/) apps.
module.exports = (pluginSdl) => {
return [
{
plugins: {
"@microsoft/sdl": pluginSdl
"@microsoft/sdl": pluginSdl,
},
rules: {
"@microsoft/sdl/no-angular-bypass-sanitizer": "error"
}
}
"@microsoft/sdl/no-angular-bypass-sanitizer": "error",
},
},
];
};
};

12
config/angularjs.js поставляемый
Просмотреть файл

@ -3,18 +3,18 @@
"use strict";
// Generates shareable config for legacy AngularJS (https://angularjs.org/) apps.
// Generates shareable config for legacy AngularJS (https://angularjs.org/) apps.
module.exports = (pluginSdl) => {
return [
{
plugins: {
"@microsoft/sdl": pluginSdl
"@microsoft/sdl": pluginSdl,
},
rules: {
"@microsoft/sdl/no-angularjs-enable-svg": "error",
"@microsoft/sdl/no-angularjs-sanitization-whitelist": "error",
"@microsoft/sdl/no-angularjs-bypass-sce": "error"
}
}
"@microsoft/sdl/no-angularjs-bypass-sce": "error",
},
},
];
};
};

Просмотреть файл

@ -7,7 +7,7 @@ module.exports = (pluginSdl) => {
return [
{
plugins: {
"@microsoft/sdl": pluginSdl
"@microsoft/sdl": pluginSdl,
},
rules: {
"no-caller": "error",
@ -23,8 +23,8 @@ module.exports = (pluginSdl) => {
"@microsoft/sdl/no-insecure-url": "error",
"@microsoft/sdl/no-msapp-exec-unsafe": "error",
"@microsoft/sdl/no-postmessage-star-origin": "error",
"@microsoft/sdl/no-winjs-html-unsafe": "error"
}
}
"@microsoft/sdl/no-winjs-html-unsafe": "error",
},
},
];
};
};

Просмотреть файл

@ -7,11 +7,11 @@ module.exports = (pluginSdl) => {
return [
{
plugins: {
"@microsoft/sdl": pluginSdl
"@microsoft/sdl": pluginSdl,
},
rules: {
"@microsoft/sdl/no-electron-node-integration": "error"
}
}
"@microsoft/sdl/no-electron-node-integration": "error",
},
},
];
};
};

Просмотреть файл

@ -9,19 +9,19 @@ module.exports = (pluginSdl) => {
return [
{
plugins: {
n: pluginN
n: pluginN,
},
rules: {
"n/no-deprecated-api": "error"
}
"n/no-deprecated-api": "error",
},
},
{
plugins: {
"@microsoft/sdl": pluginSdl
"@microsoft/sdl": pluginSdl,
},
rules: {
"@microsoft/sdl/no-unsafe-alloc": "error"
}
"@microsoft/sdl/no-unsafe-alloc": "error",
},
},
];
};
};

27
config/react.js поставляемый
Просмотреть файл

@ -11,33 +11,34 @@ module.exports = (pluginSdl) => {
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true
}
}
}
jsx: true,
},
},
},
},
{
plugins: {
"react": pluginReact
react: pluginReact,
},
rules: {
"react/no-danger": "error",
"react/jsx-no-target-blank": ["error",
"react/jsx-no-target-blank": [
"error",
{
allowReferrer: false,
enforceDynamicLinks: "always",
warnOnSpreadAttributes: true,
}
]
}
},
],
},
},
{
plugins: {
"@microsoft/sdl": pluginSdl,
},
rules: {
"@microsoft/sdl/react-iframe-missing-sandbox": "error"
}
}
"@microsoft/sdl/react-iframe-missing-sandbox": "error",
},
},
];
};
};

Просмотреть файл

@ -13,28 +13,28 @@ module.exports = () => {
ecmaVersion: 6,
sourceType: "module",
ecmaFeatures: {
jsx: true
}
}
}
jsx: true,
},
},
},
},
{
files: ["**/*.{ts,tsx}"],
languageOptions: {
parserOptions: {
parser: "@typescript-eslint/parser",
}
},
},
plugins: {
"@typescript-eslint": pluginTypescript
"@typescript-eslint": pluginTypescript,
},
rules: {
"@typescript-eslint/no-implied-eval": "error",
// @typescript-eslint/no-implied-eval offers more accurate results for typescript.
// thus we turn the more generic rule off for ts and tsx files.
// This also avoids duplicate hits.
"no-implied-eval": "off"
}
}
"no-implied-eval": "off",
},
},
];
};
};

Просмотреть файл

@ -4,4 +4,4 @@ Calls to `$sceProvider.enabled(false)`, `$sceDelegate.trustAs()`, `$sce.trustAs(
SCE should be bypassed only in very rare and justifiable cases after careful review so that the risk of introducing Cross-Site-Scripting (XSS) vulnerability is minimized.
See [official documentation](https://docs.angularjs.org/api/ng/service/$sce#strict-contextual-escaping) for more details.
See [official documentation](https://docs.angularjs.org/api/ng/service/$sce#strict-contextual-escaping) for more details.

Просмотреть файл

@ -6,8 +6,8 @@ Cookies should be used only in rare and justifiable cases after thorough securit
## Further Reading
* [Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
- [Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
## Related Rules
* [tslint-microsoft-contrib/no-cookies](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noCookiesRule.ts)
- [tslint-microsoft-contrib/no-cookies](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noCookiesRule.ts)

Просмотреть файл

@ -4,4 +4,4 @@ Writes to [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/D
## Related Rules
* [tslint-microsoft-contrib/no-document-domain](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noDocumentDomainRule.ts)
- [tslint-microsoft-contrib/no-document-domain](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noDocumentDomainRule.ts)

Просмотреть файл

@ -4,4 +4,4 @@ Calls to document.write or document.writeln manipulate DOM directly without any
## Related Rules
* [tslint-microsoft-contrib/no-document-write](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noDocumentWriteRule.ts)
- [tslint-microsoft-contrib/no-document-write](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noDocumentWriteRule.ts)

Просмотреть файл

@ -6,4 +6,4 @@
## Related Rules
* [codeql/js/enabling-electron-renderer-node-integration](https://help.semmle.com/wiki/display/JS/Enabling+Node.js+integration+for+Electron+web+content+renderers)
- [codeql/js/enabling-electron-renderer-node-integration](https://help.semmle.com/wiki/display/JS/Enabling+Node.js+integration+for+Electron+web+content+renderers)

Просмотреть файл

@ -4,4 +4,4 @@ Direct calls to method `html()` often (e.g. in jQuery framework) manipulate DOM
## Related Rules
* [tslint-microsoft-contrib/no-inner-html](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noInnerHtml.ts)
- [tslint-microsoft-contrib/no-inner-html](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noInnerHtml.ts)

Просмотреть файл

@ -2,10 +2,10 @@
Assignments to [innerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)/[outerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML) properties or calls to [insertAdjacentHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) method manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead.
* [Rule Source](../../lib/rules/no-inner-html.js)
* [Rule Test](../../tests/lib/rules/no-inner-html.js)
- [Rule Source](../../lib/rules/no-inner-html.js)
- [Rule Test](../../tests/lib/rules/no-inner-html.js)
## Related Rules
* [tslint-microsoft-contrib/no-inner-html](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noInnerHtml.ts)
* [eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized/blob/master/docs/rules/method.md)
- [tslint-microsoft-contrib/no-inner-html](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noInnerHtml.ts)
- [eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized/blob/master/docs/rules/method.md)

Просмотреть файл

@ -6,12 +6,12 @@ Use crypto.randomBytes() or window.crypto.getRandomValues() instead.
## Related Rules
* [tslint-microsoft-contrib/no-insecure-random](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/insecureRandomRule.ts)
- https://help.semmle.com/wiki/display/JS/Insecure+randomness
- [source](https://github.com/github/codeql/blob/master/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll)
- https://vulncat.fortify.com/en/detail?id=desc.semantic.abap.insecure_randomness#JavaScript
- https://rules.sonarsource.com/javascript/RSPEC-2245
- [source](https://github.com/SonarSource/SonarJS/blob/master/eslint-bridge/src/rules/pseudo-random.ts)
- https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-pseudoRandomBytes.js
- https://github.com/gkouziik/eslint-plugin-security-node/blob/master/lib/rules/detect-insecure-randomness.js
- [tslint-microsoft-contrib/no-insecure-random](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/insecureRandomRule.ts)
* https://help.semmle.com/wiki/display/JS/Insecure+randomness
- [source](https://github.com/github/codeql/blob/master/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll)
* https://vulncat.fortify.com/en/detail?id=desc.semantic.abap.insecure_randomness#JavaScript
* https://rules.sonarsource.com/javascript/RSPEC-2245
- [source](https://github.com/SonarSource/SonarJS/blob/master/eslint-bridge/src/rules/pseudo-random.ts)
* https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-pseudoRandomBytes.js
* https://github.com/gkouziik/eslint-plugin-security-node/blob/master/lib/rules/detect-insecure-randomness.js

Просмотреть файл

@ -6,7 +6,9 @@ Insecure protocols such as [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transf
- [Rule Test](../../tests/lib/rules/no-insecure-url.js)
## Options
This rule comes with three [default lists](../../lib/rules/no-insecure-url.js#L13):
- **blocklist** - a RegEx list of insecure URL patterns.
- **exceptions** - a RegEx list of common false positive patterns. For example, HTTP URLs to XML schemas are usually allowed as they are used as identifiers, not for establishing actual network connections.
- **varExceptions** - a RegEx list of false positive patterns which a derivated from the variable name. For example, a variable that is called "insecureURL" which is used to test HTTP explicitly.
@ -14,7 +16,9 @@ This rule comes with three [default lists](../../lib/rules/no-insecure-url.js#L1
These lists can be overrided by providing options.
---
For example, providing these options... :
```javascript
"@microsoft/sdl/no-insecure-url": ["error", {
"blocklist": ["^(http|ftp):\\/\\/", "^https:\\/\\/www\\.disallow-example\\.com"],
@ -24,21 +28,25 @@ For example, providing these options... :
```
... overrides the internal blocklist, blocking the following URL patterns... :
- `http://`...
- `ftp://`...
- `https://www.disallow-example.com`
... and also overrides the internal exceptions list, allowing the following URL patterns as exceptions.:
- `http://schemas.microsoft.com`
- `http://schemas.microsoft.com/sharepoint`
- `http://schemas.microsoft.com/path/subpath`
... and also overrides the internal variable exceptions list, allowing the following declaration name patterns as exceptions.:
- `var insecureURL = "http://..."`
- `var insecureWebsite = "http://..."`
- ...
URLs in neither the blocklist nor the exceptions list, are allowed:
- `telnet://`...
- `ws://`...
- ...
@ -46,16 +54,19 @@ URLs in neither the blocklist nor the exceptions list, are allowed:
---
**Note**: The RegEx for the lists is provided within a string in a JSON. It is without delimiting slashes `/ /` and thus users cannot pass RegEx parameters. We make it case-insensitive after user input. Do not forget to escape characters:
```javascript
let pureRegex = /^https:\/\/www\.disallow-example\.com/;
let regexInString = "^https:\\/\\/www\\.disallow-example\\.com";
```
## Related Rules
* [tslint-microsoft-contrib/no-http-string](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noHttpStringRule.ts)
* [CodeQL/InsecureDownloadCustomizations.qll](https://github.com/github/codeql/blob/master/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll#L62)
* [DevSkim/DS137138](https://github.com/microsoft/DevSkim/blob/main/guidance/DS137138.md)
* [Fortify/insecure_transport](https://vulncat.fortify.com/en/detail?id=desc.config.java.insecure_transport#JavaScript%2fTypeScript)
- [tslint-microsoft-contrib/no-http-string](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/noHttpStringRule.ts)
- [CodeQL/InsecureDownloadCustomizations.qll](https://github.com/github/codeql/blob/master/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll#L62)
- [DevSkim/DS137138](https://github.com/microsoft/DevSkim/blob/main/guidance/DS137138.md)
- [Fortify/insecure_transport](https://vulncat.fortify.com/en/detail?id=desc.config.java.insecure_transport#JavaScript%2fTypeScript)
## Further Reading
* [HTTPS Everywhere](https://en.wikipedia.org/wiki/HTTPS_Everywhere)
- [HTTPS Everywhere](https://en.wikipedia.org/wiki/HTTPS_Everywhere)

Просмотреть файл

@ -1,3 +1,3 @@
# Do not use * as target origin when sending data to other windows (no-postmessage-star-origin)
# Do not use \* as target origin when sending data to other windows (no-postmessage-star-origin)
Always provide specific target origin, not * when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary.
Always provide specific target origin, not \* when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary.

Просмотреть файл

@ -4,9 +4,9 @@ When calling [`Buffer.allocUnsafe`](https://nodejs.org/api/buffer.html#buffer_st
These methods should be used only in justifiable cases (e.g. due to performance reasons) after thorough security review.
* [Rule Source](../../lib/rules/no-unsafe-alloc.js)
* [Rule Test](../../tests/lib/rules/no-unsafe-alloc.js)
- [Rule Source](../../lib/rules/no-unsafe-alloc.js)
- [Rule Test](../../tests/lib/rules/no-unsafe-alloc.js)
## Resources
* [Node.js - What makes Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() "unsafe"?](https://nodejs.org/api/buffer.html#buffer_what_makes_buffer_allocunsafe_and_buffer_allocunsafeslow_unsafe)
- [Node.js - What makes Buffer.allocUnsafe() and Buffer.allocUnsafeSlow() "unsafe"?](https://nodejs.org/api/buffer.html#buffer_what_makes_buffer_allocunsafe_and_buffer_allocunsafeslow_unsafe)

Просмотреть файл

@ -1,3 +1,3 @@
# Do not set HTML using unsafe methods from WinJS.Utilities (no-winjs-html-unsafe)
Calls to [`setInnerHTMLUnsafe`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)), [`setOuterHTMLUnsafe`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211698(v=win.10)) or [`insertAdjacentHTMLUnsafe`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br229832(v=win.10)) methods from [Windows Library for JavaScript](https://docs.microsoft.com/en-us/previous-versions/windows/apps/mt502392(v=win.10)) do not perform input validation and should be avoided. Use alternate methods such as [`setInnerHTML`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)) instead.
Calls to [`setInnerHTMLUnsafe`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)>), [`setOuterHTMLUnsafe`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211698(v=win.10)>) or [`insertAdjacentHTMLUnsafe`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br229832(v=win.10)>) methods from [Windows Library for JavaScript](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/mt502392(v=win.10)>) do not perform input validation and should be avoided. Use alternate methods such as [`setInnerHTML`](<https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)>) instead.

Просмотреть файл

@ -4,14 +4,14 @@ The [sandbox](https://www.w3schools.com/tags/att_iframe_sandbox.asp) attribute e
Additional functionality such as the ability to run scripts should be enabled only in justifiable cases after thorough security review.
* [Rule Source](../../lib/rules/react-iframe-missing-sandbox.js)
* [Rule Test](../../tests/lib/rules/react-iframe-missing-sandbox.js)
- [Rule Source](../../lib/rules/react-iframe-missing-sandbox.js)
- [Rule Test](../../tests/lib/rules/react-iframe-missing-sandbox.js)
## Related Rules
* [tslint-microsoft-contrib/react-iframe-missing-sandbox](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/reactIframeMissingSandboxRule.ts)
- [tslint-microsoft-contrib/react-iframe-missing-sandbox](https://github.com/microsoft/tslint-microsoft-contrib/blob/master/src/reactIframeMissingSandboxRule.ts)
## More Reading
* [How to safely inject HTML in React using an iframe](https://medium.com/the-thinkmill/how-to-safely-inject-html-in-react-using-an-iframe-adc775d458bc)
* [Play safely in sandboxed IFrames](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/)
- [How to safely inject HTML in React using an iframe](https://medium.com/the-thinkmill/how-to-safely-inject-html-in-react-using-an-iframe-adc775d458bc)
- [Play safely in sandboxed IFrames](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/)

Просмотреть файл

@ -8,67 +8,62 @@
"use strict";
module.exports = {
isTypeScriptParserServices(parserServices) {
// Check properties specific to @typescript-eslint/parser
return (
parserServices &&
parserServices.program &&
parserServices.esTreeNodeToTSNodeMap &&
parserServices.tsNodeToESTreeNodeMap
);
},
hasFullTypeInformation(context) {
var hasFullTypeInformation = (
context &&
context.sourceCode &&
context.sourceCode.parserServices &&
this.isTypeScriptParserServices(context.sourceCode.parserServices)
);
return hasFullTypeInformation;
},
getFullTypeChecker(context) {
return this.hasFullTypeInformation(context) ? context.sourceCode.parserServices.program.getTypeChecker() : null;
},
getNodeTypeAsString(fullTypeChecker, node, context) {
if (fullTypeChecker && node) {
const tsNode = context.sourceCode.parserServices.esTreeNodeToTSNodeMap.get(node);
const tsType = fullTypeChecker.getTypeAtLocation(tsNode);
const type = fullTypeChecker.typeToString(tsType);
return type;
}
return "any";
},
isDocumentObject(node, context, fullTypeChecker) {
if (fullTypeChecker) {
const type = this.getNodeTypeAsString(fullTypeChecker, node, context);
return (type === "Document");
}
// Best-effort checking without Type information
switch (node.type) {
case "Identifier":
return node != undefined && node.name == "document";
case "MemberExpression":
return (
node != undefined &&
node.property != undefined &&
node.property.name == "document" && (
(node.object != undefined &&
typeof node.object.name === "string" &&
node.object.name.toLowerCase().endsWith('window')) ||
(
node.object != undefined &&
node.object.property != undefined &&
node.object.property.name == "window" &&
(
(node.object.object != undefined && node.object.object.type == "ThisExpression") ||
(node.object.object != undefined && node.object.object.name == "globalThis")
)
)
)
);
};
return false;
isTypeScriptParserServices(parserServices) {
// Check properties specific to @typescript-eslint/parser
return (
parserServices &&
parserServices.program &&
parserServices.esTreeNodeToTSNodeMap &&
parserServices.tsNodeToESTreeNodeMap
);
},
hasFullTypeInformation(context) {
var hasFullTypeInformation =
context &&
context.sourceCode &&
context.sourceCode.parserServices &&
this.isTypeScriptParserServices(context.sourceCode.parserServices);
return hasFullTypeInformation;
},
getFullTypeChecker(context) {
return this.hasFullTypeInformation(context)
? context.sourceCode.parserServices.program.getTypeChecker()
: null;
},
getNodeTypeAsString(fullTypeChecker, node, context) {
if (fullTypeChecker && node) {
const tsNode = context.sourceCode.parserServices.esTreeNodeToTSNodeMap.get(node);
const tsType = fullTypeChecker.getTypeAtLocation(tsNode);
const type = fullTypeChecker.typeToString(tsType);
return type;
}
};
return "any";
},
isDocumentObject(node, context, fullTypeChecker) {
if (fullTypeChecker) {
const type = this.getNodeTypeAsString(fullTypeChecker, node, context);
return type === "Document";
}
// Best-effort checking without Type information
switch (node.type) {
case "Identifier":
return node != undefined && node.name == "document";
case "MemberExpression":
return (
node != undefined &&
node.property != undefined &&
node.property.name == "document" &&
((node.object != undefined &&
typeof node.object.name === "string" &&
node.object.name.toLowerCase().endsWith("window")) ||
(node.object != undefined &&
node.object.property != undefined &&
node.object.property.name == "window" &&
((node.object.object != undefined && node.object.object.type == "ThisExpression") ||
(node.object.object != undefined && node.object.object.name == "globalThis"))))
);
}
return false;
},
};

Просмотреть файл

@ -9,32 +9,32 @@ const pluginSecurity = require("eslint-plugin-security");
const pkg = require(path.join("..", "package.json"));
const plugin = {
meta: {
name: pkg.name,
version: pkg.version
},
rules: {
"no-angular-bypass-sanitizer": require("./rules/no-angular-bypass-sanitizer"),
"no-angular-sanitization-trusted-urls": require("./rules/no-angular-sanitization-trusted-urls"),
"no-angularjs-bypass-sce": require("./rules/no-angularjs-bypass-sce"),
"no-angularjs-enable-svg": require("./rules/no-angularjs-enable-svg"),
"no-angularjs-sanitization-whitelist": require("./rules/no-angularjs-sanitization-whitelist"),
"no-cookies": require("./rules/no-cookies"),
"no-document-domain": require("./rules/no-document-domain"),
"no-document-write": require("./rules/no-document-write"),
"no-electron-node-integration": require("./rules/no-electron-node-integration"),
"no-html-method": require("./rules/no-html-method"),
"no-inner-html": require("./rules/no-inner-html"),
"no-insecure-random": require("./rules/no-insecure-random"),
"no-insecure-url": require("./rules/no-insecure-url"),
"no-msapp-exec-unsafe": require("./rules/no-msapp-exec-unsafe"),
"no-postmessage-star-origin": require("./rules/no-postmessage-star-origin"),
"no-unsafe-alloc": require("./rules/no-unsafe-alloc"),
"no-winjs-html-unsafe": require("./rules/no-winjs-html-unsafe"),
"react-iframe-missing-sandbox": require("./rules/react-iframe-missing-sandbox"),
},
// Filled in later in order to reference plugin itself.
configs: {}
meta: {
name: pkg.name,
version: pkg.version,
},
rules: {
"no-angular-bypass-sanitizer": require("./rules/no-angular-bypass-sanitizer"),
"no-angular-sanitization-trusted-urls": require("./rules/no-angular-sanitization-trusted-urls"),
"no-angularjs-bypass-sce": require("./rules/no-angularjs-bypass-sce"),
"no-angularjs-enable-svg": require("./rules/no-angularjs-enable-svg"),
"no-angularjs-sanitization-whitelist": require("./rules/no-angularjs-sanitization-whitelist"),
"no-cookies": require("./rules/no-cookies"),
"no-document-domain": require("./rules/no-document-domain"),
"no-document-write": require("./rules/no-document-write"),
"no-electron-node-integration": require("./rules/no-electron-node-integration"),
"no-html-method": require("./rules/no-html-method"),
"no-inner-html": require("./rules/no-inner-html"),
"no-insecure-random": require("./rules/no-insecure-random"),
"no-insecure-url": require("./rules/no-insecure-url"),
"no-msapp-exec-unsafe": require("./rules/no-msapp-exec-unsafe"),
"no-postmessage-star-origin": require("./rules/no-postmessage-star-origin"),
"no-unsafe-alloc": require("./rules/no-unsafe-alloc"),
"no-winjs-html-unsafe": require("./rules/no-winjs-html-unsafe"),
"react-iframe-missing-sandbox": require("./rules/react-iframe-missing-sandbox"),
},
// Filled in later in order to reference plugin itself.
configs: {},
};
plugin.configs["angular"] = require("../config/angular")(plugin);
@ -46,23 +46,22 @@ plugin.configs["react"] = require("../config/react")(plugin);
plugin.configs["typescript"] = require("../config/react")(plugin);
plugin.configs["required"] = [
...plugin.configs["angular"],
...plugin.configs["angularjs"],
...plugin.configs["common"],
...plugin.configs["electron"],
...plugin.configs["node"],
...plugin.configs["react"]
...plugin.configs["angular"],
...plugin.configs["angularjs"],
...plugin.configs["common"],
...plugin.configs["electron"],
...plugin.configs["node"],
...plugin.configs["react"],
];
plugin.configs["recommended"] = [
...plugin.configs["required"],
...plugin.configs["typescript"],
{
plugins: {
security: pluginSecurity
}
}
...plugin.configs["required"],
...plugin.configs["typescript"],
{
plugins: {
security: pluginSecurity,
},
},
];
module.exports = plugin;

Просмотреть файл

@ -8,32 +8,31 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "Calls to bypassSecurityTrustHtml, bypassSecurityTrustScript and similar methods bypass DomSanitizer in Angular and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angular-bypass-sanitizer.md"
},
messages: {
noBypass: "Do not bypass Angular's built-in sanitizer"
}
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"Calls to bypassSecurityTrustHtml, bypassSecurityTrustScript and similar methods bypass DomSanitizer in Angular and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angular-bypass-sanitizer.md",
},
create: function(context) {
return {
"CallExpression[arguments!=''][callee.property.name=/bypassSecurityTrust(Html|ResourceUrl|Script|Style|Url)/]"(node) {
context.report(
{
node: node,
messageId: "noBypass"
});
}
};
}
};
messages: {
noBypass: "Do not bypass Angular's built-in sanitizer",
},
},
create: function (context) {
return {
"CallExpression[arguments!=''][callee.property.name=/bypassSecurityTrust(Html|ResourceUrl|Script|Style|Url)/]"(
node,
) {
context.report({
node: node,
messageId: "noBypass",
});
},
};
},
};

Просмотреть файл

@ -6,34 +6,33 @@
* @author Vivien Flouirac
*/
"use strict";
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "Calls to [`$compileProvider.aHrefSanitizationTrustedUrlList`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationTrustedUrlList) configure allowed Url list in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angular-sanitization-trusted-urls.md"
},
messages: {
noSanitizationTrustedUrls: "Do not modify the trusted Urls list in AngularJS"
}
},
create: function(context) {
return {
"CallExpression[arguments!=''][callee.object.name='$compileProvider'][callee.property.name=/(aHref|imgSrc)SanitizationTrustedUrlList/]"(node) {
context.report(
{
node: node,
messageId: "noSanitizationTrustedUrls"
});
}
};
}
};
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"Calls to [`$compileProvider.aHrefSanitizationTrustedUrlList`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationTrustedUrlList) configure allowed Url list in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angular-sanitization-trusted-urls.md",
},
messages: {
noSanitizationTrustedUrls: "Do not modify the trusted Urls list in AngularJS",
},
},
create: function (context) {
return {
"CallExpression[arguments!=''][callee.object.name='$compileProvider'][callee.property.name=/(aHref|imgSrc)SanitizationTrustedUrlList/]"(
node,
) {
context.report({
node: node,
messageId: "noSanitizationTrustedUrls",
});
},
};
},
};

Просмотреть файл

@ -8,56 +8,62 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "Calls to $sceProvider.enabled(false), $sceDelegate.trustAs(), $sce.trustAs() and relevant shorthand methods (e.g. trustAsHtml or trustAsJs) bypass Strict Contextual Escaping (SCE) in AngularJS and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-bypass-sce.md"
},
messages: {
doNotBypass: "Do not bypass Strict Contextual Escaping (SCE) in AngularJS"
}
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"Calls to $sceProvider.enabled(false), $sceDelegate.trustAs(), $sce.trustAs() and relevant shorthand methods (e.g. trustAsHtml or trustAsJs) bypass Strict Contextual Escaping (SCE) in AngularJS and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-bypass-sce.md",
},
create: function (context) {
messages: {
doNotBypass: "Do not bypass Strict Contextual Escaping (SCE) in AngularJS",
},
},
create: function (context) {
function reportIt(node) {
context.report({
node: node,
messageId: "doNotBypass",
});
}
function reportIt(node) {
context.report({
node: node,
messageId: "doNotBypass"
});
return {
"CallExpression[arguments!=''][callee.object.name='$sceProvider'][callee.property.name='enabled']"(
node,
) {
// Known false positives
if (
node.arguments == undefined ||
node.arguments.length != 1 ||
(node.arguments[0].type == "Literal" && /true|1/.test(node.arguments[0].value))
) {
return;
}
return reportIt(node);
},
"CallExpression[arguments!=''][callee.object.name='$sceDelegate'][callee.property.name='trustAs']":
reportIt,
"CallExpression[arguments!=''][callee.object.name='$sce'][callee.property.name=/trustAs(Css|Html|Js|ResourceUrl|Url)?/]"(
node,
) {
// Known false positives
if (
node.arguments &&
node.arguments.length === 1 &&
node.arguments[0].type === "Literal" &&
node.arguments[0].value === ""
) {
return;
}
return {
"CallExpression[arguments!=''][callee.object.name='$sceProvider'][callee.property.name='enabled']"(node) {
// Known false positives
if (node.arguments == undefined || node.arguments.length != 1 || (node.arguments[0].type == "Literal" && /true|1/.test(node.arguments[0].value))){
return;
}
return reportIt(node)
},
"CallExpression[arguments!=''][callee.object.name='$sceDelegate'][callee.property.name='trustAs']": reportIt,
"CallExpression[arguments!=''][callee.object.name='$sce'][callee.property.name=/trustAs(Css|Html|Js|ResourceUrl|Url)?/]"(node) {
// Known false positives
if (
node.arguments
&& node.arguments.length === 1
&& node.arguments[0].type === "Literal"
&& node.arguments[0].value === ""
) {
return;
}
return reportIt(node);
}
};
}
return reportIt(node);
},
};
},
};
// TODO: Review https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider#resourceUrlWhitelist and https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider#resourceUrlBlacklist

Просмотреть файл

@ -8,46 +8,41 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "Calls to $sanitizeProvider.enableSvg(true) increase attack surface of the application by enabling SVG support in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-enable-svg.md"
},
messages: {
doNotEnableSVG: "Do not enable SVG support in AngularJS"
}
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"Calls to $sanitizeProvider.enableSvg(true) increase attack surface of the application by enabling SVG support in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-enable-svg.md",
},
create: function (context) {
return {
"CallExpression[callee.object.name='$sanitizeProvider'][callee.property.name='enableSvg']"(node) {
// Known false positives
if (
(node.arguments != undefined &&
node.arguments.length != 1) ||
(
node.arguments[0].type == "Literal" && (
node.arguments[0].value == "false" || node.arguments[0].value == "0"
)
))
{
return;
}
context.report(
{
node: node,
messageId: "doNotEnableSVG"
});
}
};
}
messages: {
doNotEnableSVG: "Do not enable SVG support in AngularJS",
},
},
create: function (context) {
return {
"CallExpression[callee.object.name='$sanitizeProvider'][callee.property.name='enableSvg']"(
node,
) {
// Known false positives
if (
(node.arguments != undefined && node.arguments.length != 1) ||
(node.arguments[0].type == "Literal" &&
(node.arguments[0].value == "false" || node.arguments[0].value == "0"))
) {
return;
}
context.report({
node: node,
messageId: "doNotEnableSVG",
});
},
};
},
};
// TODO: Add rules for $sanitizeProvider.addValidElements() and $sanitizeProvider.addValidAttrs()
// TODO: Add rules for $sanitizeProvider.addValidElements() and $sanitizeProvider.addValidAttrs()

Просмотреть файл

@ -8,32 +8,31 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "Calls to [`$compileProvider.aHrefSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist) or [`$compileProvider.imgSrcSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#imgSrcSanitizationWhitelist) configure whitelists in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-sanitization-whitelist.md"
},
messages: {
noSanitizationWhitelist: "Do not modify sanitization whitelist in AngularJS"
}
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"Calls to [`$compileProvider.aHrefSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#aHrefSanitizationWhitelist) or [`$compileProvider.imgSrcSanitizationWhitelist`](https://docs.angularjs.org/api/ng/provider/$compileProvider#imgSrcSanitizationWhitelist) configure whitelists in AngularJS sanitizer and need to be reviewed.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-angularjs-sanitization-whitelist.md",
},
create: function (context) {
return {
"CallExpression[arguments!=''][callee.object.name='$compileProvider'][callee.property.name=/(aHref|imgSrc)SanitizationWhitelist/]"(node) {
context.report(
{
node: node,
messageId: "noSanitizationWhitelist"
});
}
};
}
};
messages: {
noSanitizationWhitelist: "Do not modify sanitization whitelist in AngularJS",
},
},
create: function (context) {
return {
"CallExpression[arguments!=''][callee.object.name='$compileProvider'][callee.property.name=/(aHref|imgSrc)SanitizationWhitelist/]"(
node,
) {
context.report({
node: node,
messageId: "noSanitizationWhitelist",
});
},
};
},
};

Просмотреть файл

@ -10,9 +10,6 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
@ -20,12 +17,13 @@ module.exports = {
schema: [],
docs: {
category: "Security",
description: "HTTP cookies are an old client-side storage mechanism with inherent risks and limitations. Use Web Storage, IndexedDB or other more modern methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-cookies.md"
description:
"HTTP cookies are an old client-side storage mechanism with inherent risks and limitations. Use Web Storage, IndexedDB or other more modern methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-cookies.md",
},
messages: {
doNotUseCookies: "Do not use HTTP cookies in modern applications"
}
doNotUseCookies: "Do not use HTTP cookies in modern applications",
},
},
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
@ -34,10 +32,10 @@ module.exports = {
if (astUtils.isDocumentObject(node.object, context, fullTypeChecker)) {
context.report({
node: node,
messageId: "doNotUseCookies"
messageId: "doNotUseCookies",
});
}
}
},
};
}
};
},
};

Просмотреть файл

@ -10,9 +10,6 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
@ -20,25 +17,25 @@ module.exports = {
schema: [],
docs: {
category: "Security",
description: "Writes to [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/Document/domain) property must be reviewed to avoid bypass of [same-origin checks](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin). Usage of top level domains such as `azurewebsites.net` is strictly prohibited.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-document-domain.md"
description:
"Writes to [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/Document/domain) property must be reviewed to avoid bypass of [same-origin checks](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin). Usage of top level domains such as `azurewebsites.net` is strictly prohibited.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-document-domain.md",
},
messages: {
default: 'Do not write to document.domain property'
}
default: "Do not write to document.domain property",
},
},
create: function(context) {
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
return {
"AssignmentExpression[operator='='][left.property.name='domain']"(node) {
if (astUtils.isDocumentObject(node.left.object, context, fullTypeChecker)) {
context.report(
{
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
}
},
};
}
};
},
};

Просмотреть файл

@ -10,9 +10,6 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
@ -20,25 +17,25 @@ module.exports = {
schema: [],
docs: {
category: "Security",
description: "Calls to document.write or document.writeln manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-document-write.md"
description:
"Calls to document.write or document.writeln manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-document-write.md",
},
messages: {
default: 'Do not write to DOM directly using document.write or document.writeln methods'
}
default: "Do not write to DOM directly using document.write or document.writeln methods",
},
},
create: function(context) {
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
return {
"CallExpression[arguments.length=1][callee.property.name=/write|writeln/]"(node) {
if (astUtils.isDocumentObject(node.callee.object, context, fullTypeChecker)) {
context.report(
{
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
}
},
};
}
};
},
};

Просмотреть файл

@ -7,32 +7,31 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description: "[Node.js Integration](https://www.electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) must not be enabled in any renderer that loads remote content to avoid remote code execution attacks.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-electron-node-integration.md"
},
messages: {
default: "Do not enable Node.js Integration for Remote Content"
}
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
category: "Security",
description:
"[Node.js Integration](https://www.electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) must not be enabled in any renderer that loads remote content to avoid remote code execution attacks.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-electron-node-integration.md",
},
create: function(context) {
return {
"NewExpression[callee.name=/BrowserWindow|BrowserView/] > ObjectExpression.arguments > Property.properties[key.name=webPreferences] > ObjectExpression.value > Property.properties[key.name=/nodeIntegration|nodeIntegrationInWorker|nodeIntegrationInSubFrames/][value.value='true']"(node) {
context.report(
{
node: node,
messageId: "default"
});
}
};
}
};
messages: {
default: "Do not enable Node.js Integration for Remote Content",
},
},
create: function (context) {
return {
"NewExpression[callee.name=/BrowserWindow|BrowserView/] > ObjectExpression.arguments > Property.properties[key.name=webPreferences] > ObjectExpression.value > Property.properties[key.name=/nodeIntegration|nodeIntegrationInWorker|nodeIntegrationInSubFrames/][value.value='true']"(
node,
) {
context.report({
node: node,
messageId: "default",
});
},
};
},
};

Просмотреть файл

@ -10,26 +10,24 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs:{
description: "Direct calls to method `html()` often (e.g. in jQuery framework) manipulate DOM without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-html-method.md"
docs: {
description:
"Direct calls to method `html()` often (e.g. in jQuery framework) manipulate DOM without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-html-method.md",
},
messages: {
default: 'Do not write to DOM directly using jQuery html() method'
}
default: "Do not write to DOM directly using jQuery html() method",
},
},
create: function(context) {
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
return {
// TODO:
// TODO:
// - Cover similar methods that can manipulate DOM such as append(string), jQuery(string)
// - Improve rule with type information from TypeScript parser
// - Consider ignoring all Literals?
@ -37,20 +35,16 @@ module.exports = {
// Known false positives
if (
// element.html("")
node.parent.arguments[0].type === "Literal"
&& (
node.parent.arguments[0].value === ""
|| node.parent.arguments[0].value === null
)
node.parent.arguments[0].type === "Literal" &&
(node.parent.arguments[0].value === "" || node.parent.arguments[0].value === null)
) {
return;
}
context.report(
{
context.report({
node: node,
messageId: "default"
});
}
messageId: "default",
});
},
};
}
};
},
};

Просмотреть файл

@ -10,22 +10,20 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
description: "Assignments to [innerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)/[outerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML) properties or calls to [insertAdjacentHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) method manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-inner-html.md"
description:
"Assignments to [innerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)/[outerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML) properties or calls to [insertAdjacentHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML) method manipulate DOM directly without any sanitization and should be avoided. Use document.createElement() or similar methods instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-inner-html.md",
},
messages: {
noInnerHtml: 'Do not write to DOM directly using innerHTML/outerHTML property',
noInsertAdjacentHTML: 'Do not write to DOM using insertAdjacentHTML method'
}
noInnerHtml: "Do not write to DOM directly using innerHTML/outerHTML property",
noInsertAdjacentHTML: "Do not write to DOM using insertAdjacentHTML method",
},
},
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
@ -36,15 +34,18 @@ module.exports = {
}
return {
"CallExpression[arguments.length=2] > MemberExpression.callee[property.name='insertAdjacentHTML']"(node) {
"CallExpression[arguments.length=2] > MemberExpression.callee[property.name='insertAdjacentHTML']"(
node,
) {
// Ignore known false positives
if (
node.parent != undefined
&& node.parent.arguments != undefined
&& node.parent.arguments.length >= 1
&& node.parent.arguments[1] != undefined
node.parent != undefined &&
node.parent.arguments != undefined &&
node.parent.arguments.length >= 1 &&
node.parent.arguments[1] != undefined &&
// element.insertAdjacentHTML('')
&& node.parent.arguments[1].type === 'Literal' && node.parent.arguments[1].value === ''
node.parent.arguments[1].type === "Literal" &&
node.parent.arguments[1].value === ""
) {
return;
}
@ -52,16 +53,19 @@ module.exports = {
if (mightBeHTMLElement(node.object)) {
context.report({
node: node,
messageId: "noInsertAdjacentHTML"
messageId: "noInsertAdjacentHTML",
});
}
},
"AssignmentExpression[left.type='MemberExpression'][left.property.name=/innerHTML|outerHTML/]"(node) {
"AssignmentExpression[left.type='MemberExpression'][left.property.name=/innerHTML|outerHTML/]"(
node,
) {
// Ignore known false positives
if (
node.right != undefined
node.right != undefined &&
// element.innerHTML = ''
&& node.right.type === 'Literal' && node.right.value === ''
node.right.type === "Literal" &&
node.right.value === ""
) {
return;
}
@ -69,10 +73,10 @@ module.exports = {
if (mightBeHTMLElement(node.left.object)) {
context.report({
node: node,
messageId: "noInnerHtml"
messageId: "noInnerHtml",
});
}
}
},
};
}
},
};

Просмотреть файл

@ -9,38 +9,36 @@
"use strict";
const astUtils = require("../ast-utils");
const path = require('path');
const path = require("path");
const bannedRandomLibraries = [
'chance',
'random-number',
'random-int',
'random-float',
'random-seed',
'unique-random'
]
"chance",
"random-number",
"random-int",
"random-float",
"random-seed",
"unique-random",
];
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs:{
docs: {
description: `Methods such as Math.random or crypto.pseudoRandomBytes do not produce cryptographically-secure random numbers and must not be used for security purposes such as generating tokens, passwords or keys.
Use crypto.randomBytes() or window.crypto.getRandomValues() instead.
`,
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-insecure-random.md"
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-insecure-random.md",
},
messages: {
default: 'Do not use pseudo-random number generators for generating secret values such as tokens, passwords or keys.'
}
default:
"Do not use pseudo-random number generators for generating secret values such as tokens, passwords or keys.",
},
},
create: function(context) {
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
return {
"CallExpression > MemberExpression[property.name='pseudoRandomBytes']"(node) {
@ -49,50 +47,50 @@ module.exports = {
if (fullTypeChecker) {
const type = astUtils.getNodeTypeAsString(fullTypeChecker, node.object, context);
notFalsePositive = type === "any" || type === "Crypto";
}else{
notFalsePositive = node.object.name === 'crypto';
} else {
notFalsePositive = node.object.name === "crypto";
}
if(notFalsePositive){
if (notFalsePositive) {
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
}
},
"CallExpression > MemberExpression[property.name='random']"(node) {
var notFalsePositive = false;
if (fullTypeChecker) {
const type = astUtils.getNodeTypeAsString(fullTypeChecker, node.object, context);
notFalsePositive = type === "any" || type === "Math";
}else{
notFalsePositive = node.object.name === 'Math';
} else {
notFalsePositive = node.object.name === "Math";
}
if(notFalsePositive){
if (notFalsePositive) {
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
},
ImportDeclaration(node){
if(bannedRandomLibraries.includes(path.basename(node.source.value))){
ImportDeclaration(node) {
if (bannedRandomLibraries.includes(path.basename(node.source.value))) {
context.report({
node: node,
messageId: "default"
});
messageId: "default",
});
}
},
"CallExpression[callee.name='require'][arguments.length=1]"(node){
"CallExpression[callee.name='require'][arguments.length=1]"(node) {
var requireName = path.parse(path.basename(node.arguments[0].value)).name;
if(bannedRandomLibraries.includes(requireName)){
if (bannedRandomLibraries.includes(requireName)) {
context.report({
node: node,
messageId: "default"
});
messageId: "default",
});
}
}
},
};
}
};
},
};

Просмотреть файл

@ -1,139 +1,159 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @fileoverview Disallows usage of insecure protocols in URL strings
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const DEFAULT_BLOCKLIST = [
/^(ftp|http|telnet|ws):\/\//i
];
const DEFAULT_EXCEPTIONS = [ // TODO: add more typical false positives such as XML schemas after more testing
/^http:(\/\/|\\u002f\\u002f)schemas\.microsoft\.com(\/\/|\\u002f\\u002f)?.*/i,
/^http:(\/\/|\\u002f\\u002f)schemas\.openxmlformats\.org(\/\/|\\u002f\\u002f)?.*/i,
/^http:(\/|\\u002f){2}localhost(:|\/|\\u002f)*/i,
/^http:(\/\/)www\.w3\.org\/1999\/xhtml/i,
/^http:(\/\/)www\.w3\.org\/2000\/svg/i
];
const DEFAULT_VARIABLES_EXECEPTIONS = [];
module.exports = {
defaultBlocklist: DEFAULT_BLOCKLIST,
defaultExceptions: DEFAULT_EXCEPTIONS,
defaultVarExecptions: DEFAULT_VARIABLES_EXECEPTIONS,
meta: {
type: "suggestion",
fixable: "code",
schema: [
{
type: "object",
properties: {
blocklist: {
type: "array",
items: {
type: "string"
}
},
exceptions: {
type: "array",
items: {
type: "string"
}
},
varExceptions: {
type: "array",
items: {
type: "string"
}
},
},
additionalProperties: false
}
],
docs: {
category: "Security",
description: "Insecure protocols such as [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) or [FTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol) should be replaced by their encrypted counterparts ([HTTPS](https://en.wikipedia.org/wiki/HTTPS), [FTPS](https://en.wikipedia.org/wiki/FTPS)) to avoid sending (potentially sensitive) data over untrusted network in plaintext.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-insecure-url.md"
},
messages: {
doNotUseInsecureUrl: "Do not use insecure URLs"
}
},
create: function (context) {
const options = context.options[0] || {};
const blocklist = (options.blocklist || DEFAULT_BLOCKLIST).map((pattern) => { return new RegExp(pattern, "i"); });
const exceptions = (options.exceptions || DEFAULT_EXCEPTIONS).map((pattern) => { return new RegExp(pattern, "i"); });
const varExceptions = (options.varExceptions || DEFAULT_VARIABLES_EXECEPTIONS).map((pattern) => { return new RegExp(pattern, "i"); });
function matches(patterns, value) {
return patterns.find((re) => { return re.test(value) }) !== undefined;
}
function shouldFix( varExceptions,context, node) {
// check variable for unfixable pattern e.g. `var insecureURL = "http://..."`
let text = node.parent
? context.sourceCode.getText(node.parent)
: context.sourceCode.getText(node);
// if no match, fix the line
return !matches(varExceptions,text);
}
return {
"Literal"(node) {
if (typeof node.value === "string") {
// Add an exception for xmlns attributes
if(node.parent && node.parent.type === "JSXAttribute" && node.parent.name && node.parent.name.name === "xmlns")
{
// Do nothing
}
else if (matches(blocklist, node.value) && !matches(exceptions, node.value) && shouldFix(varExceptions,context, node)) {
context.report({
node: node,
messageId: "doNotUseInsecureUrl",
fix(fixer) {
// Only fix if it contains an http url
if (node.value.toLowerCase().includes("http")) {
let fixedString = node.value.replace(/http:/i, "https:");
//insert an "s" before ":/" to change http:/ to https:/
return fixer.replaceText(node, JSON.stringify(fixedString));
}
},
});
}
}
},
"TemplateElement"(node) {
if (typeof node.value.raw === "string" && typeof node.value.cooked === "string") {
const rawStringText = node.value.raw;
const cookedStringText = node.value.cooked;
if (shouldFix(varExceptions,context, node) && (matches(blocklist, rawStringText) && !matches(exceptions, rawStringText)) ||
(matches(blocklist, cookedStringText) && !matches(exceptions, cookedStringText))) {
context.report({
node: node,
messageId: "doNotUseInsecureUrl",
fix(fixer) {
// Only fix if it contains an http url
if (node.value.raw.toLowerCase().includes("http")) {
let escapedString = JSON.stringify(context.sourceCode.getText(node));
// delete "" that JSON.stringify created and convert to `` string
escapedString = ``+ escapedString.substring(1, escapedString.length-1);
let fixedString = escapedString.replace(/http:/i, "https:");
//insert an "s" before ":/" to change http:/ to https:/
return fixer.replaceText(node, fixedString);
}
}
});
}
}
},
};
},
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @fileoverview Disallows usage of insecure protocols in URL strings
*/
"use strict";
const DEFAULT_BLOCKLIST = [/^(ftp|http|telnet|ws):\/\//i];
const DEFAULT_EXCEPTIONS = [
// TODO: add more typical false positives such as XML schemas after more testing
/^http:(\/\/|\\u002f\\u002f)schemas\.microsoft\.com(\/\/|\\u002f\\u002f)?.*/i,
/^http:(\/\/|\\u002f\\u002f)schemas\.openxmlformats\.org(\/\/|\\u002f\\u002f)?.*/i,
/^http:(\/|\\u002f){2}localhost(:|\/|\\u002f)*/i,
/^http:(\/\/)www\.w3\.org\/1999\/xhtml/i,
/^http:(\/\/)www\.w3\.org\/2000\/svg/i,
];
const DEFAULT_VARIABLES_EXECEPTIONS = [];
module.exports = {
defaultBlocklist: DEFAULT_BLOCKLIST,
defaultExceptions: DEFAULT_EXCEPTIONS,
defaultVarExecptions: DEFAULT_VARIABLES_EXECEPTIONS,
meta: {
type: "suggestion",
fixable: "code",
schema: [
{
type: "object",
properties: {
blocklist: {
type: "array",
items: {
type: "string",
},
},
exceptions: {
type: "array",
items: {
type: "string",
},
},
varExceptions: {
type: "array",
items: {
type: "string",
},
},
},
additionalProperties: false,
},
],
docs: {
category: "Security",
description:
"Insecure protocols such as [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) or [FTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol) should be replaced by their encrypted counterparts ([HTTPS](https://en.wikipedia.org/wiki/HTTPS), [FTPS](https://en.wikipedia.org/wiki/FTPS)) to avoid sending (potentially sensitive) data over untrusted network in plaintext.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-insecure-url.md",
},
messages: {
doNotUseInsecureUrl: "Do not use insecure URLs",
},
},
create: function (context) {
const options = context.options[0] || {};
const blocklist = (options.blocklist || DEFAULT_BLOCKLIST).map((pattern) => {
return new RegExp(pattern, "i");
});
const exceptions = (options.exceptions || DEFAULT_EXCEPTIONS).map((pattern) => {
return new RegExp(pattern, "i");
});
const varExceptions = (options.varExceptions || DEFAULT_VARIABLES_EXECEPTIONS).map(
(pattern) => {
return new RegExp(pattern, "i");
},
);
function matches(patterns, value) {
return (
patterns.find((re) => {
return re.test(value);
}) !== undefined
);
}
function shouldFix(varExceptions, context, node) {
// check variable for unfixable pattern e.g. `var insecureURL = "http://..."`
let text = node.parent
? context.sourceCode.getText(node.parent)
: context.sourceCode.getText(node);
// if no match, fix the line
return !matches(varExceptions, text);
}
return {
Literal(node) {
if (typeof node.value === "string") {
// Add an exception for xmlns attributes
if (
node.parent &&
node.parent.type === "JSXAttribute" &&
node.parent.name &&
node.parent.name.name === "xmlns"
) {
// Do nothing
} else if (
matches(blocklist, node.value) &&
!matches(exceptions, node.value) &&
shouldFix(varExceptions, context, node)
) {
context.report({
node: node,
messageId: "doNotUseInsecureUrl",
fix(fixer) {
// Only fix if it contains an http url
if (node.value.toLowerCase().includes("http")) {
let fixedString = node.value.replace(/http:/i, "https:");
//insert an "s" before ":/" to change http:/ to https:/
return fixer.replaceText(node, JSON.stringify(fixedString));
}
},
});
}
}
},
TemplateElement(node) {
if (typeof node.value.raw === "string" && typeof node.value.cooked === "string") {
const rawStringText = node.value.raw;
const cookedStringText = node.value.cooked;
if (
(shouldFix(varExceptions, context, node) &&
matches(blocklist, rawStringText) &&
!matches(exceptions, rawStringText)) ||
(matches(blocklist, cookedStringText) && !matches(exceptions, cookedStringText))
) {
context.report({
node: node,
messageId: "doNotUseInsecureUrl",
fix(fixer) {
// Only fix if it contains an http url
if (node.value.raw.toLowerCase().includes("http")) {
let escapedString = JSON.stringify(context.sourceCode.getText(node));
// delete "" that JSON.stringify created and convert to `` string
escapedString = `` + escapedString.substring(1, escapedString.length - 1);
let fixedString = escapedString.replace(/http:/i, "https:");
//insert an "s" before ":/" to change http:/ to https:/
return fixer.replaceText(node, fixedString);
}
},
});
}
}
},
};
},
};

Просмотреть файл

@ -8,31 +8,30 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs:{
description: "Calls to [`MSApp.execUnsafeLocalFunction()`](https://docs.microsoft.com/en-us/previous-versions/hh772324(v=vs.85)) bypass script injection validation and should be avoided.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-msapp-exec-unsafe.md"
docs: {
description:
"Calls to [`MSApp.execUnsafeLocalFunction()`](https://docs.microsoft.com/en-us/previous-versions/hh772324(v=vs.85)) bypass script injection validation and should be avoided.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-msapp-exec-unsafe.md",
},
messages: {
default: 'Do not bypass script injection validation'
}
default: "Do not bypass script injection validation",
},
},
create: function(context) {
create: function (context) {
return {
"CallExpression[arguments.length=1][callee.object.name='MSApp'][callee.property.name='execUnsafeLocalFunction']"(node) {
context.report(
{
node: node,
messageId: "default"
"CallExpression[arguments.length=1][callee.object.name='MSApp'][callee.property.name='execUnsafeLocalFunction']"(
node,
) {
context.report({
node: node,
messageId: "default",
});
}
},
};
}
};
},
};

Просмотреть файл

@ -9,35 +9,36 @@
const astUtils = require("../ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
description: "Always provide specific target origin, not * when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-postmessage-star-origin.md"
description:
"Always provide specific target origin, not * when sending data to other windows using [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns) to avoid data leakage outside of trust boundary.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-postmessage-star-origin.md",
},
messages: {
default: 'Do not use * as target origin when sending data to other windows'
}
default: "Do not use * as target origin when sending data to other windows",
},
},
create: function (context) {
const fullTypeChecker = astUtils.getFullTypeChecker(context);
return {
"CallExpression[arguments.length>=2][arguments.length<=3][callee.property.name=postMessage]"(node) {
"CallExpression[arguments.length>=2][arguments.length<=3][callee.property.name=postMessage]"(
node,
) {
// Check that second argument (target origin) is Literal "*"
if (!(node.arguments[1].type === 'Literal' && node.arguments[1].value == '*')) {
if (!(node.arguments[1].type === "Literal" && node.arguments[1].value == "*")) {
return;
}
// Check that object type is Window when full type information is available
if (fullTypeChecker) {
const tsNode = context.sourceCode.parserServices.esTreeNodeToTSNodeMap.get(node.callee.object);
const tsNode = context.sourceCode.parserServices.esTreeNodeToTSNodeMap.get(
node.callee.object,
);
const tsType = fullTypeChecker.getTypeAtLocation(tsNode);
const type = fullTypeChecker.typeToString(tsType);
if (type !== "any" && type !== "Window") {
@ -47,9 +48,9 @@ module.exports = {
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
},
};
}
};
},
};

Просмотреть файл

@ -3,21 +3,19 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs: {
description: "When calling [`Buffer.allocUnsafe`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafe_size) and [`Buffer.allocUnsafeSlow`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafeslow_size), the allocated memory is not wiped-out and can contain old, potentially sensitive data.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-unsafe-alloc.md"
description:
"When calling [`Buffer.allocUnsafe`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafe_size) and [`Buffer.allocUnsafeSlow`](https://nodejs.org/api/buffer.html#buffer_static_method_buffer_allocunsafeslow_size), the allocated memory is not wiped-out and can contain old, potentially sensitive data.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-unsafe-alloc.md",
},
messages: {
default: 'Do not allocate uninitialized buffers in Node.js'
}
default: "Do not allocate uninitialized buffers in Node.js",
},
},
create: function (context) {
return {
@ -28,19 +26,19 @@ module.exports = {
node.parent.arguments != undefined &&
node.parent.arguments.length != undefined &&
// Buffer.allocUnsafe(0);
node.parent.type === 'CallExpression' &&
node.parent.arguments.length == 1 &&
node.parent.type === "CallExpression" &&
node.parent.arguments.length == 1 &&
node.parent.arguments[0] != undefined &&
node.parent.arguments[0].type === 'Literal' &&
node.parent.arguments[0].value == '0'
node.parent.arguments[0].type === "Literal" &&
node.parent.arguments[0].value == "0"
) {
return;
}
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
},
};
}
};
},
};

Просмотреть файл

@ -8,31 +8,30 @@
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
fixable: "code",
schema: [],
docs:{
description: "Calls to [`WinJS.Utilities.setInnerHTMLUnsafe()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)) and similar methods do not perform any input validation and should be avoided. Use [`WinJS.Utilities.setInnerHTML()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)) instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-winjs-html-unsafe.md"
docs: {
description:
"Calls to [`WinJS.Utilities.setInnerHTMLUnsafe()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211696(v=win.10)) and similar methods do not perform any input validation and should be avoided. Use [`WinJS.Utilities.setInnerHTML()`](https://docs.microsoft.com/en-us/previous-versions/windows/apps/br211697(v=win.10)) instead.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-winjs-html-unsafe.md",
},
messages: {
default: 'Do not set HTML using unsafe methods from WinJS.Utilities'
}
default: "Do not set HTML using unsafe methods from WinJS.Utilities",
},
},
create: function(context) {
create: function (context) {
return {
"CallExpression[callee.object.object.name='WinJS'][callee.object.property.name='Utilities'][callee.property.name=/(insertAdjacent|setInner|setOuter)HTMLUnsafe/]"(node) {
context.report(
{
"CallExpression[callee.object.object.name='WinJS'][callee.object.property.name='Utilities'][callee.property.name=/(insertAdjacent|setInner|setOuter)HTMLUnsafe/]"(
node,
) {
context.report({
node: node,
messageId: "default"
messageId: "default",
});
}
},
};
}
};
},
};

79
lib/rules/react-iframe-missing-sandbox.js поставляемый
Просмотреть файл

@ -9,9 +9,6 @@
// TODO: Follow-up on https://github.com/yannickcr/eslint-plugin-react/issues/2754 and try to merge rule into eslint-plugin-react
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
@ -19,35 +16,38 @@ module.exports = {
schema: [],
docs: {
category: "Security",
description: "The [sandbox](https://www.w3schools.com/tags/att_iframe_sandbox.asp) attribute enables an extra set of restrictions for the content in the iframe and should always be specified.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/react-iframe-missing-sandbox.md"
description:
"The [sandbox](https://www.w3schools.com/tags/att_iframe_sandbox.asp) attribute enables an extra set of restrictions for the content in the iframe and should always be specified.",
url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/react-iframe-missing-sandbox.md",
},
messages: {
attributeMissing: 'An iframe element is missing a sandbox attribute',
invalidValue: 'An iframe element defines a sandbox attribute with invalid value "{{ value }}"',
invalidCombination: 'An iframe element defines a sandbox attribute with both allow-scripts and allow-same-origin which is invalid'
}
attributeMissing: "An iframe element is missing a sandbox attribute",
invalidValue:
'An iframe element defines a sandbox attribute with invalid value "{{ value }}"',
invalidCombination:
"An iframe element defines a sandbox attribute with both allow-scripts and allow-same-origin which is invalid",
},
},
create(context) {
const ALLOWED_VALUES = [
// From https://www.w3schools.com/tags/att_iframe_sandbox.asp
'',
'allow-forms',
'allow-modals',
'allow-orientation-lock',
'allow-pointer-lock',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',
'allow-scripts',
'allow-top-navigation',
'allow-top-navigation-by-user-activation'
"",
"allow-forms",
"allow-modals",
"allow-orientation-lock",
"allow-pointer-lock",
"allow-popups",
"allow-popups-to-escape-sandbox",
"allow-presentation",
"allow-same-origin",
"allow-scripts",
"allow-top-navigation",
"allow-top-navigation-by-user-activation",
];
function validateSandboxAttribute(node, attribute) {
const values = attribute.value.value.split(' ');
const values = attribute.value.value.split(" ");
let allowScripts = false;
let allowSameOrigin = false;
values.forEach((attributeValue) => {
@ -55,23 +55,23 @@ module.exports = {
if (ALLOWED_VALUES.indexOf(trimmedAttributeValue) === -1) {
context.report({
node,
messageId: 'invalidValue',
messageId: "invalidValue",
data: {
value: trimmedAttributeValue
}
value: trimmedAttributeValue,
},
});
}
if (trimmedAttributeValue === 'allow-scripts') {
if (trimmedAttributeValue === "allow-scripts") {
allowScripts = true;
}
if (trimmedAttributeValue === 'allow-same-origin') {
if (trimmedAttributeValue === "allow-same-origin") {
allowSameOrigin = true;
}
});
if (allowScripts && allowSameOrigin) {
context.report({
node,
messageId: 'invalidCombination'
messageId: "invalidCombination",
});
}
}
@ -80,17 +80,14 @@ module.exports = {
'JSXOpeningElement[name.name="iframe"]'(node) {
let sandboxAttributeFound = false;
node.attributes.forEach((attribute) => {
if (attribute.type === 'JSXAttribute'
&& attribute.name
&& attribute.name.type === 'JSXIdentifier'
&& attribute.name.name === 'sandbox'
if (
attribute.type === "JSXAttribute" &&
attribute.name &&
attribute.name.type === "JSXIdentifier" &&
attribute.name.name === "sandbox"
) {
sandboxAttributeFound = true;
if (
attribute.value
&& attribute.value.type === 'Literal'
&& attribute.value.value
) {
if (attribute.value && attribute.value.type === "Literal" && attribute.value.value) {
// Only string literals are supported for now
validateSandboxAttribute(node, attribute);
}
@ -99,10 +96,10 @@ module.exports = {
if (!sandboxAttributeFound) {
context.report({
node,
messageId: 'attributeMissing'
messageId: "attributeMissing",
});
}
}
},
};
}
};
},
};

16
package-lock.json сгенерированный
Просмотреть файл

@ -18,6 +18,7 @@
"@typescript-eslint/parser": "~8.6.0",
"eslint": "~9.11.0",
"mocha": "~10.7.0",
"prettier": "~3.3.0",
"typescript": "~5.5.0"
},
"engines": {
@ -2728,6 +2729,21 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",

Просмотреть файл

@ -17,6 +17,8 @@
"bugs": "https://github.com/microsoft/eslint-plugin-sdl/issues",
"main": "lib/index.js",
"scripts": {
"check-fmt": "prettier . --check",
"fmt": "prettier . --write",
"test": "mocha tests --recursive"
},
"dependencies": {
@ -29,6 +31,7 @@
"@typescript-eslint/parser": "~8.6.0",
"eslint": "~9.11.0",
"mocha": "~10.7.0",
"prettier": "~3.3.0",
"typescript": "~5.5.0"
},
"peerDependencies": {

6
tests/fixtures/ts/tsconfig.json поставляемый
Просмотреть файл

@ -1,5 +1,3 @@
{
"include": [
"estree.ts"
]
}
"include": ["estree.ts"]
}

12
tests/fixtures/tsx/tsconfig.json поставляемый
Просмотреть файл

@ -1,8 +1,6 @@
{
"compilerOptions": {
"jsx": "preserve"
},
"include": [
"estree.tsx"
]
}
"compilerOptions": {
"jsx": "preserve"
},
"include": ["estree.tsx"]
}

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -11,7 +11,7 @@ ruleTester.run(ruleId, rule, {
valid: [
"bypassSecurityTrustHtml('XSS')",
"x.bypassSecurityTrustHtml()",
"x.BypassSecurityTrustHtml('XSS')"
"x.BypassSecurityTrustHtml('XSS')",
],
invalid: [
{
@ -22,25 +22,25 @@ ruleTester.run(ruleId, rule, {
line: 1,
endLine: 1,
column: 1,
endColumn: 38
}
]
endColumn: 38,
},
],
},
{
code: "$('p').bypassSecurityTrustResourceUrl('XSS')",
errors: [{ messageId: "noBypass"}]
errors: [{ messageId: "noBypass" }],
},
{
code: "$('p').bypassSecurityTrustScript('XSS')",
errors: [{ messageId: "noBypass"}]
errors: [{ messageId: "noBypass" }],
},
{
code: "$('p').bypassSecurityTrustStyle('XSS')",
errors: [{ messageId: "noBypass"}]
errors: [{ messageId: "noBypass" }],
},
{
code: "$('p').bypassSecurityTrustUrl('XSS')",
errors: [{ messageId: "noBypass"}]
}
]
});
errors: [{ messageId: "noBypass" }],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -12,7 +12,7 @@ ruleTester.run(ruleId, rule, {
"aHrefSanitizationTrustedUrlList ('.*')",
"x.aHrefSanitizationTrustedUrlList ('.*')",
"$compileProvider.aHrefSanitizationTrustedUrlList ()",
"$compileProvider.AHrefSanitizationTrustedUrlList ('.*')"
"$compileProvider.AHrefSanitizationTrustedUrlList ('.*')",
],
invalid: [
{
@ -23,9 +23,9 @@ ruleTester.run(ruleId, rule, {
line: 1,
endLine: 1,
column: 1,
endColumn: 56
}
]
endColumn: 56,
},
],
},
{
code: "$compileProvider.imgSrcSanitizationTrustedUrlList('.*');",
@ -35,9 +35,9 @@ ruleTester.run(ruleId, rule, {
line: 1,
endLine: 1,
column: 1,
endColumn: 56
}
]
}
]
});
endColumn: 56,
},
],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -21,43 +21,43 @@ ruleTester.run(ruleId, rule, {
invalid: [
{
code: "$sceDelegate.trustAs($sce.HTML, 'XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAs($sce.HTML, 'XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAsCss('XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAsHtml('XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAsJs('XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAsResourceUrl('XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sce.trustAsUrl('XSS')",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sceProvider.enabled(false)",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sceProvider.enabled(0)",
errors: [{ messageId: "doNotBypass" }]
errors: [{ messageId: "doNotBypass" }],
},
{
code: "$sceProvider.enabled(true != true)",
errors: [{ messageId: "doNotBypass" }]
}
]
});
errors: [{ messageId: "doNotBypass" }],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -14,16 +14,16 @@ ruleTester.run(ruleId, rule, {
"$sanitizeProvider.enableSvg()",
"$sanitizeProvider.enableSvg(false)",
"$sanitizeProvider.enableSvg(0)",
"$sanitizeProvider.EnableSvg(0)"
"$sanitizeProvider.EnableSvg(0)",
],
invalid: [
{
code: "$sanitizeProvider.enableSvg(true)",
errors: [{ messageId: "doNotEnableSVG" }]
errors: [{ messageId: "doNotEnableSVG" }],
},
{
code: "$sanitizeProvider.enableSvg(1)",
errors: [{ messageId: "doNotEnableSVG" }]
}
]
});
errors: [{ messageId: "doNotEnableSVG" }],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -12,7 +12,7 @@ ruleTester.run(ruleId, rule, {
"aHrefSanitizationWhitelist('.*')",
"x.aHrefSanitizationWhitelist('.*')",
"$compileProvider.aHrefSanitizationWhitelist()",
"$compileProvider.AHrefSanitizationWhitelist('.*')"
"$compileProvider.AHrefSanitizationWhitelist('.*')",
],
invalid: [
{
@ -23,9 +23,9 @@ ruleTester.run(ruleId, rule, {
line: 1,
endLine: 1,
column: 1,
endColumn: 50
}
]
endColumn: 50,
},
],
},
{
code: "$compileProvider.imgSrcSanitizationWhitelist('.*');",
@ -35,9 +35,9 @@ ruleTester.run(ruleId, rule, {
line: 1,
endLine: 1,
column: 1,
endColumn: 51
}
]
}
]
});
endColumn: 51,
},
],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
const testUtils = require("../test-utils");
@ -39,25 +39,25 @@ function X() {
}
documentLikeAPIFunction().cookie = '...';
`
}
`,
},
],
invalid: [
{
code: "document.cookie = '...'",
errors: [{ messageId: "doNotUseCookies" }]
errors: [{ messageId: "doNotUseCookies" }],
},
{
code: "window.document.cookie = '...'",
errors: [{ messageId: "doNotUseCookies" }]
errors: [{ messageId: "doNotUseCookies" }],
},
{
code: "this.window.document.cookie = '...'",
errors: [{ messageId: "doNotUseCookies" }]
errors: [{ messageId: "doNotUseCookies" }],
},
{
code: "globalThis.window.document.cookie = '...'",
errors: [{ messageId: "doNotUseCookies" }]
errors: [{ messageId: "doNotUseCookies" }],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -67,7 +67,7 @@ function documentFunction(): Document {
}
documentFunction().cookie = '...';
`,
errors: [{ messageId: "doNotUseCookies" }]
errors: [{ messageId: "doNotUseCookies" }],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -78,7 +78,7 @@ namespace Sample {
}
}
`,
errors: [{ messageId: "doNotUseCookies" }]
}
]
});
errors: [{ messageId: "doNotUseCookies" }],
},
],
});

Просмотреть файл

@ -4,7 +4,7 @@
const path = require("path");
const testUtils = require("../test-utils");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -23,22 +23,22 @@ function main() {
var document: DocumentLikeAPI = documentLikeAPIFunction();
document.domain = 'somevalue';
}
`
}
`,
},
],
invalid: [
{
languageOptions: testUtils.tsLanguageOptions,
code: "var doc = window.document; doc.domain = 'somevalue';",
errors: [{ messageId: "default" }]
errors: [{ messageId: "default" }],
},
{
code: "document.domain = 'somevalue'",
errors: [{ messageId: "default" }]
errors: [{ messageId: "default" }],
},
{
code: "window.document.domain = 'somevalue'",
errors: [{ messageId: "default" }]
errors: [{ messageId: "default" }],
},
{
code: `
@ -48,19 +48,19 @@ window.document.domain = somevalue;
newWindow.document.domain = somevalue;
`,
errors: [
{
{
line: 3,
messageId: "default"
messageId: "default",
},
{
line: 4,
messageId: "default"
messageId: "default",
},
{
line: 5,
messageId: "default"
}
]
}
]
});
messageId: "default",
},
],
},
],
});

Просмотреть файл

@ -4,7 +4,7 @@
const path = require("path");
const testUtils = require("../test-utils");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -23,7 +23,7 @@ ruleTester.run(ruleId, rule, {
writeln: () => {},
};
}
`
`,
},
{
code: `
@ -43,8 +43,8 @@ ruleTester.run(ruleId, rule, {
document.write('', '');
document.writeln();
document.writeln('', '');
`
}
`,
},
],
invalid: [
{
@ -63,8 +63,8 @@ ruleTester.run(ruleId, rule, {
{ messageId: "default", line: 3 },
{ messageId: "default", line: 4 },
{ messageId: "default", line: 8 },
{ messageId: "default", line: 9 }
]
{ messageId: "default", line: 9 },
],
},
{
code: `
@ -81,8 +81,8 @@ ruleTester.run(ruleId, rule, {
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 },
{ messageId: "default", line: 7 }
]
}
]
{ messageId: "default", line: 7 },
],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -23,8 +23,8 @@ ruleTester.run(ruleId, rule, {
nodeIntegration: false
}
});
`
}
`,
},
],
invalid: [
{
@ -38,10 +38,10 @@ ruleTester.run(ruleId, rule, {
});
`,
errors: [
{ messageId: "default", line: 4},
{ messageId: "default", line: 5},
{ messageId: "default", line: 6}
]
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 },
],
},
{
code: `
@ -54,10 +54,10 @@ ruleTester.run(ruleId, rule, {
});
`,
errors: [
{ messageId: "default", line: 4},
{ messageId: "default", line: 5},
{ messageId: "default", line: 6}
]
}
]
});
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 },
],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
const testUtils = require("../test-utils");
@ -14,16 +14,16 @@ ruleTester.run(ruleId, rule, {
"test.html()",
"test.html('','')",
"element.html('');",
"element.html(null);"
"element.html(null);",
],
invalid: [
{
code: "$('p').html('XSS')",
errors: [{ messageId: "default", line: 1 }]
errors: [{ messageId: "default", line: 1 }],
},
{
code: "$(selector).html(sample_function())",
errors: [{ messageId: "default", line: 1 }]
errors: [{ messageId: "default", line: 1 }],
},
{
languageOptions: testUtils.es6LanguageOptions,
@ -31,9 +31,7 @@ ruleTester.run(ruleId, rule, {
import $ from "jquery";
test.html('XSS');
`,
errors: [
{ messageId: "default", line: 3 }
]
}
]
});
errors: [{ messageId: "default", line: 3 }],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
const testUtils = require("../test-utils");
@ -29,8 +29,8 @@ ruleTester.run(ruleId, rule, {
let test = new Test("test");
test.innerHTML = test;
test.outerHTML = test;
`
}
`,
},
],
invalid: [
// TypeScript with full type information
@ -45,8 +45,8 @@ ruleTester.run(ruleId, rule, {
errors: [
{ messageId: "noInnerHtml", line: 3 },
{ messageId: "noInnerHtml", line: 4 },
{ messageId: "noInsertAdjacentHTML", line: 5 }
]
{ messageId: "noInsertAdjacentHTML", line: 5 },
],
},
{
code: `
@ -55,8 +55,8 @@ ruleTester.run(ruleId, rule, {
`,
errors: [
{ messageId: "noInnerHtml", line: 2 },
{ messageId: "noInnerHtml", line: 3 }
]
{ messageId: "noInnerHtml", line: 3 },
],
},
{
code: `
@ -65,12 +65,12 @@ ruleTester.run(ruleId, rule, {
`,
errors: [
{ messageId: "noInnerHtml", line: 2 },
{ messageId: "noInnerHtml", line: 3 }
]
{ messageId: "noInnerHtml", line: 3 },
],
},
{
code: "element.insertAdjacentHTML('beforebegin', 'foo')",
errors: [{ messageId: "noInsertAdjacentHTML", line: 1 }]
}
]
});
errors: [{ messageId: "noInsertAdjacentHTML", line: 1 }],
},
],
});

Просмотреть файл

@ -3,7 +3,7 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
const testUtils = require("../test-utils");
@ -20,38 +20,36 @@ ruleTester.run(ruleId, rule, {
Math.random;
math.random();
random();
`
`,
},
{
code:`
code: `
require('./node_modules/not-unsafe-random');
require('eslint');
require('test');
require('random-package');
require('random-float2');
require('random2-seed');
`
`,
},
{
languageOptions: testUtils.es6LanguageOptions,
code:`
code: `
import './node_modules/untest';
import 'random';
import 'random-3';
import 'eslint';
import 'eslint-plugin-sdl';
import 'testing';
`
`,
},
{
code:`
code: `
cryptos.pseudoRandomBytes();
pseudoRandomBytes();
pseudoRandomByte();
cryptos.pseudoRondomBytes();
`
`,
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -62,11 +60,11 @@ ruleTester.run(ruleId, rule, {
Math.Random;
Math.random;
`
`,
},
{
languageOptions: testUtils.tsLanguageOptions,
code:`
code: `
function pseudoRandomBytes(){}
function pseudoRandomByte(){}
@ -74,8 +72,8 @@ ruleTester.run(ruleId, rule, {
pseudoRandomByte();
cryptos.pseudoRondomBytes();
cryptos.pseudoRondomBytes();
`
}
`,
},
],
invalid: [
{
@ -85,8 +83,8 @@ ruleTester.run(ruleId, rule, {
`,
errors: [
{ messageId: "default", line: 2 },
{ messageId: "default", line: 3 }
]
{ messageId: "default", line: 3 },
],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -96,8 +94,8 @@ ruleTester.run(ruleId, rule, {
`,
errors: [
{ messageId: "default", line: 2 },
{ messageId: "default", line: 3 }
]
{ messageId: "default", line: 3 },
],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -108,18 +106,14 @@ ruleTester.run(ruleId, rule, {
notMath().random();
`,
errors: [
{ messageId: "default", line: 6 }
]
errors: [{ messageId: "default", line: 6 }],
},
{
languageOptions: testUtils.tsLanguageOptions,
code: `
crypto.pseudoRandomBytes();
`,
errors: [
{ messageId: "default", line: 2 }
]
errors: [{ messageId: "default", line: 2 }],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -130,13 +124,11 @@ ruleTester.run(ruleId, rule, {
notCrypto().pseudoRandomBytes();
`,
errors: [
{ messageId: "default", line: 6 }
]
errors: [{ messageId: "default", line: 6 }],
},
{
languageOptions: testUtils.es6LanguageOptions,
code:`
code: `
import './node_modules/unique-random';
import 'chance';
import 'random-number';
@ -150,12 +142,12 @@ ruleTester.run(ruleId, rule, {
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 },
{ messageId: "default", line: 7 }
]
{ messageId: "default", line: 7 },
],
},
{
languageOptions: testUtils.es6LanguageOptions,
code:`
code: `
import * as chance1 from 'chance';
import defaultExport from 'chance';
import { chance } from 'chance';
@ -167,11 +159,11 @@ ruleTester.run(ruleId, rule, {
{ messageId: "default", line: 3 },
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 }
]
{ messageId: "default", line: 6 },
],
},
{
code:`
code: `
require('./node_modules/unique-random');
require('**/chance.js');
require('random-number');
@ -185,8 +177,8 @@ ruleTester.run(ruleId, rule, {
{ messageId: "default", line: 4 },
{ messageId: "default", line: 5 },
{ messageId: "default", line: 6 },
{ messageId: "default", line: 7 }
]
}
]
});
{ messageId: "default", line: 7 },
],
},
],
});

Просмотреть файл

@ -15,60 +15,75 @@ const testUtils = require("../test-utils");
let ruleTester = new RuleTester();
ruleTester.run(ruleId, rule, {
valid: [
{ // should allow https,ftps strings in variables
code: `
valid: [
{
// should allow https,ftps strings in variables
code: `
var x = 'https://www.example.com'
var y = 'ftps://www.example.com'
`
},
{ // should allow https,ftps template strings in variables
code: `
`,
},
{
// should allow https,ftps template strings in variables
code: `
var x = \`https://www.template-examples.com\`
var y = \`ftps://www.template-file-examples.com\`
`,
languageOptions: testUtils.es6LanguageOptions
},
{ // should allow https,ftps multipart template strings in variables
code: `
languageOptions: testUtils.es6LanguageOptions,
},
{
// should allow https,ftps multipart template strings in variables
code: `
var x = \`https://www.\${multipartExample}.com\`
var y = \`ftps://www.\${multipartExample}.com\`
`,
languageOptions: testUtils.es6LanguageOptions
},
{ // should allow http,ftp in middle of string
code: "var x = 'The protocol may be http://, https://, ftp:// or ftps://'"
},
{ // should allow https,ftps strings in default values
code: `
languageOptions: testUtils.es6LanguageOptions,
},
{
// should allow http,ftp in middle of string
code: "var x = 'The protocol may be http://, https://, ftp:// or ftps://'",
},
{
// should allow https,ftps strings in default values
code: `
function f(x : string = 'https://www.example.com') {}
function f(y : string = 'ftps://www.example.com') {}
`,
languageOptions: testUtils.tsLanguageOptions,
},
{ // should allow user-provided exceptions matches, regardless of upper/lower-case
code: `
languageOptions: testUtils.tsLanguageOptions,
},
{
// should allow user-provided exceptions matches, regardless of upper/lower-case
code: `
var a1 = 'http://www.allow-example.com'
var a2 = 'HtTp://www.allow-example.com/path'
var b1 = 'FTP://www.allow-file-example.com'
var c1 = 'LDaP://www.allow-ldap-example.com'
`,
options: [{
exceptions: ["HTTP:\/\/www\.allow-example\.com\/?.*", "FtP:\/\/www\.allow-file-example\.com", "LdaP:\/\/www\.allow-ldap-example\.com"]
}]
options: [
{
exceptions: [
"HTTP://www.allow-example.com/?.*",
"FtP://www.allow-file-example.com",
"LdaP://www.allow-ldap-example.com",
],
},
{ // should allow user-provided exceptions for variable name matches, regardless of upper/lower-case
code: `
],
},
{
// should allow user-provided exceptions for variable name matches, regardless of upper/lower-case
code: `
var insecureURL = 'http://www.allow-example.com'
var InSeCuReURL = 'ftp://www.allow-example.com/path'
`,
options: [{
varExceptions: ["insecure?.*"]
}]
},
options: [
{
// should allow xml namespaces, as they are not accessed by the browser
code: `
varExceptions: ["insecure?.*"],
},
],
},
{
// should allow xml namespaces, as they are not accessed by the browser
code: `
const someSvg: React.FC = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg">
@ -76,121 +91,132 @@ ruleTester.run(ruleId, rule, {
);
};
`,
languageOptions: testUtils.tsReactLanguageOptions,
},
{
// should allow localhost
code: `
languageOptions: testUtils.tsReactLanguageOptions,
},
{
// should allow localhost
code: `
var x = "http://localhost/test";
var y = "http://localhost";
`
},
{
// should allow xml namespaces for XHTML and SVG even if outside of jsx xmlns attribute
code: `
`,
},
{
// should allow xml namespaces for XHTML and SVG even if outside of jsx xmlns attribute
code: `
var x = "http://www.w3.org/1999/xhtml";
var y = "http://www.w3.org/2000/svg";
`
},
],
invalid: [
{ // should ban http,ftp strings in variables
code: `
`,
},
],
invalid: [
{
// should ban http,ftp strings in variables
code: `
var x1 = 'http://www.examples.com'
var x2 = 'HTTP://www.examples.com'
var y1 = 'ftp://www.file-examples.com'
var y2 = 'FTP://www.file-examples.com'
`,
output: `
output: `
var x1 = "https://www.examples.com"
var x2 = "https://www.examples.com"
var y1 = 'ftp://www.file-examples.com'
var y2 = 'FTP://www.file-examples.com'
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2},
{ messageId: "doNotUseInsecureUrl", line: 3},
{ messageId: "doNotUseInsecureUrl", line: 4},
{ messageId: "doNotUseInsecureUrl", line: 5}
],
},
{ // should ban http,ftp template strings in variables
code: `
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2 },
{ messageId: "doNotUseInsecureUrl", line: 3 },
{ messageId: "doNotUseInsecureUrl", line: 4 },
{ messageId: "doNotUseInsecureUrl", line: 5 },
],
},
{
// should ban http,ftp template strings in variables
code: `
var x1 = \`http://www.template-examples.com\`
var x2 = \`HTTP://www.template-examples.com\`
var y1 = \`ftp://www.file-examples.com\`
var y2 = \`FTP://www.file-examples.com\`
`,
output: `
output: `
var x1 = \`https://www.template-examples.com\`
var x2 = \`https://www.template-examples.com\`
var y1 = \`ftp://www.file-examples.com\`
var y2 = \`FTP://www.file-examples.com\`
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2},
{ messageId: "doNotUseInsecureUrl", line: 3},
{ messageId: "doNotUseInsecureUrl", line: 4},
{ messageId: "doNotUseInsecureUrl", line: 5}
],
languageOptions: testUtils.es6LanguageOptions
},
{ // should ban http,ftp multipart template strings in variables
code: `
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2 },
{ messageId: "doNotUseInsecureUrl", line: 3 },
{ messageId: "doNotUseInsecureUrl", line: 4 },
{ messageId: "doNotUseInsecureUrl", line: 5 },
],
languageOptions: testUtils.es6LanguageOptions,
},
{
// should ban http,ftp multipart template strings in variables
code: `
var x1 = \`http://www.\${multipartExample}.com\`;
var y1 = \`ftp://www.\${multipartExample}.com\`;
`,
output: `
output: `
var x1 = \`https://www.\${multipartExample}.com\`;
var y1 = \`ftp://www.\${multipartExample}.com\`;
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2},
{ messageId: "doNotUseInsecureUrl", line: 3},
],
languageOptions: testUtils.es6LanguageOptions
},
{ // should ban http,ftp strings in default values
code: `
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2 },
{ messageId: "doNotUseInsecureUrl", line: 3 },
],
languageOptions: testUtils.es6LanguageOptions,
},
{
// should ban http,ftp strings in default values
code: `
function f(x : string = 'http://www.example.com') {}
function f(y : string = 'ftp://www.example.com') {}
`,
output: `
output: `
function f(x : string = "https://www.example.com") {}
function f(y : string = 'ftp://www.example.com') {}
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2},
{ messageId: "doNotUseInsecureUrl", line: 3},
],
languageOptions: testUtils.tsLanguageOptions,
},
{ // should ban user-provided blacklist matches, regardless of upper/lower-case
code: `
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2 },
{ messageId: "doNotUseInsecureUrl", line: 3 },
],
languageOptions: testUtils.tsLanguageOptions,
},
{
// should ban user-provided blacklist matches, regardless of upper/lower-case
code: `
var a1 = 'http://www.ban-example.com'
var a2 = 'HTTP://www.ban-example.com/path'
var b1 = 'FtP://www.ban-file-example.com'
var c1 = 'LDAp://www.ban-ldap-example.com'
`,
output: `
output: `
var a1 = "https://www.ban-example.com"
var a2 = "https://www.ban-example.com/path"
var b1 = 'FtP://www.ban-file-example.com'
var c1 = 'LDAp://www.ban-ldap-example.com'
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2},
{ messageId: "doNotUseInsecureUrl", line: 3},
{ messageId: "doNotUseInsecureUrl", line: 4},
{ messageId: "doNotUseInsecureUrl", line: 5}
],
options: [{
blocklist: ["htTp:\/\/www\.ban-example\.com\/?.*", "fTp:\/\/www\.ban-file-example\.com\/?.*", "lDAp:\/\/www\.ban-ldap-example\.com\/?.*"]
}]
},
errors: [
{ messageId: "doNotUseInsecureUrl", line: 2 },
{ messageId: "doNotUseInsecureUrl", line: 3 },
{ messageId: "doNotUseInsecureUrl", line: 4 },
{ messageId: "doNotUseInsecureUrl", line: 5 },
],
options: [
{
// should ban any other xml attribute with urls in them
code: `
blocklist: [
"htTp://www.ban-example.com/?.*",
"fTp://www.ban-file-example.com/?.*",
"lDAp://www.ban-ldap-example.com/?.*",
],
},
],
},
{
// should ban any other xml attribute with urls in them
code: `
const someSvg: React.FC = () => {
return (
<svg someOtherAttribute="http://ban-example.com/">
@ -198,7 +224,7 @@ ruleTester.run(ruleId, rule, {
);
};
`,
output: `
output: `
const someSvg: React.FC = () => {
return (
<svg someOtherAttribute="https://ban-example.com/">
@ -206,38 +232,30 @@ ruleTester.run(ruleId, rule, {
);
};
`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 4},
],
languageOptions: testUtils.tsReactLanguageOptions,
},
{
// should escape the url string correctly
code: `var a1 = "http://moz\ti\tlla.org";`,
output: `var a1 = "https://moz\\ti\\tlla.org";`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 1},
],
},
{
// should fix url in `` correctly
code: "var x1 = `http://foo${multipartExample} http://${multipartExample}.com`;",
output: "var x1 = `https://foo${multipartExample} http://${multipartExample}.com`;",
errors: [
{ messageId: "doNotUseInsecureUrl", line: 1},
],
errors: [{ messageId: "doNotUseInsecureUrl", line: 4 }],
languageOptions: testUtils.tsReactLanguageOptions,
},
{
// should escape the url string correctly
code: `var a1 = "http://moz\ti\tlla.org";`,
output: `var a1 = "https://moz\\ti\\tlla.org";`,
errors: [{ messageId: "doNotUseInsecureUrl", line: 1 }],
},
{
// should fix url in `` correctly
code: "var x1 = `http://foo${multipartExample} http://${multipartExample}.com`;",
output: "var x1 = `https://foo${multipartExample} http://${multipartExample}.com`;",
errors: [{ messageId: "doNotUseInsecureUrl", line: 1 }],
languageOptions: testUtils.es6LanguageOptions
},
{
// should escape the string and fix it properly in ``
code: `var a1 = \`http://moz\ti\tlla.org\`;`,
output: `var a1 = \`https://moz\\ti\\tlla.org\`;`,
errors: [
{ messageId: "doNotUseInsecureUrl", line: 1},
],
languageOptions: testUtils.es6LanguageOptions,
},
{
// should escape the string and fix it properly in ``
code: `var a1 = \`http://moz\ti\tlla.org\`;`,
output: `var a1 = \`https://moz\\ti\\tlla.org\`;`,
errors: [{ messageId: "doNotUseInsecureUrl", line: 1 }],
languageOptions: testUtils.es6LanguageOptions
},
]
});
languageOptions: testUtils.es6LanguageOptions,
},
],
});

Просмотреть файл

@ -3,22 +3,17 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
const testUtils = require("../test-utils");
ruleTester.run(ruleId, rule, {
valid: [
"test.execUnsafeLocalFunction = 'test'",
"MSApp.execUnsafeLocalFunction()"
],
valid: ["test.execUnsafeLocalFunction = 'test'", "MSApp.execUnsafeLocalFunction()"],
invalid: [
{
code: "MSApp.execUnsafeLocalFunction(testfunc)",
errors: [
{ messageId: "default", line: 1, type: 'CallExpression' }
]
}
]
errors: [{ messageId: "default", line: 1, type: "CallExpression" }],
},
],
});

Просмотреть файл

@ -4,7 +4,7 @@
const path = require("path");
const testUtils = require("../test-utils");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
@ -27,8 +27,8 @@ function main() {
var w: WindowLike = new WindowLike();
w.postMessage('test', '*');
}
`
}
`,
},
],
invalid: [
{
@ -38,8 +38,8 @@ function main() {
`,
errors: [
{ messageId: "default", line: 2 },
{ messageId: "default", line: 3 }
]
{ messageId: "default", line: 3 },
],
},
{
languageOptions: testUtils.tsLanguageOptions,
@ -50,8 +50,8 @@ function main() {
`,
errors: [
{ messageId: "default", line: 2 },
{ messageId: "default", line: 4 }
]
{ messageId: "default", line: 4 },
],
},
]
});
],
});

Просмотреть файл

@ -4,16 +4,12 @@
"use strict";
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
ruleTester.run(ruleId, rule, {
valid: [
"foo.allocUnsafe",
"Buffer.allocUnsafe(0)",
"Buffer.allocUnsafeSlow(0)"
],
valid: ["foo.allocUnsafe", "Buffer.allocUnsafe(0)", "Buffer.allocUnsafeSlow(0)"],
invalid: [
{
code: `
@ -22,8 +18,8 @@ ruleTester.run(ruleId, rule, {
`,
errors: [
{ messageId: "default", line: 2 },
{ messageId: "default", line: 3 }
]
}
]
});
{ messageId: "default", line: 3 },
],
},
],
});

Просмотреть файл

@ -3,15 +3,13 @@
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
const testUtils = require("../test-utils");
ruleTester.run(ruleId, rule, {
valid: [
'element.insertAdjacentHTMLUnsafe = "test";'
],
valid: ['element.insertAdjacentHTMLUnsafe = "test";'],
invalid: [
{
code: `
@ -20,10 +18,10 @@ ruleTester.run(ruleId, rule, {
WinJS.Utilities.setOuterHTMLUnsafe(element, text);
`,
errors: [
{ messageId: "default", line: 2, type: 'CallExpression' },
{ messageId: "default", line: 3, type: 'CallExpression' },
{ messageId: "default", line: 4, type: 'CallExpression' }
]
}
]
{ messageId: "default", line: 2, type: "CallExpression" },
{ messageId: "default", line: 3, type: "CallExpression" },
{ messageId: "default", line: 4, type: "CallExpression" },
],
},
],
});

Просмотреть файл

@ -1,23 +1,23 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
'use strict';
"use strict";
const path = require("path");
const ruleId = path.parse(__filename).name;
const rule = require(path.join('../../../lib/rules/', ruleId));
const rule = require(path.join("../../../lib/rules/", ruleId));
const RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester({
languageOptions: {
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
sourceType: "module",
ecmaFeatures: {
jsx: true
}
jsx: true,
},
},
}
},
});
ruleTester.run(ruleId, rule, {
@ -37,45 +37,49 @@ ruleTester.run(ruleId, rule, {
{ code: '<iframe sandbox="allow-same-origin"></iframe>' },
{ code: '<iframe sandbox="allow-scripts"></iframe>' },
{ code: '<iframe sandbox="allow-top-navigation"></iframe>' },
{ code: '<iframe sandbox="allow-top-navigation-by-user-activation"></iframe>' },
{
code: '<iframe sandbox="allow-top-navigation-by-user-activation"></iframe>',
},
{ code: '<iframe sandbox="allow-forms allow-modals"></iframe>' },
{ code: '<iframe sandbox="allow-popups allow-popups-to-escape-sandbox allow-pointer-lock allow-same-origin allow-top-navigation"></iframe>' }
{
code: '<iframe sandbox="allow-popups allow-popups-to-escape-sandbox allow-pointer-lock allow-same-origin allow-top-navigation"></iframe>',
},
],
invalid: [
{
code: '<iframe></iframe>;',
errors: [{ messageId: 'attributeMissing' }]
code: "<iframe></iframe>;",
errors: [{ messageId: "attributeMissing" }],
},
{
code: '<iframe/>;',
errors: [{ messageId: 'attributeMissing' }]
code: "<iframe/>;",
errors: [{ messageId: "attributeMissing" }],
},
{
code: '<iframe sandbox="__unknown__"></iframe>',
errors: [{ messageId: 'invalidValue', data: { value: '__unknown__' } }]
errors: [{ messageId: "invalidValue", data: { value: "__unknown__" } }],
},
{
code: '<iframe sandbox="allow-popups __unknown__"/>',
errors: [{ messageId: 'invalidValue', data: { value: '__unknown__' } }]
errors: [{ messageId: "invalidValue", data: { value: "__unknown__" } }],
},
{
code: '<iframe sandbox="__unknown__ allow-popups"/>',
errors: [{ messageId: 'invalidValue', data: { value: '__unknown__' } }]
errors: [{ messageId: "invalidValue", data: { value: "__unknown__" } }],
},
{
code: '<iframe sandbox=" allow-forms __unknown__ allow-popups __unknown__ "/>',
errors: [
{ messageId: 'invalidValue', data: { value: '__unknown__' } },
{ messageId: 'invalidValue', data: { value: '__unknown__' } }
]
{ messageId: "invalidValue", data: { value: "__unknown__" } },
{ messageId: "invalidValue", data: { value: "__unknown__" } },
],
},
{
code: '<iframe sandbox="allow-scripts allow-same-origin"></iframe>;',
errors: [{ messageId: 'invalidCombination' }]
errors: [{ messageId: "invalidCombination" }],
},
{
code: '<iframe sandbox="allow-same-origin allow-scripts"/>;',
errors: [{ messageId: 'invalidCombination' }]
}
]
});
errors: [{ messageId: "invalidCombination" }],
},
],
});

Просмотреть файл

@ -11,27 +11,27 @@ const path = require("path");
const tsParser = require("@typescript-eslint/parser");
module.exports = {
es6LanguageOptions: {
parserOptions: {
ecmaVersion: 6,
sourceType: "module"
}
es6LanguageOptions: {
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
tsLanguageOptions: {
parser: tsParser,
parserOptions: {
tsconfigRootDir: path.join(__dirname, "..", "fixtures", "ts"),
projectService: true,
}
},
tsLanguageOptions: {
parser: tsParser,
parserOptions: {
tsconfigRootDir: path.join(__dirname, "..", "fixtures", "ts"),
projectService: true,
},
tsReactLanguageOptions: {
parser: tsParser,
parserOptions: {
tsconfigRootDir: path.join(__dirname, "..", "fixtures", "tsx"),
projectService: true,
ecmaFeatures: {
jsx: true
}
}
}
};
},
tsReactLanguageOptions: {
parser: tsParser,
parserOptions: {
tsconfigRootDir: path.join(__dirname, "..", "fixtures", "tsx"),
projectService: true,
ecmaFeatures: {
jsx: true,
},
},
},
};