Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit 2e866e8

Browse files
committed
Restrict loading of workspace versions of TSLint
Do not load the workspace version of TSLint by default
1 parent 9ae3af1 commit 2e866e8

File tree

10 files changed

+223
-61
lines changed

10 files changed

+223
-61
lines changed

.vscode/launch.json

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,12 @@
66
"configurations": [
77
{
88
"type": "node",
9-
"request": "launch",
10-
"name": "Mocha Tests",
11-
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
12-
"args": [
13-
"-u",
14-
"tdd",
15-
"--timeout",
16-
"999999",
17-
"--colors",
18-
"${workspaceFolder}/out/runner/test"
19-
],
20-
"internalConsoleOptions": "openOnSessionStart"
9+
"request": "attach",
10+
"name": "Attach",
11+
"port": 9999,
12+
"skipFiles": [
13+
"<node_internals>/**"
14+
]
2115
}
2216
]
2317
}

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 1.0.0 - November 30, 2020
4+
- Restricts when tslint is loaded from the workspace.
5+
- Global TSLint versions can always be loaded.
6+
- TSLint versions installed next to the plugin can always be loaded.
7+
- Otherwise, the consumer of the plugin must use `onConfigurationChanged` and explicitly enable `allowWorkspaceLibraryExecution`.
8+
- You can also force allow workspace versions of TSLint to be loaded by setting a `TS_TSLINT_ENABLE_WORKSPACE_LIBRARY_EXECUTION` environment variable.
9+
310
## 0.5.5 - November 11, 2019
411
- Restore old cwd after linting finishes.
512

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ TypeScript [language service plugin](https://blogs.msdn.microsoft.com/typescript
1010

1111
To use the plugin:
1212

13-
* Install TSLint 5+ in your workspace or globally.
13+
* Install TSLint 5+ in your workspace or globally (if you are using a local TSLint, see [workspace library execution](#workspace-library-execution))
1414

15-
* Install the plugin with `npm install typescript-tslint-plugin`
15+
* Install the plugin with `npm install typescript-tslint-plugin`
1616

1717
* Enable the plugin in your `tsconfig.json` file:
1818

@@ -28,6 +28,20 @@ To use the plugin:
2828

2929
See [editor support](#editor-support) for more detailed setup instructions.
3030

31+
## Workspace Library Execution
32+
33+
By default this plugin will not load TSLint or custom rules from the workspace if you are using a global version of TypeScript. This is done for security reasons. The plugin always allows using the global version of TSLint.
34+
35+
To use enable using a local TSLint install and custom rules from the workspace, you must either:
36+
37+
- Use a workspace version of TypeScript that is installed alongside TSLint.
38+
39+
- Enable workspace library execution in your editor of choice. This must be done through an editor and cannot be configured in a `tsconfig`.
40+
41+
In VS Code for example, you can run the `TSLint: Manage Workspace Library Execution` command to enable using the TSLint for the current workspace or for all workspaces.
42+
43+
- Set a `TS_TSLINT_ENABLE_WORKSPACE_LIBRARY_EXECUTION=1` environment variable and make sure the TypeScript server is run in an environment where this variable is set to true.
44+
3145
## Configuration options
3246

3347
**Notice**: This configuration settings allow you to configure the behavior of the typescript-tslint-plugin itself. To configure rules and tslint options you should use the `tslint.json` file.

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "typescript-tslint-plugin",
3-
"version": "0.5.5",
3+
"version": "1.0.0",
44
"description": "TypeScript tslint language service plugin",
55
"main": "out/index.js",
66
"author": "Microsoft",

src/index.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import * as ts_module from 'typescript/lib/tsserverlibrary';
33
import { Logger } from './logger';
44
import { ConfigurationManager } from './settings';
55
import * as mockRequire from 'mock-require';
6+
import { WorkspaceLibraryExecution } from './runner';
7+
8+
const enableWorkspaceLibraryExecutionEnvVar = 'TS_TSLINT_ENABLE_WORKSPACE_LIBRARY_EXECUTION';
69

710
export = function init({ typescript }: { typescript: typeof ts_module }) {
811
const configManager = new ConfigurationManager(typescript);
912
let logger: Logger | undefined;
13+
let plugin: TSLintPlugin | undefined;
1014

1115
// Make sure TS Lint imports the correct version of TS
1216
mockRequire('typescript', typescript);
@@ -24,13 +28,26 @@ export = function init({ typescript }: { typescript: typeof ts_module }) {
2428
return info.languageService;
2529
}
2630

27-
return new TSLintPlugin(typescript, info.languageServiceHost, logger, info.project, configManager)
28-
.decorate(info.languageService);
31+
plugin = new TSLintPlugin(typescript, info.languageServiceHost, logger, info.project, configManager);
32+
33+
// Allow clients that don't use onConfigurationChanged to still securely enable
34+
// workspace library execution with an env var.
35+
const workspaceLibraryFromEnv = process.env[enableWorkspaceLibraryExecutionEnvVar] ? WorkspaceLibraryExecution.Allow : WorkspaceLibraryExecution.Unknown;
36+
plugin.updateWorkspaceTrust(workspaceLibraryFromEnv);
37+
38+
return plugin.decorate(info.languageService);
2939
},
3040
onConfigurationChanged(config: any) {
3141
if (logger) {
3242
logger.info('onConfigurationChanged');
3343
}
44+
45+
if (plugin) {
46+
if ('allowWorkspaceLibraryExecution' in config) {
47+
plugin.updateWorkspaceTrust(config.allowWorkspaceLibraryExecution ? WorkspaceLibraryExecution.Allow : WorkspaceLibraryExecution.Disallow);
48+
}
49+
}
50+
3451
configManager.updateFromPluginConfig(config);
3552
},
3653
};

src/plugin.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as ts_module from 'typescript/lib/tsserverlibrary';
44
import { TSLINT_ERROR_CODE, TSLINT_ERROR_SOURCE } from './config';
55
import { ConfigFileWatcher } from './configFileWatcher';
66
import { Logger } from './logger';
7-
import { RunResult, TsLintRunner, toPackageManager } from './runner';
7+
import { RunResult, TsLintRunner, toPackageManager, WorkspaceLibraryExecution } from './runner';
88
import { ConfigurationManager } from './settings';
99
import { getNonOverlappingReplacements, filterProblemsForFile, getReplacements } from './runner/failures';
1010

@@ -52,7 +52,10 @@ class ProblemMap {
5252
export class TSLintPlugin {
5353
private readonly codeFixActions = new Map<string, ProblemMap>();
5454
private readonly configFileWatcher: ConfigFileWatcher;
55-
private readonly runner: TsLintRunner;
55+
56+
private runner: TsLintRunner;
57+
58+
private workspaceTrust = WorkspaceLibraryExecution.Unknown;
5659

5760
public constructor(
5861
private readonly ts: typeof ts_module,
@@ -118,6 +121,13 @@ export class TSLintPlugin {
118121
});
119122
}
120123

124+
public updateWorkspaceTrust(workspaceTrust: WorkspaceLibraryExecution) {
125+
this.workspaceTrust = workspaceTrust;
126+
127+
// Reset the runner
128+
this.runner = new TsLintRunner(message => { this.logger.info(message); });
129+
}
130+
121131
private getSemanticDiagnostics(
122132
delegate: (fileName: string) => ts_module.Diagnostic[],
123133
fileName: string,
@@ -150,6 +160,7 @@ export class TSLintPlugin {
150160
? Array.isArray(config.exclude) ? config.exclude : [config.exclude]
151161
: [],
152162
packageManager: toPackageManager(config.packageManager),
163+
workspaceLibraryExecution: this.workspaceTrust,
153164
});
154165
if (result.configFilePath) {
155166
this.configFileWatcher.ensureWatching(result.configFilePath);

0 commit comments

Comments
 (0)