Why does this error occur when it shouldn't? - javascript

I've been writing a script that will check for reflective XSS vulnerabilities. I'm having an error on a part that checks if you have "http://" or "https://" in your URL and '*' in the place of queries. However, when I put https://google.com/#q=*", it results inERROR! MISSING 'http://', OR 'https://'!`. Here's my code:
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to or contact me at keeganjkuhn#gmail.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: https://www.google.com/#q=*</h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<script>
function myFunction() {
var x = document.getElementById("myText").value;
// Error check
if ( !x.includes("*") && ( !x.includes("http://") || !x.includes("https://") ) ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'*\' IN PLACE OF QUERY, \'http://\', AND \'https://\'!";
x = false;
return 0;
}
if ( !x.includes("*") ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'*\' IN PLACE OF QUERY!";
x = false;
return 0;
}
if ( !x.includes("http://") || !x.includes("https://") ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'http://\', OR \'https://\'!";
x = false;
return 0;
}
document.getElementById("demo").innerHTML = x;
}
</script>
</body>
</html>
What am I doing wrong?

You check if http is not in OR https is not in. One of both will always be true.
Perform the checks one after another... for example

I've refactored your function to show how you can reduce the complexity of the code when you separate the validation logic from the rendering of the errors.
function myFunction() {
var errors = [];
var x = document.getElementById("myText").value;
if (!x.includes("http://") && !x.includes("https://")) {
errors.push('missing HTTP or HTTPS');
}
if (!x.includes("*")) {
errors.push('missing * in place of query')
}
// render the errors
if (errors.length) {
x = 'Error: ' + errors.join(', ') + '!';
}
document.getElementById("demo").innerHTML = x;
}
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to or contact me at keeganjkuhn#gmail.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: https://www.google.com/#q=*</h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<script>
function myFunction() {
var errors = [];
var x = document.getElementById("myText").value;
if (!x.includes("http://") && !x.includes("https://")) {
errors.push('missing HTTP or HTTPS');
}
if (!x.includes("*")) {
errors.push('missing * in place of query')
}
if (errors.length) {
x = 'Error: ' + errors.join(', ') + '!';
}
document.getElementById("demo").innerHTML = x;
}
</script>

