Skip to content

Commit

Permalink
feat: add optional flask-talisman and use csp nonce on scripts (#2075)
Browse files Browse the repository at this point in the history
* feat: add optional flask-talisman and use csp nonce on scripts

* remove void(0) and add missing nonce

* remove EOL and add quotes
  • Loading branch information
dpgaspar authored Jul 10, 2023
1 parent 7f194cf commit 6640cce
Show file tree
Hide file tree
Showing 21 changed files with 284 additions and 227 deletions.
20 changes: 20 additions & 0 deletions docs/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -938,3 +938,23 @@ Some images:

.. image:: ./images/security.png
:width: 100%

Optional dependency Flask-Talisman
==================================

All javascript code and inline scripts can have a nonce attribute provided by Flask-Talisman.
This package will not initialize Flask-Talisman for you, but will use `csp_nonce()` on Jinja2 if it exists.
To initialize Flask-Talisman, you can do the following:

.. code-block:: python
from flask import Flask
from flask_appbuilder import AppBuilder
from flask_talisman import Talisman
app = Flask(__name__)
app.config.from_object('config')
db = SQLA(app)
appbuilder = AppBuilder(app, db.session)
Talisman(app)
10 changes: 8 additions & 2 deletions flask_appbuilder/templates/appbuilder/baselib.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
{% if item1 | is_menu_visible %}
{% if item1.childs %}
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
{% if item1.icon %}
<i class="fa {{item1.icon}}"></i>&nbsp;
{% endif %}
Expand Down Expand Up @@ -58,7 +58,7 @@
{% set locale = 'en' %}
{% endif %}
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<div class="f16"><i class="flag {{languages[locale].get('flag')}}"></i><b class="caret"></b>
</div>
</a>
Expand Down Expand Up @@ -126,3 +126,9 @@
</div>
</div>
{% endmacro %}

{% macro get_nonce() -%}
{%- if csp_nonce is defined -%}
{{- csp_nonce() -}}
{%- endif %}
{%- endmacro %}
61 changes: 43 additions & 18 deletions flask_appbuilder/templates/appbuilder/general/lib.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% import 'appbuilder/baselib.html' as baselib %}

{% macro render_additional_links(additional_links, pk) %}
{% if additional_links %}
{% for item in additional_links %}
Expand All @@ -20,16 +22,27 @@
{% endif %}
<input type="hidden" id="action" name="action" />
</form>

<a href="javascript:void(0)" class="btn btn-sm btn-primary"
{% if action.confirmation %}
onclick="var a = new AdminActions(); return a.execute_single('{{path}}','{{action.confirmation}}');">
{% else %}
onclick="var a = new AdminActions(); return a.execute_single('{{path}}',false);">
{% endif %}
<a
id="btn-action-{{ endpoint }}"
href="#"
class="btn btn-sm btn-primary"
>
<i class="fa {{action.icon}}"></i>
{{_(action.text)}}
</a>
{{_(action.text)}}
</a>

