From 654446fe4f1be77299e0d38a7016e825804dcbd1 Mon Sep 17 00:00:00 2001 From: Guillaume Weghsteen Date: Fri, 12 Jul 2024 09:57:15 +0000 Subject: [PATCH] Wire tsetse violations to ESLint message ids. Change-Id: Ic594a1ed16102e987bb2e47b6d30d0f524134d52 --- safety-web/src/trusted_types_checks.ts | 10 +- safety-web/src/tsetse_compat.ts | 91 +++++++++++++++++++ safety-web/test/test.ts | 2 +- .../expected_violations.json | 4 +- .../expected_violations.json | 4 +- .../expected_violations.json | 4 +- 6 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 safety-web/src/tsetse_compat.ts diff --git a/safety-web/src/trusted_types_checks.ts b/safety-web/src/trusted_types_checks.ts index 1f1087a..d4477be 100644 --- a/safety-web/src/trusted_types_checks.ts +++ b/safety-web/src/trusted_types_checks.ts @@ -16,6 +16,7 @@ import { ESLintUtils } from '@typescript-eslint/utils'; import { getConfiguredChecker } from './common/configured_checker'; import { Checker } from './common/third_party/tsetse/checker'; import * as ts from 'typescript'; +import { tsetseMessageToMessageId, messageIdMap } from './tsetse_compat'; const createRule = ESLintUtils.RuleCreator( () => 'safety-web', @@ -36,7 +37,7 @@ export const trustedTypesChecks = createRule({ recommended: 'strict', }, messages: { - // TODO: add the list of rules + ...messageIdMap, unknown_rule_triggered: 'trusted-types-checks reported a violation that could not be mapped to a known violation id.', }, schema: [], @@ -80,10 +81,11 @@ export const trustedTypesChecks = createRule({ start: { line: start.line + 1, column: start.character }, end: { line: end.line + 1, column: end.character }, }, - // TODO: create a messageId from the tsetse violation. - messageId: 'unknown_rule_triggered', + messageId: tsetseMessageToMessageId( + // TODO: refine `toDiagnostic` to refine type and remove this cast. + diagnostic.messageText as string) || 'unknown_rule_triggered', data: { - tsecMessage: diagnostic.messageText + tsetseMessage: diagnostic.messageText } }); } diff --git a/safety-web/src/tsetse_compat.ts b/safety-web/src/tsetse_compat.ts new file mode 100644 index 0000000..d2cec46 --- /dev/null +++ b/safety-web/src/tsetse_compat.ts @@ -0,0 +1,91 @@ +import { Rule as banBaseHrefAssignments } from './common/rules/dom_security/ban_base_href_assignments'; +import { Rule as banDocumentExeccommand } from './common/rules/dom_security/ban_document_execcommand'; +import { Rule as banDocumentWriteCalls } from './common/rules/dom_security/ban_document_write_calls'; +import { Rule as banDocumentWritelnCalls } from './common/rules/dom_security/ban_document_writeln_calls'; +import { Rule as banDomparserParsefromstring } from './common/rules/dom_security/ban_domparser_parsefromstring'; +import { Rule as banElementInnerhtmlAssignments } from './common/rules/dom_security/ban_element_innerhtml_assignments'; +import { Rule as banElementInsertadjacenthtml } from './common/rules/dom_security/ban_element_insertadjacenthtml'; +import { Rule as banElementOuterhtmlAssignments } from './common/rules/dom_security/ban_element_outerhtml_assignments'; +import { Rule as banElementSetattribute } from './common/rules/dom_security/ban_element_setattribute'; +import { Rule as banEvalCalls } from './common/rules/dom_security/ban_eval_calls'; +import { Rule as banFunctionCalls } from './common/rules/dom_security/ban_function_calls'; +import { Rule as banIframeSrcdocAssignments } from './common/rules/dom_security/ban_iframe_srcdoc_assignments'; +import { Rule as banObjectDataAssignments } from './common/rules/dom_security/ban_object_data_assignments'; +import { Rule as banRangeCreatecontextualfragment } from './common/rules/dom_security/ban_range_createcontextualfragment'; +import { Rule as banScriptAppendchildCalls } from './common/rules/dom_security/ban_script_appendchild_calls'; +import { Rule as banScriptContentAssignments } from './common/rules/dom_security/ban_script_content_assignments'; +import { Rule as banScriptSrcAssignments } from './common/rules/dom_security/ban_script_src_assignments'; +import { Rule as banServiceworkercontainerRegister } from './common/rules/dom_security/ban_serviceworkercontainer_register'; +import { Rule as banSharedWorkerCalls } from './common/rules/dom_security/ban_shared_worker_calls'; +import { Rule as banTrustedtypesCreatepolicy } from './common/rules/dom_security/ban_trustedtypes_createpolicy'; +import { Rule as banWindowStringfunctiondef } from './common/rules/dom_security/ban_window_stringfunctiondef'; +import { Rule as banWorkerCalls } from './common/rules/dom_security/ban_worker_calls'; +import { Rule as banWorkerImportscripts } from './common/rules/dom_security/ban_worker_importscripts'; +import { Rule as banLegacyConversions } from './common/rules/unsafe/ban_legacy_conversions'; +import { Rule as banReviewedConversions } from './common/rules/unsafe/ban_reviewed_conversions'; + +export const messageIdMap = { + ban_base_href_assignments: '{{ tsetseMessage }}', + ban_document_execcommand: '{{ tsetseMessage }}', + ban_document_write_calls: '{{ tsetseMessage }}', + ban_document_writeln_calls: '{{ tsetseMessage }}', + ban_domparser_parsefromstring: '{{ tsetseMessage }}', + ban_element_innerhtml_assignments: '{{ tsetseMessage }}', + ban_element_insertadjacenthtml: '{{ tsetseMessage }}', + ban_element_outerhtml_assignments: '{{ tsetseMessage }}', + ban_element_setattribute: '{{ tsetseMessage }}', + ban_eval_calls: '{{ tsetseMessage }}', + ban_function_calls: '{{ tsetseMessage }}', + ban_iframe_srcdoc_assignments: '{{ tsetseMessage }}', + ban_object_data_assignments: '{{ tsetseMessage }}', + ban_range_createcontextualfragment: '{{ tsetseMessage }}', + ban_script_appendchild_calls: '{{ tsetseMessage }}', + ban_script_content_assignments: '{{ tsetseMessage }}', + ban_script_src_assignments: '{{ tsetseMessage }}', + ban_serviceworkercontainer_register: '{{ tsetseMessage }}', + ban_shared_worker_calls: '{{ tsetseMessage }}', + ban_trustedtypes_createpolicy: '{{ tsetseMessage }}', + ban_window_stringfunctiondef: '{{ tsetseMessage }}', + ban_worker_calls: '{{ tsetseMessage }}', + ban_worker_importscripts: '{{ tsetseMessage }}', + ban_legacy_conversions: '{{ tsetseMessage }}', + ban_reviewed_conversions: '{{ tsetseMessage }}', +}; + +export type TrustedTypeCheckMessageId = keyof typeof messageIdMap; + +const ruleNameToMessageIdMap: Map = new Map([ + [banBaseHrefAssignments.RULE_NAME, 'ban_base_href_assignments'], + [banDocumentExeccommand.RULE_NAME, 'ban_document_execcommand'], + [banDocumentWriteCalls.RULE_NAME, 'ban_document_write_calls'], + [banDocumentWritelnCalls.RULE_NAME, 'ban_document_writeln_calls'], + [banDomparserParsefromstring.RULE_NAME, 'ban_domparser_parsefromstring'], + [banElementInnerhtmlAssignments.RULE_NAME, 'ban_element_innerhtml_assignments'], + [banElementInsertadjacenthtml.RULE_NAME, 'ban_element_insertadjacenthtml'], + [banElementOuterhtmlAssignments.RULE_NAME, 'ban_element_outerhtml_assignments'], + [banElementSetattribute.RULE_NAME, 'ban_element_setattribute'], + [banEvalCalls.RULE_NAME, 'ban_eval_calls'], + [banFunctionCalls.RULE_NAME, 'ban_function_calls'], + [banIframeSrcdocAssignments.RULE_NAME, 'ban_iframe_srcdoc_assignments'], + [banObjectDataAssignments.RULE_NAME, 'ban_object_data_assignments'], + [banRangeCreatecontextualfragment.RULE_NAME, 'ban_range_createcontextualfragment'], + [banScriptAppendchildCalls.RULE_NAME, 'ban_script_appendchild_calls'], + [banScriptContentAssignments.RULE_NAME, 'ban_script_content_assignments'], + [banScriptSrcAssignments.RULE_NAME, 'ban_script_src_assignments'], + [banServiceworkercontainerRegister.RULE_NAME, 'ban_serviceworkercontainer_register'], + [banSharedWorkerCalls.RULE_NAME, 'ban_shared_worker_calls'], + [banTrustedtypesCreatepolicy.RULE_NAME, 'ban_trustedtypes_createpolicy'], + [banWindowStringfunctiondef.RULE_NAME, 'ban_window_stringfunctiondef'], + [banWorkerCalls.RULE_NAME, 'ban_worker_calls'], + [banWorkerImportscripts.RULE_NAME, 'ban_worker_importscripts'], + [banLegacyConversions.RULE_NAME, 'ban_legacy_conversions'], + [banReviewedConversions.RULE_NAME, 'ban_reviewed_conversions'], +]); + +export function tsetseMessageToMessageId(tsetseMessage: string): TrustedTypeCheckMessageId | undefined { + const match = tsetseMessage.match(/^\[([a-z-]+)\]/); + if (match !== null) { + return ruleNameToMessageIdMap.get(match[1]); + } + return undefined; +} diff --git a/safety-web/test/test.ts b/safety-web/test/test.ts index 1a191c7..17c946e 100644 --- a/safety-web/test/test.ts +++ b/safety-web/test/test.ts @@ -39,7 +39,7 @@ ruleTester.run('trusted-types-checks', trustedTypesChecks, code: `document.createElement('script').innerHTML = 'foo';`, errors: [ { - messageId: 'unknown_rule_triggered', + messageId: 'ban_element_innerhtml_assignments', }, ], }, diff --git a/tests/basic_javascript_eslint9/expected_violations.json b/tests/basic_javascript_eslint9/expected_violations.json index bb2b619..a8b22cc 100644 --- a/tests/basic_javascript_eslint9/expected_violations.json +++ b/tests/basic_javascript_eslint9/expected_violations.json @@ -4,10 +4,10 @@ "messages": [ { "ruleId": "safety-web/trusted-types-checks", - "message": "trusted-types-checks reported a violation that could not be mapped to a known violation id.", + "message": "[ban-element-innerhtml-assignments] Assigning directly to Element#innerHTML can result in XSS vulnerabilities.", "line": 15, "column": 1, - "messageId": "unknown_rule_triggered", + "messageId": "ban_element_innerhtml_assignments", "endLine": 15, "endColumn": 51 } diff --git a/tests/basic_typescript_eslint8/expected_violations.json b/tests/basic_typescript_eslint8/expected_violations.json index df897b7..b334202 100644 --- a/tests/basic_typescript_eslint8/expected_violations.json +++ b/tests/basic_typescript_eslint8/expected_violations.json @@ -4,10 +4,10 @@ "messages": [ { "ruleId": "safety-web/trusted-types-checks", - "message": "trusted-types-checks reported a violation that could not be mapped to a known violation id.", + "message": "[ban-element-innerhtml-assignments] Assigning directly to Element#innerHTML can result in XSS vulnerabilities.", "line": 15, "column": 1, - "messageId": "unknown_rule_triggered", + "messageId": "ban_element_innerhtml_assignments", "endLine": 15, "endColumn": 51 } diff --git a/tests/basic_typescript_eslint9/expected_violations.json b/tests/basic_typescript_eslint9/expected_violations.json index df897b7..b334202 100644 --- a/tests/basic_typescript_eslint9/expected_violations.json +++ b/tests/basic_typescript_eslint9/expected_violations.json @@ -4,10 +4,10 @@ "messages": [ { "ruleId": "safety-web/trusted-types-checks", - "message": "trusted-types-checks reported a violation that could not be mapped to a known violation id.", + "message": "[ban-element-innerhtml-assignments] Assigning directly to Element#innerHTML can result in XSS vulnerabilities.", "line": 15, "column": 1, - "messageId": "unknown_rule_triggered", + "messageId": "ban_element_innerhtml_assignments", "endLine": 15, "endColumn": 51 }