You need to write the if condition correctly.
Change the condition from
if ( !x.includes("http://") || !x.includes("https://") ) {
to
if ( !(x.includes("http://") || x.includes("https://")) ) {
In this way, you raise the error only when the url doesn't contain either http:// or https://
Complete Code:
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to or contact me at keeganjkuhn#gmail.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: https://www.google.com/#q=*</h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<script>
function myFunction() {
var x = document.getElementById("myText").value;
// Error check
if ( !x.includes("*") && ( !x.includes("http://") || !x.includes("https://") ) ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'*\' IN PLACE OF QUERY, \'http://\', AND \'https://\'!";
x = false;
return 0;
}
if ( !x.includes("*") ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'*\' IN PLACE OF QUERY!";
x = false;
return 0;
}
if ( !(x.includes("http://") || x.includes("https://")) ) {
document.getElementById("demo").innerHTML = "ERROR! MISSING \'http://\', OR \'https://\'!";
x = false;
return 0;
}
document.getElementById("demo").innerHTML = x;
}
</script>
</body>
</html>

Related

Uncaught TypeError: google.script.run.doSomething is not a function

I am trying to check if the input name is already in a Google Sheet. However, I am getting this error:
Uncaught TypeError: google.script.run.doSomething is not a function.
Here is my Index.html file.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="UTF-8">
</head>
<body>
<input type="text" id="meetingTitle" value=""> // Getting value here
<button onclick="checkName()">Check if available</button> //Calling function is is causing the error.
<p id=nameVerification><i>Click the button above to check availability.</i></p>
<script>
function checkName() {
var toPass = document.getElementById("meetingTitle").value;
prompt("toPass " + toPass);
google.script.run.doSomething();
}
function checkNameCS(checkNameSSReturn) {
if (checkNameSSReturn == "") {
document.getElementById('nameVerification').innerHTML = "Already in Use: Please try with another name."
document.getElementById("meetingTitle").value = "";
} else {
document.getElementById("meetingTitle").value = checkNameSSReturn;
document.getElementById('nameVerification').innerHTML = "Meeting name available. Procced."
}
}
function doSomething () {
var nameGiven = document.getElementById("meetingTitle").value;
var nameExists = false;
var nameVerified = false;
var name = nameGiven.toLowerCase();
name = strip(name);
prompt("name " + name);
var spreadsheetId = ''; //Sheet id entered
var rangeName = 'Sheet1';
var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
if (!values) {} else {
for (var row = 0; row < values.length; row++) {
if (name == values[row][0]) {
nameExists = true;
}
}
}
if (nameExists) {
checkNameCS("");
prompt("name2 " + " ");
return;
}
nameVerified = true;
prompt("name2 " + name);
checkNameCS(name);
return;
}
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');
}
</script>
</body>
</html>
I tried debuging it with prompts but with no success. It seems like the function do something is properly called. But the code stops working aftergoogle.script.run.doSomething();.
I have looked at the documentation for successhandlers but they dont solve the issue either.
How about this modification?
Issue of your script:
doSomething() of google.script.run.doSomething() is required to be Google Apps Script.
In your script, doSomething() is put in HTML (index.html), and a method for using Google Apps Script is included. When google.script.run.doSomething() is run, doSomething() cannot be found at Google Apps Script (code.gs). By this, such error occurs. And if doSomething() is run at HTML side, also an error occurs at Sheets.Spreadsheets.Values.get(), because Sheets.Spreadsheets.Values.get() is the method of Advanced Google Services with Google Apps Script.
If you put it to Google Apps Script (code.gs), Javascript which is used at the script of doSomething() is required to be modified.
Modified script:
In this modification, your script was separated to Google Apps Script (code.gs) and HTML (index.html). var nameGiven = document.getElementById("meetingTitle").value; and checkNameCS(name); are used in index.html.
By the way, before you run this script, please enable Sheets API at Advanced Google Services.
Google Apps Script: code.gs
function strip(str) {
return str.replace(/^\s+|\s+$/g, '');
}
function doSomething (nameGiven) {
var nameExists = false;
var nameVerified = false;
var name = nameGiven.toLowerCase();
name = strip(name);
var spreadsheetId = '###'; //Sheet id entered
var rangeName = 'Sheet1';
var values = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeName).values;
if (values) {
for (var row = 0; row < values.length; row++) {
if (name == values[row][0]) {
nameExists = true;
}
}
}
if (nameExists) {
return "";
}
nameVerified = true;
return name;
}
HTML: index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta charset="UTF-8">
</head>
<body>
<input type="text" id="meetingTitle" value="">
<button onclick="checkName()">Check if available</button>
<p id=nameVerification><i>Click the button above to check availability.</i></p>
<script>
function checkName() {
var toPass = document.getElementById("meetingTitle").value;
prompt("toPass " + toPass);
var nameGiven = document.getElementById("meetingTitle").value; // Added
google.script.run.withSuccessHandler(checkNameCS).doSomething(nameGiven); // Modified
}
function checkNameCS(checkNameSSReturn) {
console.log(checkNameSSReturn)
if (checkNameSSReturn == "") {
document.getElementById('nameVerification').innerHTML = "Already in Use: Please try with another name."
document.getElementById("meetingTitle").value = "";
} else {
document.getElementById("meetingTitle").value = checkNameSSReturn;
document.getElementById('nameVerification').innerHTML = "Meeting name available. Procced."
}
}
</script>
</body>
</html>
Reference:
Class google.script.run

Why is this alert box not popping up when button clicked?

