This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v2-8-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit aa1ca2170346762a385b9c1eb7e4e66556746b54
Author: Amogh Desai <[email protected]>
AuthorDate: Thu Jan 25 23:37:06 2024 +0530

    Making links in task logs as hyperlinks by preventing HTML injection 
(#36829)
    
    (cherry picked from commit 6629e2bf7b80d07f2cf61895873521400cdb0d5b)
---
 airflow/www/package.json                           |  2 +
 .../js/dag/details/taskInstance/Logs/LogBlock.tsx  |  2 +-
 .../js/dag/details/taskInstance/Logs/utils.ts      | 27 ++++++-
 airflow/www/yarn.lock                              | 83 ++++++++++++++++++++++
 4 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/airflow/www/package.json b/airflow/www/package.json
index 12b25445ba..2beb8ef37f 100644
--- a/airflow/www/package.json
+++ b/airflow/www/package.json
@@ -55,6 +55,7 @@
     "@types/react-dom": "^18.0.5",
     "@types/react-syntax-highlighter": "^15.5.6",
     "@types/react-table": "^7.7.12",
+    "@types/sanitize-html": "^2.9.5",
     "@typescript-eslint/eslint-plugin": "^5.13.0",
     "@typescript-eslint/parser": "^5.0.0",
     "babel-jest": "^27.3.1",
@@ -140,6 +141,7 @@
     "reactflow": "^11.7.4",
     "redoc": "^2.0.0-rc.72",
     "remark-gfm": "^3.0.1",
+    "sanitize-html": "^2.11.0",
     "swagger-ui-dist": "4.1.3",
     "tsconfig-paths": "^3.14.2",
     "type-fest": "^2.17.0",
diff --git a/airflow/www/static/js/dag/details/taskInstance/Logs/LogBlock.tsx 
b/airflow/www/static/js/dag/details/taskInstance/Logs/LogBlock.tsx
index f92e8a80a4..dad3fda391 100644
--- a/airflow/www/static/js/dag/details/taskInstance/Logs/LogBlock.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/LogBlock.tsx
@@ -73,7 +73,7 @@ const LogBlock = ({ parsedLogs, wrap, tryNumber }: Props) => {
       borderRadius={3}
       borderColor="blue.500"
     >
-      {parsedLogs}
+      <div dangerouslySetInnerHTML={{ __html: parsedLogs }} />
       <div ref={codeBlockBottomDiv} />
     </Code>
   );
diff --git a/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts 
b/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
index 80b534ccd5..c3c4084044 100644
--- a/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
@@ -21,6 +21,8 @@
 
 import { defaultFormatWithTZ } from "src/datetime_utils";
 
+import sanitizeHtml from "sanitize-html";
+
 export enum LogLevel {
   DEBUG = "DEBUG",
   INFO = "INFO",
@@ -97,7 +99,30 @@ export const parseLogs = (
         line.includes(fileSourceFilter)
       )
     ) {
-      parsedLines.push(parsedLine);
+      // sanitize the lines to remove any tags that may cause HTML injection
+      const sanitizedLine = sanitizeHtml(parsedLine, {
+        allowedTags: ["a"],
+        allowedAttributes: {
+          a: ["href", "target", "style"],
+        },
+        transformTags: {
+          a: (tagName, attribs) => {
+            attribs.style = "color: blue; text-decoration: underline;";
+            return {
+              tagName: "a",
+              attribs,
+            };
+          },
+        },
+      });
+
+      // for lines with links, transform to hyperlinks
+      const lineWithHyperlinks = sanitizedLine.replace(
+        /((https?:\/\/|http:\/\/)[^\s]+)/g,
+        '<a href="$1" target="_blank" style="color: blue; text-decoration: 
underline;">$1</a>'
+      );
+
+      parsedLines.push(lineWithHyperlinks);
     }
   });
 
diff --git a/airflow/www/yarn.lock b/airflow/www/yarn.lock
index c0cf36d6cc..f659671261 100644
--- a/airflow/www/yarn.lock
+++ b/airflow/www/yarn.lock
@@ -3473,6 +3473,13 @@
     "@types/scheduler" "*"
     csstype "^3.0.2"
 
+"@types/sanitize-html@^2.9.5":
+  version "2.9.5"
+  resolved 
"https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.9.5.tgz#e8b2214c8afc7bb88d62f9c3bbbc5b4ecc80a25d";
+  integrity 
sha512-2Sr1vd8Dw+ypsg/oDDfZ57OMSG2Befs+l2CMyCC5bVSK3CpE7lTB2aNlbbWzazgVA+Qqfuholwom6x/mWd1qmw==
+  dependencies:
+    htmlparser2 "^8.0.0"
+
 "@types/scheduler@*":
   version "0.16.2"
   resolved 
