mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-19 16:55:02 +02:00
fix(core): Import security audit risk reporters with a file extension (backport to release-candidate/2.32.x) (#35267)
Co-authored-by: Lorent Lempereur <looorent@users.noreply.github.com>
This commit is contained in:
parent
c580585cf4
commit
7d61ea0122
|
|
@ -0,0 +1,43 @@
|
|||
import { RuleTester } from '@typescript-eslint/rule-tester';
|
||||
|
||||
import { NoDynamicImportTemplateRule } from './no-dynamic-import-template.js';
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
ruleTester.run('no-dynamic-import-template', NoDynamicImportTemplateRule, {
|
||||
valid: [
|
||||
{
|
||||
code: 'await import(`./reporters/${name}.js`)',
|
||||
},
|
||||
{
|
||||
code: 'await import(`../reporters/${name}.mjs`)',
|
||||
},
|
||||
{
|
||||
code: 'await import(`./data/${name}.json`)',
|
||||
},
|
||||
{
|
||||
code: "await import('./reporters/credentials.js')",
|
||||
},
|
||||
{
|
||||
code: 'await import(`n8n-nodes-base/${name}`)',
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
code: 'await import(`@/security-audit/${name}.js`)',
|
||||
errors: [{ messageId: 'noDynamicImportTemplate' }],
|
||||
},
|
||||
{
|
||||
code: 'await import(`./reporters/${name}`)',
|
||||
errors: [{ messageId: 'missingExtension' }],
|
||||
},
|
||||
{
|
||||
code: 'await import(`../reporters/${name}`)',
|
||||
errors: [{ messageId: 'missingExtension' }],
|
||||
},
|
||||
{
|
||||
code: 'await import(`./reporters/${name}.ts`)',
|
||||
errors: [{ messageId: 'missingExtension' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -1,16 +1,20 @@
|
|||
import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
|
||||
|
||||
const MODULE_EXTENSIONS = ['.js', '.mjs', '.cjs', '.json', '.node'];
|
||||
|
||||
export const NoDynamicImportTemplateRule = ESLintUtils.RuleCreator.withoutDocs({
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description:
|
||||
'Disallow non-relative imports in template string argument to `await import()`, because `tsc-alias` as of 1.8.7 is unable to resolve aliased paths in this scenario.',
|
||||
'Disallow non-relative imports in template string argument to `await import()`, because `tsc-alias` as of 1.8.7 is unable to resolve aliased paths in this scenario. Also require an explicit file extension, because `module: NodeNext` emits a native `import()` whose specifier Node resolves without extension inference.',
|
||||
},
|
||||
schema: [],
|
||||
messages: {
|
||||
noDynamicImportTemplate:
|
||||
'Use relative imports in template string argument to `await import()`, because `tsc-alias` as of 1.8.7 is unable to resolve aliased paths in this scenario.',
|
||||
missingExtension:
|
||||
'End the template string argument to `await import()` with an explicit file extension (e.g. `.js`). Under `module: NodeNext` this compiles to a native `import()`, and Node throws ERR_MODULE_NOT_FOUND for an extensionless relative specifier.',
|
||||
},
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
|
@ -26,6 +30,23 @@ export const NoDynamicImportTemplateRule = ESLintUtils.RuleCreator.withoutDocs({
|
|||
messageId: 'noDynamicImportTemplate',
|
||||
});
|
||||
},
|
||||
|
||||
'AwaitExpression > ImportExpression > TemplateLiteral'(node: TSESTree.TemplateLiteral) {
|
||||
const head = node.quasis[0].value.cooked;
|
||||
|
||||
if (!head?.startsWith('./') && !head?.startsWith('../')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tail = node.quasis[node.quasis.length - 1].value.cooked ?? '';
|
||||
|
||||
if (!MODULE_EXTENSIONS.some((extension) => tail.endsWith(extension))) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'missingExtension',
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -63,11 +63,10 @@ export class SecurityAuditService {
|
|||
};
|
||||
|
||||
// `@vite-ignore` keeps vite's dynamic-import-vars plugin from analyzing this
|
||||
// runtime-only import: without a static file extension it otherwise errors,
|
||||
// which surfaces fatally during v8 coverage's uncovered-file walk.
|
||||
// runtime-only import, which surfaces fatally during v8 coverage's uncovered-file walk.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const RiskReporterModule = await import(
|
||||
/* @vite-ignore */ `./risk-reporters/${toFilename[className]}`
|
||||
/* @vite-ignore */ `./risk-reporters/${toFilename[className]}.js`
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user