Program: CWE-79
Project: CVE-2022-31113
Buggy source:
{% macro whatsthis(help_url) -%}
<a href="{{help_url}}" target="_blank" class="what-is-this">
  <svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-info-circle fa-w-16"><path fill="currentColor" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z" class=""></path></svg>
</a>
{%- endmacro %}


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="/resources/favicon.ico">
    <link rel="stylesheet" type="text/css" href="/resources/famfamfam-flags.css" >

    <title>Canarytokens</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

    <!-- Custom styles for this template -->
    <link href="https://v4-alpha.getbootstrap.com/examples/narrow-jumbotron/narrow-jumbotron.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/css/tooltipster.bundle.min.css" integrity="sha256-Qc4lCfqZWYaHF5hgEOFrYzSIX9Rrxk0NPHRac+08QeQ=" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-borderless.min.css" integrity="sha256-ZiBTbkzExWV/DU4+02ZMqXaNu7o0XfNmxTa0+gRbdO0=" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/resources/styles.css?ver=3">
  </head>
  <script type="text/javascript">
   // var t_locations = ['-33.918861,18.423300','-26.196246,28.034088','37.615223,-122.389977','55.751244,37.6184.23'];
   // var t_count = 0;
   var geo_info = {};
    function appendGeoInfo(id,info){
      geo_info[id] = info;
    }
    // function appendGeoInfoTest(id){
    //   geo_info[id] = {'loc':t_locations[t_count]};
    //   t_count++;
    // }
