diff --git a/.eslintrc.json b/.eslintrc.json index e26cd5d07..26e1beefd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -222,6 +222,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -252,6 +256,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -320,6 +332,41 @@ ] }, "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + }, { "files": [ ".projenrc.ts" diff --git a/packages/@aws-cdk-testing/cli-integ/.eslintrc.json b/packages/@aws-cdk-testing/cli-integ/.eslintrc.json index 12cf1184f..b96a4a843 100644 --- a/packages/@aws-cdk-testing/cli-integ/.eslintrc.json +++ b/packages/@aws-cdk-testing/cli-integ/.eslintrc.json @@ -123,6 +123,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -153,6 +157,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -318,5 +330,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk-testing/cli-integ/lib/cli/stage-distribution.ts b/packages/@aws-cdk-testing/cli-integ/lib/cli/stage-distribution.ts index 2376f5b40..8dd0365ec 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/cli/stage-distribution.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/cli/stage-distribution.ts @@ -108,6 +108,7 @@ async function main() { await usageDir.activateInCurrentProcess(); await shell(args.COMMAND ?? [], { + // eslint-disable-next-line no-restricted-syntax -- cli-integ deliberately runs commands through a shell to mimic real terminal invocation in integ tests. shell: true, show: 'always', }); diff --git a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts index 82c96a5f8..09aa05f0c 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/npm.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/npm.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- cli-integ is a test harness that spawns processes to exercise the CLI as a user would; it is test infrastructure, not shipped runtime. import { spawnSync } from 'child_process'; import * as semver from 'semver'; import { shell } from './shell'; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/repo-tools/npm.ts b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/repo-tools/npm.ts index 38e0e1e87..def67e48c 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/package-sources/repo-tools/npm.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/package-sources/repo-tools/npm.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- cli-integ is a test harness that spawns processes to exercise the CLI as a user would; it is test infrastructure, not shipped runtime. import * as child_process from 'child_process'; import * as fs from 'fs-extra'; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/process.ts b/packages/@aws-cdk-testing/cli-integ/lib/process.ts index 9b64ee585..7532ece64 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/process.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/process.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- cli-integ is a test harness that spawns processes to exercise the CLI as a user would; it is test infrastructure, not shipped runtime. import * as child from 'child_process'; import type { Readable, Writable } from 'stream'; import * as pty from 'node-pty'; @@ -63,6 +64,7 @@ export class Process { // (passing args with shell: true is deprecated because they are not escaped). const fullCommand = [command, ...args].join(' '); const process = child.spawn(fullCommand, [], { + // eslint-disable-next-line no-restricted-syntax -- cli-integ deliberately runs commands through a shell to mimic real terminal invocation in integ tests. shell: true, stdio: ['ignore', 'pipe', 'pipe'], ...options, diff --git a/packages/@aws-cdk-testing/cli-integ/lib/shell.ts b/packages/@aws-cdk-testing/cli-integ/lib/shell.ts index 436ee7633..1acd22efe 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/shell.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/shell.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- type-only import in cli-integ, a test harness that spawns processes to exercise the CLI; test infrastructure, not shipped runtime. import type * as child_process from 'child_process'; import * as fs from 'fs'; import * as os from 'os'; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts index 5923a445e..61d862662 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts @@ -518,6 +518,7 @@ export class TestFixture extends ShellHelper { '--username', username, '--password', '${ECR_PASSWORD}', 'public.ecr.aws'], { + // eslint-disable-next-line no-restricted-syntax -- cli-integ deliberately runs commands through a shell to mimic real terminal invocation in integ tests. shell: true, modEnv: { ECR_PASSWORD: password, diff --git a/packages/@aws-cdk-testing/cli-integ/lib/with-sam.ts b/packages/@aws-cdk-testing/cli-integ/lib/with-sam.ts index e3350a84c..7ae5eaecd 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/with-sam.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/with-sam.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports -- cli-integ is a test harness that spawns processes to exercise the CLI as a user would; it is test infrastructure, not shipped runtime. import * as child_process from 'child_process'; import * as os from 'os'; import * as path from 'path'; @@ -192,6 +193,7 @@ export async function shellWithAction( ...options, env, // Need this for Windows where we want .cmd and .bat to be found as well. + // eslint-disable-next-line no-restricted-syntax -- cli-integ deliberately runs commands through a shell to mimic real terminal invocation in integ tests. shell: true, stdio: ['ignore', 'pipe', 'pipe'], }); diff --git a/packages/@aws-cdk/cdk-assets-lib/.eslintrc.json b/packages/@aws-cdk/cdk-assets-lib/.eslintrc.json index a7966375f..4ed46c0ff 100644 --- a/packages/@aws-cdk/cdk-assets-lib/.eslintrc.json +++ b/packages/@aws-cdk/cdk-assets-lib/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -153,6 +157,14 @@ "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, { "name": "@aws-cdk/private-tools", "message": "Import shared tools from './private/tools' (the generated shim), not '@aws-cdk/private-tools' directly." @@ -336,5 +348,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/cdk-explorer/.eslintrc.json b/packages/@aws-cdk/cdk-explorer/.eslintrc.json index e0c610e49..41efb7f7f 100644 --- a/packages/@aws-cdk/cdk-explorer/.eslintrc.json +++ b/packages/@aws-cdk/cdk-explorer/.eslintrc.json @@ -121,6 +121,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -151,6 +155,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -316,5 +328,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/cli-plugin-contract/.eslintrc.json b/packages/@aws-cdk/cli-plugin-contract/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/@aws-cdk/cli-plugin-contract/.eslintrc.json +++ b/packages/@aws-cdk/cli-plugin-contract/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/cloud-assembly-api/.eslintrc.json b/packages/@aws-cdk/cloud-assembly-api/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/@aws-cdk/cloud-assembly-api/.eslintrc.json +++ b/packages/@aws-cdk/cloud-assembly-api/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/cloud-assembly-schema/.eslintrc.json b/packages/@aws-cdk/cloud-assembly-schema/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/.eslintrc.json +++ b/packages/@aws-cdk/cloud-assembly-schema/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/cloudformation-diff/.eslintrc.json b/packages/@aws-cdk/cloudformation-diff/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/@aws-cdk/cloudformation-diff/.eslintrc.json +++ b/packages/@aws-cdk/cloudformation-diff/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/integ-runner/.eslintrc.json b/packages/@aws-cdk/integ-runner/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/@aws-cdk/integ-runner/.eslintrc.json +++ b/packages/@aws-cdk/integ-runner/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/integ-runner/lib/utils.ts b/packages/@aws-cdk/integ-runner/lib/utils.ts index e1a1b3bf6..f0329a464 100644 --- a/packages/@aws-cdk/integ-runner/lib/utils.ts +++ b/packages/@aws-cdk/integ-runner/lib/utils.ts @@ -1,4 +1,5 @@ // Helper functions for CDK Exec +// eslint-disable-next-line no-restricted-imports -- integ-runner is test tooling; exec() spawns an argv array with no shell, so this is safe. Migrating onto the shared subprocess tool is deferred follow-up work. import { spawnSync } from 'child_process'; /** diff --git a/packages/@aws-cdk/private-tools/.eslintrc.json b/packages/@aws-cdk/private-tools/.eslintrc.json index e0c610e49..41efb7f7f 100644 --- a/packages/@aws-cdk/private-tools/.eslintrc.json +++ b/packages/@aws-cdk/private-tools/.eslintrc.json @@ -121,6 +121,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -151,6 +155,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -316,5 +328,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/private-tools/lib/subprocess/index.ts b/packages/@aws-cdk/private-tools/lib/subprocess/index.ts index fe827d0ef..fbf5bb070 100644 --- a/packages/@aws-cdk/private-tools/lib/subprocess/index.ts +++ b/packages/@aws-cdk/private-tools/lib/subprocess/index.ts @@ -16,6 +16,7 @@ * the only path to a shell and takes no argv form, so command lines can * never be assembled from parts by this codebase. */ +// eslint-disable-next-line no-restricted-imports -- this module IS the sanctioned wrapper around child_process import * as child_process from 'child_process'; import { StringDecoder } from 'string_decoder'; import spawn from 'cross-spawn'; @@ -279,6 +280,7 @@ export function runSync(argv: readonly string[], options: RunSyncOptions = {}): export async function runUserCommandLine(commandLine: string, options: RunOptions = {}): Promise { const child = child_process.spawn(commandLine, { ...spawnOptions(options), + // eslint-disable-next-line no-restricted-syntax -- this is the single sanctioned shell entry point (see the module header) shell: true, }); return monitor(child, commandLine, options); diff --git a/packages/@aws-cdk/toolkit-lib/.eslintrc.json b/packages/@aws-cdk/toolkit-lib/.eslintrc.json index 6a8e078ea..8c3e061a1 100644 --- a/packages/@aws-cdk/toolkit-lib/.eslintrc.json +++ b/packages/@aws-cdk/toolkit-lib/.eslintrc.json @@ -119,6 +119,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -150,6 +154,14 @@ "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, { "name": "@aws-cdk/private-tools", "message": "Import shared tools from './private/tools' (the generated shim), not '@aws-cdk/private-tools' directly." @@ -332,6 +344,41 @@ "@cdklabs/no-throw-default-error": "error" }, "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + }, { "files": [ "./test/**" diff --git a/packages/@aws-cdk/user-input-gen/.eslintrc.json b/packages/@aws-cdk/user-input-gen/.eslintrc.json index e0c610e49..41efb7f7f 100644 --- a/packages/@aws-cdk/user-input-gen/.eslintrc.json +++ b/packages/@aws-cdk/user-input-gen/.eslintrc.json @@ -121,6 +121,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -151,6 +155,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -316,5 +328,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/@aws-cdk/yarn-cling/.eslintrc.json b/packages/@aws-cdk/yarn-cling/.eslintrc.json index e0c610e49..41efb7f7f 100644 --- a/packages/@aws-cdk/yarn-cling/.eslintrc.json +++ b/packages/@aws-cdk/yarn-cling/.eslintrc.json @@ -121,6 +121,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -151,6 +155,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -316,5 +328,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/aws-cdk/.eslintrc.json b/packages/aws-cdk/.eslintrc.json index b28fc0ca0..069e325d1 100644 --- a/packages/aws-cdk/.eslintrc.json +++ b/packages/aws-cdk/.eslintrc.json @@ -119,6 +119,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -150,6 +154,14 @@ "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, { "name": "@aws-cdk/private-tools", "message": "Import shared tools from './private/tools' (the generated shim), not '@aws-cdk/private-tools' directly." @@ -328,6 +340,41 @@ "@cdklabs/no-throw-default-error": "error" }, "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + }, { "files": [ "./test/**" diff --git a/packages/cdk-assets/.eslintrc.json b/packages/cdk-assets/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/cdk-assets/.eslintrc.json +++ b/packages/cdk-assets/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/packages/cdk/.eslintrc.json b/packages/cdk/.eslintrc.json index 625959c6e..a2b63dee4 100644 --- a/packages/cdk/.eslintrc.json +++ b/packages/cdk/.eslintrc.json @@ -122,6 +122,10 @@ { "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", "message": "Use the md5hash() function from the core library if you want md5" + }, + { + "selector": "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + "message": "Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line." } ], "no-throw-literal": [ @@ -152,6 +156,14 @@ { "name": "punycode", "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + }, + { + "name": "child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." + }, + { + "name": "node:child_process", + "message": "Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool ('./private/tools')." } ], "patterns": [ @@ -317,5 +329,41 @@ "off" ] }, - "overrides": [] + "overrides": [ + { + "files": [ + "**/test/**", + "**/tests/**", + "**/*.test.ts", + "**/*.integtest.ts", + "projenrc/**", + "**/projenrc/**", + ".projenrc.ts", + "**/.projenrc.ts" + ], + "rules": { + "no-restricted-imports": [ + "error", + { + "paths": [ + { + "name": "punycode", + "message": "Package 'punycode' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation" + } + ], + "patterns": [ + "!punycode/" + ] + } + ], + "no-restricted-syntax": [ + "error", + { + "selector": "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + "message": "Use the md5hash() function from the core library if you want md5" + } + ] + } + } + ] } diff --git a/projenrc/eslint/imports.ts b/projenrc/eslint/imports.ts index 1d4c4b902..82cab159a 100644 --- a/projenrc/eslint/imports.ts +++ b/projenrc/eslint/imports.ts @@ -1,3 +1,8 @@ +export const PUNYCODE_IMPORT_RESTRICTION = { + name: 'punycode', + message: 'Package \'punycode\' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation', +}; + export default { 'import/no-unresolved': ['error'], // Require all imported libraries actually resolve (!!required for import/no-extraneous-dependencies to work!!) 'import/no-duplicates': 'error', // Cannot import from the same module twice (we prefer `import/no-duplicate` over `no-duplicate-imports` since the former can handle type imports) @@ -15,9 +20,15 @@ export default { 'no-restricted-imports': [ 'error', { paths: [ + PUNYCODE_IMPORT_RESTRICTION, + // Route child process spawning through the shared subprocess tool. + { + name: 'child_process', + message: 'Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool (\'./private/tools\').', + }, { - name: 'punycode', - message: 'Package \'punycode\' has to be imported with trailing slash, see warning in https://github.com/bestiejs/punycode.js#installation', + name: 'node:child_process', + message: 'Do not use `child_process` directly. Use `run`/`runSync`/`runUserCommandLine` from the subprocess tool (\'./private/tools\').', }, ], patterns: ['!punycode/'], diff --git a/projenrc/eslint/index.ts b/projenrc/eslint/index.ts index 45c78eeda..b939d6da9 100644 --- a/projenrc/eslint/index.ts +++ b/projenrc/eslint/index.ts @@ -3,10 +3,10 @@ import type { typescript } from 'projen'; import bestPractices from './best-practices'; import constructs from './constructs'; import formatting from './formatting'; -import imports from './imports'; +import imports, { PUNYCODE_IMPORT_RESTRICTION } from './imports'; import jest from './jest'; import jsdoc from './jsdoc'; -import team from './team'; +import team, { MD5_SYNTAX_RESTRICTION } from './team'; const ESLINT_RULES = { ...team, @@ -60,6 +60,22 @@ export function configureEslint(x: typescript.TypeScriptProject) { 'plugin:jest/recommended', ); x.eslint?.addRules(ESLINT_RULES); + x.eslint?.addOverride({ + files: [ + '**/test/**', + '**/tests/**', + '**/*.test.ts', + '**/*.integtest.ts', + 'projenrc/**', + '**/projenrc/**', + '.projenrc.ts', + '**/.projenrc.ts', + ], + rules: { + 'no-restricted-imports': ['error', { paths: [PUNYCODE_IMPORT_RESTRICTION], patterns: ['!punycode/'] }], + 'no-restricted-syntax': ['error', MD5_SYNTAX_RESTRICTION], + }, + }); // For our published packages, we need all type imports to be from a public dependency if (!isRoot && !isPrivate && x.eslint) { diff --git a/projenrc/eslint/team.ts b/projenrc/eslint/team.ts index 7005209af..f648d4db3 100644 --- a/projenrc/eslint/team.ts +++ b/projenrc/eslint/team.ts @@ -1,16 +1,29 @@ // CDK team specific rules // These are typically informed by past operational events + +// No more md5, will break in FIPS environments +export const MD5_SYNTAX_RESTRICTION = { + // Both qualified and unqualified calls + selector: "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", + message: 'Use the md5hash() function from the core library if you want md5', +}; + export default { // This can cause huge I/O performance hits '@cdklabs/promiseall-no-unbounded-parallelism': ['error'], - // No more md5, will break in FIPS environments 'no-restricted-syntax': [ 'error', + MD5_SYNTAX_RESTRICTION, { - // Both qualified and unqualified calls - selector: "CallExpression:matches([callee.name='createHash'], [callee.property.name='createHash']) Literal[value='md5']", - message: 'Use the md5hash() function from the core library if you want md5', + // Spawning through a shell is the one place command injection can happen. + // The only sanctioned shell entry point is `runUserCommandLine` in the + // subprocess tool (which carries its own eslint-disable); everything else + // must spawn an argv array via `run`/`runSync`, which never touch a shell. + // + // Reject any `shell` property that is not statically `false`. + selector: "Property:matches([key.name='shell'], [key.value='shell']):not([value.type='Literal'][value.value=false])", + message: 'Do not enable the `shell` spawn option. Use `run`/`runSync` (argv, no shell) from the subprocess tool, or `runUserCommandLine` for a user-authored command line.', }, ], };