1

I am using Google Chrome version 98 for this.

I've noticed that when I have a window.prompt and I input <script>, it returns a string with the value of \x3Cscript> instead of <script>. This is odd to me because if I just input <, then it returns <. Only when I input <script> does it change the first angle bracket to its hex code; inputting <a> returns <a>, even inputting <scrip returns <scrip. What I am asking is, does the Javascript engine inside a browser do this parsing internally to prevent injecting Javascript? How does the window.prompt function work internally? I've tried searching for how window.prompt works and could not find anything related to this.

EDIT: I ask this question because I originally was testing out writing a cookie based on user input, and then making a greeting based on the cookie value. Here is the code:

const header = document.getElementById('survey-header');

if (document.cookie.split(';').some(item => item.trim().startsWith('name='))) {
    name = document.cookie
      .split('; ')
      .find(row => row.startsWith('name='))
      .split('=')[1];
  } else {
    name = window.prompt('Please enter your name', 'User');
    document.cookie = 'name=' + name
  }

  /* Set header to greeting message */
  header.textContent = 'Greetings, ' + name

But I noticed that when I try to inject Javascript into the prompt, the header is displayed as Greetings, \x3Cscript>...</script>. That made me curious why only some angle brackets are displayed as their hex code.

7
  • 3
    Unable to reproduce; are you sure it isn't just your machine/browser/engine or is there more code to this? Commented Mar 5, 2022 at 4:07
  • How are you outputting the value you enter into prompt? Commented Mar 5, 2022 at 4:08
  • I am going into the console and writing "foo = window.prompt("test", "test")", and writing "<script>" in the prompt. When I check the value of "foo" it is "\x3Cscript>". There is no other code involved. Even testing it on another computer it produces the same output. Commented Mar 5, 2022 at 4:12
  • 1
    But "\x3C" is "<". That’s just how the console displays this, possibly to mitigate XSS. It has nothing to do with prompt. Have you tried putting foo = "<script>" directly into the console? This is all you need to reproduce it in the latest stable Chromium. Commented Mar 5, 2022 at 4:21
  • It will do it for an end script tag as well </script> becomes \x3C/script>. Maybe it's some legacy security measure. And then there's this: stackoverflow.com/questions/8231048/… Commented Mar 5, 2022 at 4:22

1 Answer 1

3

There are a few differences between regular script execution and the "chrome console"/REPL. Regular scripts are executed by a JavaScript engine that conforms to the JavaScript (EcmaScript) specification, so the way different JavaScript engines behave is standardized. The chrome console on the other hand is free to have some special quirks and rules that it implements that don't necessarily follow the JavaScript spec. As a result, you'll find that some things behave slightly differently in the chrome console compared to how they would behave in a standard script (see here for another example).

In your case, the behavior you're seeing is specific to Chrome's console and isn't something that is done because it is specified in the JavaScript specification. The feature instead comes from a design decision made by the Chrome dev-tools team. The output you see is an escaped version of the string "<script>", which is done to enable users to safely copy outputs from the Chrome console into their own HTML code. This is outlined as part of the design goals for how the chrome console displays strings:

Design goals

We want to improve the readability of the displayed strings, while continuing to output valid JavaScript literals. To ensure security for our users, we should escape "<!-​-", "<script", and "</script" such that the resulting string can safely be copied into tags within HTML.

(their emphasis)

If you're curious, you can see how this is implemented here.

Because this behavior is specific to Chrome's console, regular JavaScript engines won't sanitize your user inputs - it is still up to you to use the appropriate DOM methods (such as .innerText, .textContent, etc.) and string sanitization methods for managing and displaying your user inputs securely. If you enter <script>alert(1);</script> in the input below, you'll find that your string is not escaped and can still cause securtity issues:

const userInput = prompt("Enter XSS code:");
document.write(userInput);

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the explanation, but I am still confused. I originally was testing out writing a cookie with the key "name" in plain Javascript, and greeting the user in the header of the page based on the name value. I ask the user to enter their name in the prompt, and then saved the cookie into document.cookie. I attempted to try out "<script>alert(1);</script>" in the prompt to see if the cookie would save that and cause an alert to appear when they refresh (since the value of name is written inside a <p> tag), but it didn't. What occurred here? I edited my question to include the code.
@Cizox In that case, you don't see an alert on your page because you're using .textContent. When you use .textContent the browser will render your content as text, and not HTML (even if it contains HTML such as <script>alert(1);</script>, the browser will parse your content to use HTML entities: &lt;script&gt;alert(1);&lt;/script&gt;), and so no alert is shown. Unlike with the browser console, the behaviour of .textContent escpaing your string content is specified and so it can be relied on.
“that don't necessarily follow the JavaScript spec” — More explicitly, the console has nothing to do with the JavaScript spec (or more accurately: ECMAScript spec). It has its own spec, standardized by WHATWG. Displaying \x3C instead of < is only a display concern and doesn’t affect the ECMAScript spec. The Console spec says “How the implementation prints [the log argument] is up to the implementation.”
@SebastianSimon thanks for the further clarification

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.