</script>
  <body>
    <div class="container-fluid">
      <div class="header clearfix">
        <nav>
          <ul class="nav nav-pills float-right">
            <li class="nav-item">
              <a class="nav-link" href="/generate">New token</a>
            </li>
            <li class="nav-item">
              <a class="nav-link manage-link" href="/manage?token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}">Manage this token</a>
            </li>
          </ul>
        </nav>
        <h3 class="text-muted">
          <a style="color: inherit; text-decoration: inherit;" href="/">
            <img alt="logo" src="/resources/logo.png" class="logo">
          </a>
        </h3>
      </div>
      <div class="history-header">
        <h3>History for Canarytoken: <p class="token-length">{{canarydrop['canarytoken']}}</p></h3>
      </div>
      <div class="alert alert-info alert-dismissible" role="alert" style="text-align: center;">
          <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <strong>Heads Up!</strong> Click the incident items for more info.
        </div>
      <div class="row content">
          <div class="col-sm-6 incident-size">
          <div class="row" style="align-items: center;">
            <div class="col-md 12">
              <h4 style="text-align: center;">Incident Map</h4>
            </div>
          </div>
{% if API_KEY %}
          <div class="row">
              <div class="col-md-12"><div class="map" id="map"></div></div>
          </div>
{% else %}
           <div class="row">
              <div class="col-md-12"><p id="map-no-key">The Incident Map could not be displayed because a valid Google Maps API key could not be found. This can be added to the <code>frontend.env</code> file.</p></div>
          </div>
{%endif%}
        </div>
        <div class="col-sm-6 incident-size">
{% if (canarydrop['triggered_list']|length) > 0 %}

        <div class="row" style="align-items: center;">
          <h4 style="text-align: center;" class="col-md-9">Incident List</h4>
          <div id="file_format" class="wrapper-dropdown form-control col-md-2" style="text-align: center;margin-bottom: 0;padding: 5px;" tabindex="1">
            <span id="selected_file_format">
              Export
            </span>
            <input name="file_format" type="hidden">
            <ul id="file_format_dropdown" class="dropdown">
              <li data-type="JSON"           data-memo-placeholder="Download incident list as a (.json)"><a onClick="jsonDownload()"><span class="title">JSON File Format</span><div class="explanation">Download incident list as (.json)</div></a></li>
              <li data-type="CSV"            data-memo-placeholder="Download incident list as a (.csv)"><a onClick="csvDownload()"><span class="title">CSV File Format</span><div class="explanation">Download incident list as (.csv)</div></a></li>
            </ul>
          </div>
        </div>

        <!-- <h6 class="text-info" style="text-align: center;">Click to expand Incidents</h6> -->
{% else %}
        <h4 style="text-align: center;">Incident List is Currently Empty</h4>
{% endif %}
        <div class="row incident-list">
          <div class="col-md-12" id="incidents">
{% for item in canarydrop['triggered_list']|sort(reverse=True) %}
          <div class="incident-item expand" id="item-{{item}}">
                <p class="details-header">
                <b>Date:</b> {{ item|e }}
                <b>IP:</b> {{ canarydrop['triggered_list'][item]['src_ip'] }}
  {% if canarydrop['type'] == 'aws_keys' %}
                                  <b>Channel:</b> AWS API Key Token
  {% else %}
                                  <b>Channel:</b> {{ canarydrop['triggered_list'][item]['input_channel'] }}
  {% endif %}
                </p>
                <div class="incident-item-details">
                <!-- <script type="text/javascript">
                  appendGeoInfoTest("{{item}}");
                </script> -->
  {% if canarydrop['triggered_list'][item]['geo_info'] and not canarydrop['triggered_list'][item]['geo_info']['bogon'] == true%}
              <table class="table table-striped">
                <col width="25%">
                <col width="75%">
                <tr class="header_row">
                   <td colspan="2">
                     Geo Info
                   </td>
                </tr>
    {% if canarydrop['triggered_list'][item]['geo_info']['country'] %}
                <tr class="info_row">
                  <td>Country</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['country'] }}
                      <i class="famfamfam-flag-{{(canarydrop['triggered_list'][item]['geo_info']['country'])|lower}}"></i>
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['city'] %}
                <tr class="info_row">
                  <td>City</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['city'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['region'] %}
                <tr class="info_row">
                  <td>Region</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['region'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['org'] %}
                <tr class="info_row">
                  <td>Organisation</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['org'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['hostname'] %}
                <tr class="info_row">
                  <td>Hostname</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['hostname'] }}
                  </td>
                </tr>
    {% endif %}
                <script type="text/javascript">
                  appendGeoInfo("{{item}}",{{canarydrop['triggered_list'][item]['geo_info']|tojson}});
                </script>
              </table>
  {%endif%}
  {% if canarydrop['triggered_list'][item]['is_tor_relay'] != None %}
              <table class="table table-bordered table-hover">
                <col width="25%">
                <col width="75%">
                <tr class="header_row">
                   <td colspan="2">
                     <img src="https://upload.wikimedia.org/wikipedia/commons/1/15/Tor-logo-2011-flat.svg" style="width:30px;height:19px;">
                   </td>
                </tr>
                <tr class="info_row">
                  <td>
                    Known Exit Node
                  </td>
                  <td>
                    {{ canarydrop['triggered_list'][item]['is_tor_relay']==True }}
                  </td>
                </tr>
              </table>
  {%endif%}

            <table class="table table-bordered table-hover">
              <col width="25%">
              <col width="75%">
              <tr class="header_row">
                <td colspan="2">
                  Basic Info
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Memo
                </td>
                <td>
                  {{ canarydrop['memo']|e }}
                </td>
              </tr>
  {% for field in canarydrop['triggered_list'][item] %}
    {% if canarydrop['triggered_list'][item][field] != None and
          canarydrop['triggered_list'][item][field] is defined and
          field not in ['geo_info','is_tor_relay','additional_info','secretkeeper_photo'] %}
      {% if field not in ['src_ip','input_channel'] %}
              <tr class="info_row">
        {% if canarydrop['type'] == 'aws_keys' %}
                <td>
                  AWS Access Key ID
                </td>
                <td>
                  {{ canarydrop['aws_access_key_id'] }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Token Type
                </td>
                <td>
                  AWS API Key
                </td>
              </tr>
          {% if 'useragent' in canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  User-agent
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['useragent']|e }}
                </td>
              </tr>
          {% endif %}
        {% elif canarydrop['type'] ==  'wireguard' and field == 'src_data' %}
              <tr class="info_row">
                <td>
                  Client Source Port
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['src_port'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Client Handshake ID
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['session_index'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Client Public Key
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['client_public_key'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Server Public Key
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['server_public_key'] |e }}
                </td>
              </tr>
        {% elif field == 'src_data' and field in canarydrop['triggered_list'][item] and 'generic_data' in canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  Generic Data
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['generic_data']|e }}
                </td>
              </tr>
        {% elif canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  {{field}}
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]|e }}
                </td>
              </tr>
        {% endif %}
      {%endif%}
    {%endif%}
  {% endfor %}
            </table>
  {% if canarydrop['triggered_list'][item]['additional_info'] %}
                  <table class="table table-bordered table-hover">
                                <b>Additional Info</b>
                    <col width="25%">
                    <col width="75%">
    {% for info in canarydrop['triggered_list'][item]['additional_info'] %}
                    <tr class="header_row">
                       <td colspan="2">
                         {{info}}
                       </td>
                    </tr>
      {%if info == 'iOS-App'%}
                      <script type="text/javascript">
                        appendGeoInfo("{{item}}",{{canarydrop['triggered_list'][item]['additional_info'][info]}})
                      </script>
      {% elif info == 'secretkeeper_photo'%}
                          <tr class="info_row">
                            <td>
                              Photo
                            </td>
                            <td>
                              <img src="data:image/png;base64,{{canarydrop.get_secretkeeper_photo_as_base64(item)}}"/>
                            </td>
                          </tr>
      {% elif info == 'AWS Key Log Data'%}
        {% if canarydrop['triggered_list'][item]['additional_info'][info].get('safety_net', None) %}
              <tr class="info_row">
                <td>
                  Evasion Attempt {{ whatsthis('https://help.canary.tools/hc/en-gb/articles/4415516925585-AWS-API-Key-Canarytoken-safety-net-triggered')}}
                </td>
                <td>
                  Yes 
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Key Last Used
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item]['additional_info']['AWS Key Log Data']['last_used'][0]|e }}
                </td>
              </tr>
          {% continue %}
        {% endif %}
      {% elif canarydrop['triggered_list'][item]['additional_info'][info].__class__.__name__ == 'str' %}
                        {% continue %}
      {% endif %}
      {% for info_item in canarydrop['triggered_list'][item]['additional_info'][info] %}
                        <tr class="info_row">
                          <td>
                            {{info_item}}
                          </td>
                          <td>
                            {{ canarydrop['triggered_list'][item]['additional_info'][info][info_item][0] == '1'
                                  if info_item in ['enabled','installed']
                                  else canarydrop['triggered_list'][item]['additional_info'][info][info_item]|join(', ') }}
                          </td>
                        </tr>
      {% endfor %}
    {% endfor %}
                  </table>
  {% endif %}
            </div>
          </div>
{%endfor%}
          </div>
        </div>
      </div>
      </div>
      <footer class="footer">
        <p>Brought to you by <a href="https://canary.tools/" target="_blank">Thinkst Canary</a>, our insanely easy-to-use honeypot solution that deploys in just four minutes. <strong>Know. When it matters.</strong></p>
        <p>&copy; Thinkst Canary 2015&ndash;{{now.year}}</p>
        <p id="mainsite" class="hidden">This <a href="https://canarytokens.org/">Canarytokens</a> installation is unaffiliated with Thinkst Canary.</p>
      </footer>

    </div> <!-- /container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="//v4-alpha.getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.6.0/clipboard.min.js"></script>
    <script src="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/js/tooltipster.bundle.min.js" integrity="sha256-q732ZLDh1y9/RwzPjKt/GODE3lqj+078N0wwMDYQiPg=" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    <script src="/resources/site.js"></script>
    <script>

    function jsonDownload() {
      window.location = "/download?fmt=incidentlist_json&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
    }
    function csvDownload() {
      window.location = "/download?fmt=incidentlist_csv&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
    }

    var green_icon = 'https://maps.google.com/mapfiles/ms/icons/green-dot.png';
    var red_icon = 'https://maps.google.com/mapfiles/ms/icons/red-dot.png'

        function calcSizes(map){
          var height = $(window).height();
          $('#map').height(height*0.85);
          $('#incidents').height(height*0.85);
          google.maps.event.trigger(map, 'resize');
        }

        function initMap() {
          if(Object.keys(geo_info).length === 0 && geo_info.constructor === Object){
            $('#incidents').parent().parent().show();
          }else{
            $('#map').parent().parent().parent().show();
            $('#incidents').parent().parent().show();

          var map = new google.maps.Map(document.getElementById('map'), {
              center: {lat: 0, lng: 0},
              zoom: 4,
              maxZoom: 7,
              minZoom: 2,
              mapTypeId: 'hybrid',
              mapTypeControl: false,
              streetViewControl: false
            });

          $(document).ready(calcSizes(map));
          $(document).resize(calcSizes(map));

          var bounds = new google.maps.LatLngBounds();
          var markers = {};
          for (x in geo_info){
            var loc = String(geo_info[x]['loc']).split(",");
            var latitude = parseFloat(loc[0]);
            var longitude = parseFloat(loc[1]);
            if (isNaN(latitude) || isNaN(longitude)) {
              continue;
            }
            var latlng = new google.maps.LatLng(latitude,longitude);

            if(markers[latlng]==undefined){
              markers[latlng]= '<br>'+x;
            }else{
              markers[latlng] += '<br>'+x;
            }

            var content = '';
            for(info in geo_info[x]){
              if(geo_info[x][info]==undefined || info == 'org' || info == 'postal' || info=='hostname' || info == 'asn'){
                continue;
              }
              if(info=='ip'){
                if(geo_info[x]['hostname']==undefined){
                  content = '<b>'+geo_info[x]['ip']+'</b>'+content;
                }
                else{
                  content = '<b>'+geo_info[x]['ip']+ '</b><br>'+geo_info[x]['hostname']+'<br>'+content;
                }
              }else if(info=='country'){
                content +='<br><i class="famfamfam-flag-'+(geo_info[x]['country']).toLowerCase()+'"></i> '+(geo_info[x]['country']);
              }else{
                content += '<br>'+geo_info[x][info];
              }
            }
            content = content +'<br>'+markers[latlng];

            var info = new google.maps.InfoWindow({
              content : content
            });

            var marker = new google.maps.Marker({
              map : map,
              draggable :false,
              animation:google.maps.Animation.DROP,
              position : latlng,
              icon : red_icon
            });
            bounds.extend(marker.position);
            var list_item = document.getElementById('item-'+x);
            var clickHandler = new ClickEventHandler(map, marker,info,list_item);
          }

          map.fitBounds(bounds);
          }
        }


        var ClickEventHandler = function(map, marker, info, item){
          this.map = map;
          this.marker = marker;
          this.item = item;
          this.info = info

          this.marker.addListener('click', function(){
            info.open(this.map, this);
          });

          $(this.item).click(function(){
              if(marker.getIcon() == green_icon){
                marker.setIcon(red_icon);
                marker.setAnimation(null);
              }else{
                marker.setIcon(green_icon);
                marker.setAnimation(google.maps.Animation.BOUNCE);
              }
            });
        };

      $('.expand').click(function(){
        $(this).find('.incident-item-details').slideToggle('slow');
    });

    function DropDown(el, click_cb) {
          this.dd = el;
          this.click_cb = click_cb;
          this.initEvents();
      }
      DropDown.prototype = {
          initEvents : function() {
              var obj = this;

              obj.dd.on('click', function(event){
                  $(this).toggleClass('active');
                  if ($(event.target).parents().hasClass('file_format_dropdown') && obj.click_cb) {
                    obj.click_cb(event);
                  }
                  event.stopPropagation();
              });
          }
      }
      $(function() {
        /* init dropdown menu */
		    var dd = new DropDown( $('#file_format'),
                                function(event) {
                                  var list_item = $(event.target).parents('li');
                                  $('#file_format_dropdown').data('selected', list_item.data('file_format'))
                                  $('#selected_file_format').text(list_item.find('span.title').text());
                                });
                                });

      $(document).click(function() {
          $('.wrapper-dropdown').removeClass('active');
      });

    </script>
{% if API_KEY %}
  <script src="https://maps.googleapis.com/maps/api/js?key={{API_KEY}}&callback=initMap" async defer></script>
{% else %}
  <script>
    $('#incidents').parent().parent().show();
    $('#map-no-key').parent().parent().parent().show();
  </script>
{%endif%}
  </body>