I've been writing a script to check for reflective XSS vulnerabilities. So far, it has an input for a URL with * in place of queries and an error checker for malformed URLs. It also has a file uploader for users to upload "payloads". However, I recently made a part that replaces * with the contents of the payload, and then for debugging purposes, I made it alert() the variable with the file contents. However, its not working. Here's my code:
function selectPayload(y) {
var fr = new FileReader();
fr.readAsText(document.getElementById('file').files[0]);
fr.onload = function() {
var dir = fr.result;
var payload = y.replace("*", fr.result);
alert(payload);
};
}
function myFunction() {
var errors = [];
var x = document.getElementById("myText").value;
if (!x.includes("http://") && !x.includes("https://")) {
errors.push('missing HTTP or HTTPS in URL');
}
if (!x.includes("*")) {
errors.push('missing * in place of query')
}
// Renders errors
if (errors.length) {
x = 'Error: ' + errors.join(', ') + '!';
}
document.getElementById("demo").innerHTML = x;
selectPayload(x);
}
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to
or contact me at email#example.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: <code>https://www.google.com/#q=*</code></h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<h4>Select a payload:</h4>
<h5>Default payloads in <code>payloads</code></h5>
<input type="file" id="file"> <button onclick="selectPayload()">Submit</button>
</body>
</html>
What am I doing wrong?
You have the second button calling the wrong function. Changed to call myFunction() instead of selectPayload(). Unless you intended to call selectPayload() with the second button, in which case you neet to pass it an argument like it expects.
function selectPayload(y) {
var fr = new FileReader();
fr.readAsText(document.getElementById('file').files[0]);
fr.onload = function() {
var dir = fr.result;
var payload = y.replace("*", fr.result);
alert(payload);
};
}
function myFunction() {
var errors = [];
var x = document.getElementById("myText").value;
if (!x.includes("http://") && !x.includes("https://")) {
errors.push('missing HTTP or HTTPS in URL');
}
if (!x.includes("*")) {
errors.push('missing * in place of query')
}
// Renders errors
if (errors.length) {
x = 'Error: ' + errors.join(', ') + '!';
}
document.getElementById("demo").innerHTML = x;
selectPayload(x);
}
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to
or contact me at keeganjkuhn#gmail.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: <code>https://www.google.com/#q=*</code></h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<h4>Select a payload:</h4>
<h5>Default payloads in <code>payloads</code></h5>
<input type="file" id="file"> <button onclick="myFunction()">Submit</button>
</body>
</html>
Here: I've found code that will work:
<!DOCTYPE html>
<html>
<head>
<title>Slingshot.XSS</title>
</head>
<body style="font-family:monospace;" align="center">
<script>
function selectPayload() {
var x = document.getElementById("myText").value;
var fr = new FileReader();
fr.readAsText(document.getElementById('file').files[0]);
fr.onload = function() {
var dir = fr.result;
var payload = x.replace("*", fr.result);
alert(payload);
};
}
function myFunction() {
var errors = [];
var x = document.getElementById("myText").value;
if (!x.includes("http://") && !x.includes("https://")) {
errors.push('missing HTTP or HTTPS in URL');
}
if (!x.includes("*")) {
errors.push('missing * in place of query')
}
// Renders errors
if (errors.length) {
x = 'Error: ' + errors.join(', ') + '!';
}
document.getElementById("demo").innerHTML = x;
}
</script>
<h2>Slingshot.XSS</h2>
<h3>Slingshot.XSS is a script that launches pre-loaded XSS payloads at a target to test its vulnerabilities.</h3>
<h4>Please report all issues to
or contact me at keeganjkuhn#gmail.com.</h4>
Source Code / Learn More
<br />
<h4>Enter a URL with <b>*</b> in the place of query.</h4>
<h5>Example: <code>https://www.google.com/#q=*</code></h5>
<input type="text" id="myText" placeholder="Enter a URL"> <button onclick="myFunction()">Submit</button>
<p id="demo">No Submitted URL</p>
<h4>Select a payload:</h4>
<h5>Default payloads in <code>payloads</code></h5>
<input type="file" id="file"> <button onclick="selectPayload()">Submit</button>
</body>
</html>

Palindrome incorrect results.

I'm trying to create a palindrome checker. And now it seems that my lengthChecker() is no longer being called, nor is the condition whenever a word isn't a palindrome, then say it's not a palindrome. What could be the issue?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Lesson #6 Homework</title>
<script type="text/javascript" src="./js/palindrome.js"></script>
</head>
<body>
<h1>Is it a Palindrome?</h1>
<div id="mainCont">
<p>Hello. Please enter a word, and I'll see if it is a palindrome.</p>
<p>Word:
<input type="text" id="str" name="string" />
<button id="checkInput">Submit</button>
</p>
</div>
</body>
</html>
Here is the JS as of now:
function lengthChecker() {
var str = document.getElementById("str").value;
if (str.length > 10 ) {
alert("Sorry. Your input surpasses the 10 characters maximum. Please try again.")
return false;
} else if (str.length == 0) {
alert ("Sorry. Your input is too short, and doesn't meet the 10 characters maximum. Please try again.")
return false;
}
palindrome();
}
function palindrome() {
var revStr = "";
var str = document.getElementById("str").value;
var i = str.length;
for (var j = i; j >= 0; j--) {
revStr = revStr + str.charAt(j);
}
if (str == revStr) {
isPalindrome();
} else {
alert(str + " -is not a Palindrome");
}
}
function isPalindrome() {
alert(str + " is a Palindrome.");
}
document.addEventListener("DOMContentLoaded" , function(e){
var el = document.getElementById("checkInput");
el.addEventListener("click", isPalindrome);
});
You have your Javascript linked in the head element, so it is executed before the <button id="checkInput"> gets into the DOM. Move it to the end of body or make it deferred.
Because you are tying to access your button, before your page is properly loaded.
You need to get your button and bind your event handler, when DOM is loaded.
document.addEventListener("DOMContentLoaded", function(e) {
var el = document.getElementById("checkInput");
el.addEventListener("click", isPalindrome);
});