"https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39";
@@ -5632,6 +5639,15 @@ dom-serializer@^1.0.1:
     domhandler "^4.2.0"
     entities "^2.0.0"
 
+dom-serializer@^2.0.0:
+  version "2.0.0"
+  resolved 
"https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53";
+  integrity 
sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.2"
+    entities "^4.2.0"
+
 domelementtype@1:
   version "1.3.1"
   resolved 
"https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f";
@@ -5642,6 +5658,11 @@ domelementtype@^2.0.1, domelementtype@^2.2.0:
   resolved 
"https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57";
   integrity 
sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
 
+domelementtype@^2.3.0:
+  version "2.3.0"
+  resolved 
"https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d";
+  integrity 
sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
 domexception@^2.0.1:
   version "2.0.1"
   resolved 
"https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304";
@@ -5670,6 +5691,13 @@ domhandler@^4.3.1:
   dependencies:
     domelementtype "^2.2.0"
 
+domhandler@^5.0.2, domhandler@^5.0.3:
+  version "5.0.3"
+  resolved 
"https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31";
+  integrity 
sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+  dependencies:
+    domelementtype "^2.3.0"
+
 dompurify@^2.2.8:
   version "2.2.9"
   resolved 
"https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.9.tgz#4b42e244238032d9286a0d2c87b51313581d9624";
@@ -5701,6 +5729,15 @@ domutils@^2.8.0:
     domelementtype "^2.2.0"
     domhandler "^4.2.0"
 
+domutils@^3.0.1:
+  version "3.1.0"
+  resolved 
"https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e";
+  integrity 
sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
+  dependencies:
+    dom-serializer "^2.0.0"
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+
 echarts@^5.4.2:
   version "5.4.2"
   resolved 
"https://registry.yarnpkg.com/echarts/-/echarts-5.4.2.tgz#9f38781c9c6ae323e896956178f6956952c77a48";
@@ -5757,6 +5794,11 @@ entities@^2.0.0:
   resolved 
"https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55";
   integrity 
sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
 
+entities@^4.2.0, entities@^4.4.0:
+  version "4.5.0"
+  resolved 
"https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48";
+  integrity 
sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
 envinfo@^7.7.3:
   version "7.8.1"
   resolved 
"https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475";
@@ -6893,6 +6935,16 @@ htmlparser2@^6.0.1:
     domutils "^2.5.2"
     entities "^2.0.0"
 
+htmlparser2@^8.0.0:
+  version "8.0.2"
+  resolved 
"https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21";
+  integrity 
sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
+    entities "^4.4.0"
+
 http-proxy-agent@^4.0.1:
   version "4.0.1"
   resolved 
"https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a";
@@ -8899,6 +8951,11 @@ nanoid@^3.3.6:
   resolved 
"https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c";
   integrity 
sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
 
+nanoid@^3.3.7:
+  version "3.3.7"
+  resolved 
"https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8";
+  integrity 
sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+
 natural-compare@^1.4.0:
   version "1.4.0"
   resolved 
"https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7";
@@ -9290,6 +9347,11 @@ parse-json@^5.0.0, parse-json@^5.2.0:
     json-parse-even-better-errors "^2.3.0"
     lines-and-columns "^1.1.6"
 
+parse-srcset@^1.0.2:
+  version "1.0.2"
+  resolved 
"https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1";
+  integrity 
sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==
+
 [email protected]:
   version "6.0.1"
   resolved 
"https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b";
@@ -9670,6 +9732,15 @@ postcss@^8.2.15, postcss@^8.4.13, postcss@^8.4.24:
     picocolors "^1.0.0"
     source-map-js "^1.0.2"
 
+postcss@^8.3.11:
+  version "8.4.33"
+  resolved 
"https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742";
+  integrity 
sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==
+  dependencies:
+    nanoid "^3.3.7"
+    picocolors "^1.0.0"
+    source-map-js "^1.0.2"
+
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved 
"https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396";
@@ -10369,6 +10440,18 @@ safe-regex-test@^1.0.0:
   resolved 
"https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a";
   integrity 
sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
+sanitize-html@^2.11.0:
+  version "2.11.0"
+  resolved 
"https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.11.0.tgz#9a6434ee8fcaeddc740d8ae7cd5dd71d3981f8f6";
+  integrity 
sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==
+  dependencies:
+    deepmerge "^4.2.2"
+    escape-string-regexp "^4.0.0"
+    htmlparser2 "^8.0.0"
+    is-plain-object "^5.0.0"
+    parse-srcset "^1.0.2"
+    postcss "^8.3.11"
+
 sax@^1.2.4:
   version "1.2.4"
   resolved 
"https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9";

Reply via email to