It is because id attribute is not safe.
This is not my answer but it will answer your question : https://security.stackexchange.com/questions/88973/why-do-id-attributes-need-stricter-validation
For id
and name
, these attributes are frequently used as reference points in the DOM.
If an attacker can spoof these reference points, she may be able trick existing scripts into getting and setting values from places other than designed, which may be dangerous depending on the context that is is used.
Note from me: The rest of his post talks about the name attribute, but you'll get the idea behind all this if you don't already by what's above
This also applies to HTML forms where name
is used to identify the name/value pair. For example, if a website does not encode a particular form field when it is output, but since the form field is server generated and the form is protected against CSRF by the use of tokens it cannot be exploited by normal means. However, an attacker may be able to entice a user to visit a URL with a parameter that is used in name
, containing an XSS payload to execute on submission of the form.
e.g. Normal use:
https://example.com/product?item_name=watch&qty=1
which renders a form
<form>
<input type="hidden" name="watch" value="1" />
<input type="hidden" name="shop_name" value="Bob's Supplies" />
<input type="hidden" name="anti-csrf" value="asdjasodhoai" />
<input type="submit" value="Click here to buy" />
</form>
And then gets output as
Thank you for buying from Bob's Supplies.
However, an attacker could send a link to the user like so:
https://example.com/product?item_name=shop_name&qty=<script>alert('xss')</script>
As the application is correctly HTML encoding at this point it renders the form as
<form>
<input type="hidden" name="shop_name" value="<script>alert('xss')</script>" />
<input type="hidden" name="shop_name" value="Bob's Supplies" />
<input type="hidden" name="anti-csrf" value="asdjasodhoai" />
<input type="submit" value="Click here to buy" />
</form>
This then gets output as
Thank you for buying from <script>alert('xss')</script>.
since this page doesn't HTML encode the shop_name
parameter because it is trusted and the application framework always takes the first value in case of duplicates. Very contrived, but it was the first thing that fell into my head to demonstrate the point.