this JavaScript log in wont work

i found and edited this code from this website for practice but the code wont work with me. the goal of the code is to create a username and password on one page (which for now is limited to premade usernames and passwords) and send that array of information to another page where you can log in using the username and password from the other page. the code looks fine to me but i am an amateur and want to know what is wrong with it. thank you for your answer.
the code for where the username and password are defined is:
<!DOCTYPE html>
<html>
<head>
<title>
create account
</title>
<script>
sessionStorage.setItem("unArray", JSON.stringify("bob", "sam"));
sessionStorage.setItem("pwArray", JSON.stringify("lol", "jk"));
</script>
</head>
<body>
</body>
</html>
the code for taking the already created username and password from the above page and using that for a log in page is this:
<!DOCTYPE html>
<html>
<head>
<title>
log on page
</title>
<script type = "text/javascript">
var count = 2;
function validate() {
var un = document.getElementById("username").value;
var pw = document.getElementById("pword").value
var valid = false;
var unArray = JSON.parse(sessionStorage.getItem("unArray"));
var pwArray = JSON.parse(vsessionStorage.getItem("pwArray"));
for (var i=0; i <unArray.length; i++) {
if ((un == unArray[i]) && (pw == pwArray[i])) {
valid = true;
break;
}
}
if (valid) {
alert ("Login was successful");
window.location = "http://www.google.com";
return false;
}
var t = " tries";
if (count == 1) {t = " try"}
if (count >= 1) {
alert ("Invalid username and/or password. " +
"You have " + count + t + " left.");
document.myform.username.value = "";
document.myform.pword.value = "";
setTimeout("document.myform.username.focus()", 25);
setTimeout("document.myform.username.select()", 25);
count --;
}
else {
alert ("Still incorrect! You have no more tries left!");
document.myform.username.value = "No more tries allowed!";
document.myform.pword.value = "";
document.myform.username.disabled = true;
document.myform.pword.disabled = true;
return false;
}
}
</script>
<style>
p.log_on{
position: fixed;
top: 30px;
left: 20px;
}
</style>
</head>
<body>
<form name = "myform">
<p class="log_on">
ENTER USER NAME <input type="text" id="username"><br><br><br><br><br>
ENTER PASSWORD <input type="password" id="pword">
<input type="button" value="Check In" id="Submit" onclick="validate()">
</p>
</form>
</body>
</html>
The following two lines:
sessionStorage.setItem("unArray", JSON.stringify("bob", "sam"));
sessionStorage.setItem("pwArray", JSON.stringify("lol", "jk"));
are not using the JSON.stringify function correctly.
They should be:
sessionStorage.setItem("unArray", JSON.stringify(["bob", "sam"]));
sessionStorage.setItem("pwArray", JSON.stringify(["lol", "jk"]));
See the following link for reference: Mozilla Developer Network.
Per the documentation, the JSON.stringify parameters are defined as the following:
Syntax
JSON.stringify(value[, replacer [, space]])
Parameters
value - The value to convert to a JSON string.
replacer (Optional) - If a function, transforms values and properties encountered while stringifying; if an array, specifies the set of properties included in objects in the final string.
A detailed description of the replacer function is provided in the JavaScript guide article Using native JSON.
space (Optional) - Causes the resulting string to be pretty-printed.

Javascript does not work upon AJAX call