</html>


Fixed version (ground truth):
{% macro whatsthis(help_url) -%}
<a href="{{help_url}}" target="_blank" class="what-is-this">
  <svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-info-circle fa-w-16"><path fill="currentColor" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z" class=""></path></svg>
</a>
{%- endmacro %}


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="shortcut icon" href="/resources/favicon.ico">
    <link rel="stylesheet" type="text/css" href="/resources/famfamfam-flags.css" >

    <title>Canarytokens</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

    <!-- Custom styles for this template -->
    <link href="https://v4-alpha.getbootstrap.com/examples/narrow-jumbotron/narrow-jumbotron.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/css/tooltipster.bundle.min.css" integrity="sha256-Qc4lCfqZWYaHF5hgEOFrYzSIX9Rrxk0NPHRac+08QeQ=" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/css/plugins/tooltipster/sideTip/themes/tooltipster-sideTip-borderless.min.css" integrity="sha256-ZiBTbkzExWV/DU4+02ZMqXaNu7o0XfNmxTa0+gRbdO0=" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/resources/styles.css?ver=3">
  </head>
  <script type="text/javascript">
   // var t_locations = ['-33.918861,18.423300','-26.196246,28.034088','37.615223,-122.389977','55.751244,37.6184.23'];
   // var t_count = 0;
   var geo_info = {};
    function appendGeoInfo(id,info){
      geo_info[id] = info;
    }
    // function appendGeoInfoTest(id){
    //   geo_info[id] = {'loc':t_locations[t_count]};
    //   t_count++;
    // }