<script nonce="{{ baselib.get_nonce() }}">
document.getElementById("btn-action-{{ endpoint }}")
.addEventListener("click", function () {
{% if action.confirmation %}
const adminAction = new AdminActions();
return adminAction.execute_single('{{path}}','{{action.confirmation}}');
{% else %}
const adminAction = new AdminActions();
return adminAction.execute_single('{{path}}',false);
{% endif %}
})
</script>
{% endif %}
{% endfor %}
{% endmacro %}
Expand Down Expand Up @@ -66,15 +79,15 @@
{% for action_key in actions %}
{% set action = actions.get(action_key) %}
<li>
<a href="javascript:void(0)"
<a href="#"
class="{{action.name}}_menu_item">
<i class="fa {{action.icon}}"></i>
{{ _(action.text) }}
</a>
</li>
{% endfor %}
</ul>
<script type="text/javascript">
<script nonce="{{ baselib.get_nonce() }}">
$(document).ready(function() {
{% for action_key in actions %}
{% set action = actions.get(action_key) %}
Expand Down Expand Up @@ -176,7 +189,7 @@
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&laquo;</a>
<a href="#">&laquo;</a>
</li>
{% endif %}
{% if page > 0 %}
Expand All @@ -185,14 +198,14 @@
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&lt;</a>
<a href="#">&lt;</a>
</li>
{% endif %}

{% for p in range(min, max) %}
{% if page == p %}
<li class="active">
<a href="javascript:void(0)">{{ (p + 1) }}</a>
<a href="#">{{ (p + 1) }}</a>
</li>
{% else %}
<li>
Expand All @@ -207,7 +220,7 @@
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&gt;</a>
<a href="#">&gt;</a>
</li>
{% endif %}
{% if max < pages %}
Expand All @@ -216,7 +229,7 @@
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0)">&raquo;</a>
<a href="#">&raquo;</a>
</li>
{% endif %}
</ul>
Expand Down Expand Up @@ -389,9 +402,21 @@ <h4 class="panel-title">
{% endmacro %}

{% macro lnk_delete(my_href) %}
<a href="javascript:void(0)" class="btn btn-sm btn-default confirm" rel="tooltip" title="{{_('Delete record')}}"
onclick="var a = new AdminActions(); return a.execute_single_delete('{{my_href}}','{{ _('You sure you want to delete this item?') }}');">
<a
id="btn-delete-{{ my_href }}"
href="#"
class="btn btn-sm btn-default confirm"
rel="tooltip"
title="{{_('Delete record')}}"
>
<span class="sr-only">{{ _('Delete') }}</span>
<i class="fa fa-trash"></i>
</a>
<script nonce="{{ baselib.get_nonce() }}">
document.getElementById("btn-delete-{{ my_href }}")
.addEventListener("click", function () {
const adminAction = new AdminActions();
return adminAction.execute_single_delete('{{my_href}}','{{_('Are you sure you want to delete this item?')}}');
})
</script>
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
{% endblock %}

{% block add_tail_js %}
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}"></script>
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}" nonce="{{ baselib.get_nonce() }}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
{% endblock %}

{% block add_tail_js %}
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}"></script>
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}" nonce="{{ baselib.get_nonce() }}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{% import 'appbuilder/baselib.html' as baselib %}

<form class="form-search" action="" method="post">
<div class="table-responsive">
<table class="table table-condensed"><tr>
Expand All @@ -11,7 +13,6 @@
</table>
</div>
</form>
<script>
<script nonce="{{ baselib.get_nonce() }}">
$(".my_select2").prepend("<option value=''></option>");
</script>

Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@
{% endblock content %}

{% block add_tail_js %}
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}"></script>
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}" nonce="{{ baselib.get_nonce() }}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
{% endblock %}

{% block add_tail_js %}
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}"></script>
<script src="{{url_for('appbuilder.static',filename='js/ab_keep_tab.js')}}" nonce="{{ baselib.get_nonce() }}"></script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@

{% block content %}

<script type="text/javascript">
var baseLoginUrl = "{{appbuilder.get_url_for_login}}";
var baseRegisterUrl = "{{appbuilder.get_url_for_login}}";
var next = "?next=" + "{{request.args.get('next', '') | urlencode}}";

function signin(provider) {
window.location.href = baseLoginUrl + provider + next;
}
</script>

<div class="container">
<div id="loginbox" style="margin-top:50px;" class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-primary">
Expand All @@ -23,7 +13,7 @@
<div>
{% for provider in providers %}
<a
onclick="signin('{{ provider.name }}');"
id="btn-signin-{{provider.name}}"
class="btn btn-primary btn-block"
type="submit"
>
Expand All @@ -37,4 +27,19 @@
</div>
</div>

{% endblock %}
<script nonce="{{ baselib.get_nonce() }}">
var baseLoginUrl = "{{appbuilder.get_url_for_login}}";
var baseRegisterUrl = "{{appbuilder.get_url_for_login}}";
var next = "?next=" + "{{request.args.get('next', '') | urlencode}}";

function signin(provider) {
window.location.href = baseLoginUrl + provider + next;
}

{% for provider in providers %}
document.getElementById("btn-signin-{{provider.name}}")
.addEventListener("click", function () { signin("{{provider.name}}") })
{% endfor %}

</script>
{% endblock %}
Loading

0 comments on commit 6640cce

Please sign in to comment.