I have a page which does an AJAX call and loads an entire page. The page that gets loaded has some Javascript. The javascript works on page by itself when loaded, but when its gets loaded by AJAX, the Javascript does not work. I dont know what I am missing.
The code of the loaded page
<html>
<script type="text/javascript">
function showfield(name){
if(name=='lstbox')document.getElementById('div1').style.display="block";
else document.getElementById('div1').style.display="none";
}
function hidefield() {
document.getElementById('div1').style.display='none';
}
</script>
<head>
</head>
<body onload="hidefield()">
<form action = "test2.php" method = "post">
Please enter a name for the App <input type = "text" name = "name">
<table border = "1"><tr><th>Choose a Label</th><th>Choose an element</th></tr>
<tr><td><input type = "text" name = "label1" /></td> <td>
<select name = "elementtype1" id="elementtype1" onchange="showfield(this.options[this.selectedIndex].value)">
<option value = 'select'> Select </option>
<option value='txtbox'>Text Box</option>
<option value='lstbox'>List Box</option>
<option value='chkbox'>Check Box</option>
<option value='radio'>Radio Button</option>
</select></td><td><div id="div1">Enter Listbox options: <input type="text" name="whatever1" /></div></td></tr>
</table>
<input type = "submit" value = "Submit">
</form>
</body>
</html>
The code of the loading(AJAX) page is
<html>
<head>
</head>
<body>
<script src="ajax.js" type="text/javascript"></script>
<script src="responseHTML.js" type="text/javascript"></script>
<div id="storage" style="display:none;">
</div>
<div id="displayed">
<FORM name="ajax" method="POST" action="">
<p>
<INPUT type="BUTTON" value="Get the Panel" ONCLICK="loadWholePage('appcreator.php')">
</p>
</FORM>
</div>
</body>
</html>
The ajax.js code
function createXHR()
{
var request = false;
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (err2) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (err3) {
try {
request = new XMLHttpRequest();
}
catch (err1)
{
request = false;
}
}
}
return request;
}
The responseHTML.js code
function getBody(content)
{
test = content.toLowerCase(); // to eliminate case sensitivity
var x = test.indexOf("<body");
if(x == -1) return "";
x = test.indexOf(">", x);
if(x == -1) return "";
var y = test.lastIndexOf("</body>");
if(y == -1) y = test.lastIndexOf("</html>");
if(y == -1) y = content.length; // If no HTML then just grab everything till end
return content.slice(x + 1, y);
}
/**
Loads a HTML page
Put the content of the body tag into the current page.
Arguments:
url of the other HTML page to load
id of the tag that has to hold the content
*/
function loadHTML(url, fun, storage, param)
{
var xhr = createXHR();
xhr.onreadystatechange=function()
{
if(xhr.readyState == 4)
{
//if(xhr.status == 200)
{
storage.innerHTML = getBody(xhr.responseText);
fun(storage, param);
}
}
};
xhr.open("GET", url , true);
xhr.send(null);
}
/**
Callback
Assign directly a tag
*/
function processHTML(temp, target)
{
target.innerHTML = temp.innerHTML;
}
function loadWholePage(url)
{
var y = document.getElementById("storage");
var x = document.getElementById("displayed");
loadHTML(url, processHTML, x, y);
}
/**
Create responseHTML
for acces by DOM's methods
*/
function processByDOM(responseHTML, target)
{
target.innerHTML = "Extracted by id:<br />";
// does not work with Chrome/Safari
//var message = responseHTML.getElementsByTagName("div").namedItem("two").innerHTML;
var message = responseHTML.getElementsByTagName("div").item(1).innerHTML;
target.innerHTML += message;
target.innerHTML += "<br />Extracted by name:<br />";
message = responseHTML.getElementsByTagName("form").item(0);
target.innerHTML += message.dyn.value;
}
function accessByDOM(url)
{
//var responseHTML = document.createElement("body"); // Bad for opera
var responseHTML = document.getElementById("storage");
var y = document.getElementById("displayed");
loadHTML(url, processByDOM, responseHTML, y);
}
Javascript loaded in HTML through AJAX will not be executed.
If you want to include scripts dynamically, append <script> tags to the existing loaded page's <head> element.
execute the script with jquery rather than with innerHTML
//this is not working!
document.getElementById("chart-content").innerHTML = this.responseText;
//try this
$("#chart-content").html(this.responseText);
The script is outside the body tag, and the loader picks out only the code inside the body tag, so the script is not even part of what you add to the page.
Loading you Js within the <head> should work. use this.
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', loadJs);
} else {
loadJs();
}
function loadJs() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/assets/script/editor-controlls.js';
script.defer = true
document.getElementsByTagName('head')[0].appendChild(script);
}

Categories