</script>
  <body>
    <div class="container-fluid">
      <div class="header clearfix">
        <nav>
          <ul class="nav nav-pills float-right">
            <li class="nav-item">
              <a class="nav-link" href="/generate">New token</a>
            </li>
            <li class="nav-item">
              <a class="nav-link manage-link" href="/manage?token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}">Manage this token</a>
            </li>
          </ul>
        </nav>
        <h3 class="text-muted">
          <a style="color: inherit; text-decoration: inherit;" href="/">
            <img alt="logo" src="/resources/logo.png" class="logo">
          </a>
        </h3>
      </div>
      <div class="history-header">
        <h3>History for Canarytoken: <p class="token-length">{{canarydrop['canarytoken']}}</p></h3>
      </div>
      <div class="alert alert-info alert-dismissible" role="alert" style="text-align: center;">
          <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <strong>Heads Up!</strong> Click the incident items for more info.
        </div>
      <div class="row content">
          <div class="col-sm-6 incident-size">
          <div class="row" style="align-items: center;">
            <div class="col-md 12">
              <h4 style="text-align: center;">Incident Map</h4>
            </div>
          </div>
{% if API_KEY %}
          <div class="row">
              <div class="col-md-12"><div class="map" id="map"></div></div>
          </div>
{% else %}
           <div class="row">
              <div class="col-md-12"><p id="map-no-key">The Incident Map could not be displayed because a valid Google Maps API key could not be found. This can be added to the <code>frontend.env</code> file.</p></div>
          </div>
{%endif%}
        </div>
        <div class="col-sm-6 incident-size">
{% if (canarydrop['triggered_list']|length) > 0 %}

        <div class="row" style="align-items: center;">
          <h4 style="text-align: center;" class="col-md-9">Incident List</h4>
          <div id="file_format" class="wrapper-dropdown form-control col-md-2" style="text-align: center;margin-bottom: 0;padding: 5px;" tabindex="1">
            <span id="selected_file_format">
              Export
            </span>
            <input name="file_format" type="hidden">
            <ul id="file_format_dropdown" class="dropdown">
              <li data-type="JSON"           data-memo-placeholder="Download incident list as a (.json)"><a onClick="jsonDownload()"><span class="title">JSON File Format</span><div class="explanation">Download incident list as (.json)</div></a></li>
              <li data-type="CSV"            data-memo-placeholder="Download incident list as a (.csv)"><a onClick="csvDownload()"><span class="title">CSV File Format</span><div class="explanation">Download incident list as (.csv)</div></a></li>
            </ul>
          </div>
        </div>

        <!-- <h6 class="text-info" style="text-align: center;">Click to expand Incidents</h6> -->
{% else %}
        <h4 style="text-align: center;">Incident List is Currently Empty</h4>
{% endif %}
        <div class="row incident-list">
          <div class="col-md-12" id="incidents">
{% for item in canarydrop['triggered_list']|sort(reverse=True) %}
          <div class="incident-item expand" id="item-{{item}}">
                <p class="details-header">
                <b>Date:</b> {{ item|e }}
                <b>IP:</b> {{ canarydrop['triggered_list'][item]['src_ip'] }}
  {% if canarydrop['type'] == 'aws_keys' %}
                                  <b>Channel:</b> AWS API Key Token
  {% else %}
                                  <b>Channel:</b> {{ canarydrop['triggered_list'][item]['input_channel'] }}
  {% endif %}
                </p>
                <div class="incident-item-details">
                <!-- <script type="text/javascript">
                  appendGeoInfoTest("{{item}}");
                </script> -->
  {% if canarydrop['triggered_list'][item]['geo_info'] and not canarydrop['triggered_list'][item]['geo_info']['bogon'] == true%}
              <table class="table table-striped">
                <col width="25%">
                <col width="75%">
                <tr class="header_row">
                   <td colspan="2">
                     Geo Info
                   </td>
                </tr>
    {% if canarydrop['triggered_list'][item]['geo_info']['country'] %}
                <tr class="info_row">
                  <td>Country</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['country'] }}
                      <i class="famfamfam-flag-{{(canarydrop['triggered_list'][item]['geo_info']['country'])|lower}}"></i>
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['city'] %}
                <tr class="info_row">
                  <td>City</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['city'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['region'] %}
                <tr class="info_row">
                  <td>Region</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['region'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['org'] %}
                <tr class="info_row">
                  <td>Organisation</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['org'] }}
                  </td>
                </tr>
    {% endif %}
    {% if canarydrop['triggered_list'][item]['geo_info']['hostname'] %}
                <tr class="info_row">
                  <td>Hostname</td>
                  <td>
                      {{ canarydrop['triggered_list'][item]['geo_info']['hostname'] }}
                  </td>
                </tr>
    {% endif %}
                <script type="text/javascript">
                  appendGeoInfo("{{item}}",{{canarydrop['triggered_list'][item]['geo_info']|tojson}});
                </script>
              </table>
  {%endif%}
  {% if canarydrop['triggered_list'][item]['is_tor_relay'] != None %}
              <table class="table table-bordered table-hover">
                <col width="25%">
                <col width="75%">
                <tr class="header_row">
                   <td colspan="2">
                     <img src="https://upload.wikimedia.org/wikipedia/commons/1/15/Tor-logo-2011-flat.svg" style="width:30px;height:19px;">
                   </td>
                </tr>
                <tr class="info_row">
                  <td>
                    Known Exit Node
                  </td>
                  <td>
                    {{ canarydrop['triggered_list'][item]['is_tor_relay']==True }}
                  </td>
                </tr>
              </table>
  {%endif%}

            <table class="table table-bordered table-hover">
              <col width="25%">
              <col width="75%">
              <tr class="header_row">
                <td colspan="2">
                  Basic Info
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Memo
                </td>
                <td>
                  {{ canarydrop['memo']|e }}
                </td>
              </tr>
  {% for field in canarydrop['triggered_list'][item] %}
    {% if canarydrop['triggered_list'][item][field] != None and
          canarydrop['triggered_list'][item][field] is defined and
          field not in ['geo_info','is_tor_relay','additional_info','secretkeeper_photo'] %}
      {% if field not in ['src_ip','input_channel'] %}
              <tr class="info_row">
        {% if canarydrop['type'] == 'aws_keys' %}
                <td>
                  AWS Access Key ID
                </td>
                <td>
                  {{ canarydrop['aws_access_key_id'] }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Token Type
                </td>
                <td>
                  AWS API Key
                </td>
              </tr>
          {% if 'useragent' in canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  User-agent
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['useragent']|e }}
                </td>
              </tr>
          {% endif %}
        {% elif canarydrop['type'] ==  'wireguard' and field == 'src_data' %}
              <tr class="info_row">
                <td>
                  Client Source Port
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['src_port'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Client Handshake ID
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['session_index'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Client Public Key
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['client_public_key'] |e }}
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Server Public Key
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['server_public_key'] |e }}
                </td>
              </tr>
        {% elif field == 'src_data' and field in canarydrop['triggered_list'][item] and 'generic_data' in canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  Generic Data
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]['generic_data']|e }}
                </td>
              </tr>
        {% elif canarydrop['triggered_list'][item][field] %}
              <tr class="info_row">
                <td>
                  {{field}}
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item][field]|e }}
                </td>
              </tr>
        {% endif %}
      {%endif%}
    {%endif%}
  {% endfor %}
            </table>
  {% if canarydrop['triggered_list'][item]['additional_info'] %}
                  <table class="table table-bordered table-hover">
                                <b>Additional Info</b>
                    <col width="25%">
                    <col width="75%">
    {% for info in canarydrop['triggered_list'][item]['additional_info'] %}
                    <tr class="header_row">
                       <td colspan="2">
                         {{info|e}}
                       </td>
                    </tr>
      {%if info == 'iOS-App'%}
                      <script type="text/javascript">
                        appendGeoInfo("{{item}}",{{canarydrop['triggered_list'][item]['additional_info'][info]}})
                      </script>
      {% elif info == 'secretkeeper_photo'%}
                          <tr class="info_row">
                            <td>
                              Photo
                            </td>
                            <td>
                              <img src="data:image/png;base64,{{canarydrop.get_secretkeeper_photo_as_base64(item)}}"/>
                            </td>
                          </tr>
      {% elif info == 'AWS Key Log Data'%}
        {% if canarydrop['triggered_list'][item]['additional_info'][info].get('safety_net', None) %}
              <tr class="info_row">
                <td>
                  Evasion Attempt {{ whatsthis('https://help.canary.tools/hc/en-gb/articles/4415516925585-AWS-API-Key-Canarytoken-safety-net-triggered')}}
                </td>
                <td>
                  Yes 
                </td>
              </tr>
              <tr class="info_row">
                <td>
                  Key Last Used
                </td>
                <td>
                  {{ canarydrop['triggered_list'][item]['additional_info']['AWS Key Log Data']['last_used'][0]|e }}
                </td>
              </tr>
          {% continue %}
        {% endif %}
      {% elif canarydrop['triggered_list'][item]['additional_info'][info].__class__.__name__ == 'str' %}
                        {% continue %}
      {% endif %}
      {% for info_item in canarydrop['triggered_list'][item]['additional_info'][info] %}
                        <tr class="info_row">
                          <td>
                            {{info_item}}
                          </td>
                          <td>
                            {{ canarydrop['triggered_list'][item]['additional_info'][info][info_item][0] == '1'
                                  if info_item in ['enabled','installed']
                                  else canarydrop['triggered_list'][item]['additional_info'][info][info_item]|join(', ')|e }}
                          </td>
                        </tr>
      {% endfor %}
    {% endfor %}
                  </table>
  {% endif %}
            </div>
          </div>
{%endfor%}
          </div>
        </div>
      </div>
      </div>
      <footer class="footer">
        <p>Brought to you by <a href="https://canary.tools/" target="_blank">Thinkst Canary</a>, our insanely easy-to-use honeypot solution that deploys in just four minutes. <strong>Know. When it matters.</strong></p>
        <p>&copy; Thinkst Canary 2015&ndash;{{now.year}}</p>
        <p id="mainsite" class="hidden">This <a href="https://canarytokens.org/">Canarytokens</a> installation is unaffiliated with Thinkst Canary.</p>
      </footer>

    </div> <!-- /container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="//v4-alpha.getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.6.0/clipboard.min.js"></script>
    <script src="https://cdn.jsdelivr.net/jquery.tooltipster/4.1.8/js/tooltipster.bundle.min.js" integrity="sha256-q732ZLDh1y9/RwzPjKt/GODE3lqj+078N0wwMDYQiPg=" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    <script src="/resources/site.js"></script>
    <script>

    function jsonDownload() {
      window.location = "/download?fmt=incidentlist_json&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
    }
    function csvDownload() {
      window.location = "/download?fmt=incidentlist_csv&token={{canarydrop['canarytoken']}}&auth={{canarydrop['auth']}}";
    }

    var green_icon = 'https://maps.google.com/mapfiles/ms/icons/green-dot.png';
    var red_icon = 'https://maps.google.com/mapfiles/ms/icons/red-dot.png'

        function calcSizes(map){
          var height = $(window).height();
          $('#map').height(height*0.85);
          $('#incidents').height(height*0.85);
          google.maps.event.trigger(map, 'resize');
        }

        function initMap() {
          if(Object.keys(geo_info).length === 0 && geo_info.constructor === Object){
            $('#incidents').parent().parent().show();
          }else{
            $('#map').parent().parent().parent().show();
            $('#incidents').parent().parent().show();

          var map = new google.maps.Map(document.getElementById('map'), {
              center: {lat: 0, lng: 0},
              zoom: 4,
              maxZoom: 7,
              minZoom: 2,
              mapTypeId: 'hybrid',
              mapTypeControl: false,
              streetViewControl: false
            });

          $(document).ready(calcSizes(map));
          $(document).resize(calcSizes(map));

          var bounds = new google.maps.LatLngBounds();
          var markers = {};
          for (x in geo_info){
            var loc = String(geo_info[x]['loc']).split(",");
            var latitude = parseFloat(loc[0]);
            var longitude = parseFloat(loc[1]);
            if (isNaN(latitude) || isNaN(longitude)) {
              continue;
            }
            var latlng = new google.maps.LatLng(latitude,longitude);

            if(markers[latlng]==undefined){
              markers[latlng]= '<br>'+x;
            }else{
              markers[latlng] += '<br>'+x;
            }

            var content = '';
            for(info in geo_info[x]){
              if(geo_info[x][info]==undefined || info == 'org' || info == 'postal' || info=='hostname' || info == 'asn'){
                continue;
              }
              if(info=='ip'){
                if(geo_info[x]['hostname']==undefined){
                  content = '<b>'+geo_info[x]['ip']+'</b>'+content;
                }
                else{
                  content = '<b>'+geo_info[x]['ip']+ '</b><br>'+geo_info[x]['hostname']+'<br>'+content;
                }
              }else if(info=='country'){
                content +='<br><i class="famfamfam-flag-'+(geo_info[x]['country']).toLowerCase()+'"></i> '+(geo_info[x]['country']);
              }else{
                content += '<br>'+geo_info[x][info];
              }
            }
            content = content +'<br>'+markers[latlng];

            var info = new google.maps.InfoWindow({
              content : content
            });

            var marker = new google.maps.Marker({
              map : map,
              draggable :false,
              animation:google.maps.Animation.DROP,
              position : latlng,
              icon : red_icon
            });
            bounds.extend(marker.position);
            var list_item = document.getElementById('item-'+x);
            var clickHandler = new ClickEventHandler(map, marker,info,list_item);
          }

          map.fitBounds(bounds);
          }
        }


        var ClickEventHandler = function(map, marker, info, item){
          this.map = map;
          this.marker = marker;
          this.item = item;
          this.info = info

          this.marker.addListener('click', function(){
            info.open(this.map, this);
          });

          $(this.item).click(function(){
              if(marker.getIcon() == green_icon){
                marker.setIcon(red_icon);
                marker.setAnimation(null);
              }else{
                marker.setIcon(green_icon);
                marker.setAnimation(google.maps.Animation.BOUNCE);
              }
            });
        };

      $('.expand').click(function(){
        $(this).find('.incident-item-details').slideToggle('slow');
    });

    function DropDown(el, click_cb) {
          this.dd = el;
          this.click_cb = click_cb;
          this.initEvents();
      }
      DropDown.prototype = {
          initEvents : function() {
              var obj = this;

              obj.dd.on('click', function(event){
                  $(this).toggleClass('active');
                  if ($(event.target).parents().hasClass('file_format_dropdown') && obj.click_cb) {
                    obj.click_cb(event);
                  }
                  event.stopPropagation();
              });
          }
      }
      $(function() {
        /* init dropdown menu */
		    var dd = new DropDown( $('#file_format'),
                                function(event) {
                                  var list_item = $(event.target).parents('li');
                                  $('#file_format_dropdown').data('selected', list_item.data('file_format'))
                                  $('#selected_file_format').text(list_item.find('span.title').text());
                                });
                                });

      $(document).click(function() {
          $('.wrapper-dropdown').removeClass('active');
      });

    </script>
{% if API_KEY %}
  <script src="https://maps.googleapis.com/maps/api/js?key={{API_KEY}}&callback=initMap" async defer></script>
{% else %}
  <script>
    $('#incidents').parent().parent().show();
    $('#map-no-key').parent().parent().parent().show();
  </script>
{%endif%}
  </body>
</html>