diff --git a/airflow/www/views.py b/airflow/www/views.py
index d097e54b85c05..9f34b9c440085 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -131,7 +131,8 @@ def dag_run_link(v, c, m, p):
dag_id=m.dag_id,
run_id=m.run_id,
execution_date=m.execution_date)
- return Markup('{m.run_id}'.format(**locals()))
+ title = escape(m.run_id)
+ return Markup('{title}'.format(**locals()))
def task_instance_link(v, c, m, p):
@@ -202,12 +203,14 @@ def label_link(v, c, m, p):
url = url_for(
'airflow.chart', chart_id=m.id, iteration_no=m.iteration_no,
**default_params)
- return Markup("{m.label}".format(**locals()))
+ title = escape(m.label)
+ return Markup("{title}".format(**locals()))
def pool_link(v, c, m, p):
+ title = escape(m.pool)
url = '/admin/taskinstance/?flt1_pool_equals=' + m.pool
- return Markup("{m.pool}".format(**locals()))
+ return Markup("{title}".format(**locals()))
def pygment_html_render(s, lexer=lexers.TextLexer):
diff --git a/airflow/www_rbac/views.py b/airflow/www_rbac/views.py
index c916941112df2..767ef4aef037c 100644
--- a/airflow/www_rbac/views.py
+++ b/airflow/www_rbac/views.py
@@ -36,7 +36,7 @@
import sqlalchemy as sqla
from flask import (
redirect, request, Markup, Response, render_template,
- make_response, flash, jsonify)
+ make_response, flash, jsonify, escape)
from flask._compat import PY2
from flask_appbuilder import BaseView, ModelView, expose, has_access
from flask_appbuilder.actions import action
@@ -1974,6 +1974,7 @@ def pool_link(attr):
pool_id = attr.get('pool')
if pool_id is not None:
url = '/taskinstance/list/?_flt_3_pool=' + str(pool_id)
+ pool_id = escape(pool_id)
return Markup("{pool_id}".format(**locals()))
else:
return Markup('Invalid')
diff --git a/tests/www_rbac/test_views.py b/tests/www_rbac/test_views.py
index 93f6bfd8f7142..3e583507b9ba5 100644
--- a/tests/www_rbac/test_views.py
+++ b/tests/www_rbac/test_views.py
@@ -244,6 +244,13 @@ def test_create_pool_with_empty_name(self):
follow_redirects=True)
self.check_content_in_response('This field is required.', resp)
+ def test_odd_name(self):
+ self.pool['pool'] = 'test-pool'
+ self.session.add(models.Pool(**self.pool))
+ self.session.commit()
+ resp = self.client.get('/pool/list/')
+ self.check_content_in_response('test-pool<script>', resp)
+
class TestMountPoint(unittest.TestCase):
def setUp(self):