<span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><div>I have come across a scenario in an application and would like some advice on the subject of applying the proper encoding.  </div>
<div><br></div><div><br></div><div>Scenario:</div><div>A developer is taking user input and using it to dynamically construct an URL which is used in an onClick event handler of an &lt;a&gt; tag.  The code (JSP) looks similar to this:</div>
<div><br></div><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; ">
<div><font face="&#39;courier new&#39;, monospace">&lt;a HREF=&quot;&quot;<br>onClick=&quot;window.open(&#39;<a href="http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=" target="_blank" style="color: rgb(28, 81, 168); ">http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=</a>&lt;%=</font><span style="font-family: &#39;courier new&#39;, monospace; ">request.getParameter(&quot;test&quot;)%&gt;&#39;, &#39;windowRef&#39;, &#39;</span></div>
<span style="font-family: &#39;courier new&#39;, monospace; ">resizable=yes,scrollbars=yes,status=no,location=no,toolbars=yes,height=500,width=800&#39;); return false;&quot;&gt;link text&lt;/a&gt;</span></blockquote><div>
<br></div><div><br></div><div>As you can see, param3 is vulnerable to XSS.  The tricky part is that the data is being used to form a URL (URL Context) but from within a JavaScript event handler (JavaScript Context). </div>
</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><div><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><br>
</span></div>The question is - Which of the following encoding strategies would be the right one to use?</span><span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px; "><div>
<br></div><div><br></div><div>Option 1: Only use URL encoding</div><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; ">
<div><font face="&#39;courier new&#39;, monospace">&lt;a HREF=&quot;&quot;<br>onClick=&quot;window.open(&#39;<a href="http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=" target="_blank" style="color: rgb(28, 81, 168); ">http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=</a>&lt;%= OutputEncoder.encodeForURL(</font><span style="font-family: &#39;courier new&#39;, monospace; ">request.getParameter(&quot;test&quot;)) %&gt;&#39;, &#39;windowRef&#39;, &#39;</span></div>
<span style="font-family: &#39;courier new&#39;, monospace; ">resizable=yes,scrollbars=yes,status=no,location=no,toolbars=yes,height=500,width=800&#39;); return false;&quot;&gt;link text&lt;/a&gt;</span></blockquote><div>
<br></div><div>This option appears to work well, but are still in a JavaScript context and are unsure if there would still be attack strings that would allow for a successful XSS attack.</div><div><br></div><div><br></div>
<div>Option 2: Only use JavaScript encoding:</div><div><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; ">
<font face="&#39;courier new&#39;, monospace">&lt;a HREF=&quot;&quot;<br></font><font face="&#39;courier new&#39;, monospace">onClick=&quot;window.open(&#39;<a href="http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=" target="_blank" style="color: rgb(28, 81, 168); ">http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=</a>&lt;%= OutputEncoder.encodeForJavaScript(</font><span style="font-family: &#39;courier new&#39;, monospace; ">request.getParameter(&quot;test&quot;)) %&gt;&#39;, &#39;windowRef&#39;, &#39;<br>
</span><span style="font-family: &#39;courier new&#39;, monospace; ">resizable=yes,scrollbars=yes,status=no,location=no,toolbars=yes,height=500,width=800&#39;); return false;&quot;&gt;link text&lt;/a&gt;</span></blockquote>
</div><div><br></div><div>This option works from a security standpoint, but breaks in scenarios where the value of the parameter <i>test</i> is supposed to equal &quot;blah&amp;a=b&quot;.  When using only JavaScript encoding, page.jsp would read the value of param3 as blah and have an extra parameter named a with the value b instead of having the value of param3 equal blah&amp;a=b which ultimately results in a functional defect.</div>
<div><br></div><div><br></div><div>Option 3: Double encode using URL AND JavaScript encoding</div><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; ">
<font face="&#39;courier new&#39;, monospace">&lt;a HREF=&quot;&quot;<br></font><font face="&#39;courier new&#39;, monospace">onClick=&quot;window.open(&#39;<a href="http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=" target="_blank" style="color: rgb(28, 81, 168); ">http://www.example.com/app/page.jsp?param1=a&amp;param2=b&amp;param3=</a>&lt;%= OutputEncoder.encodeForJavaScript(</font><font face="&#39;courier new&#39;, monospace">OutputEncoder.encodeForURL(</font><span style="font-family: &#39;courier new&#39;, monospace; ">request.getParameter(&quot;test&quot;))</span><span style="font-family: &#39;courier new&#39;, monospace; ">) %&gt;&#39;, &#39;windowRef&#39;, &#39;<br>
</span><span style="font-family: &#39;courier new&#39;, monospace; ">resizable=yes,scrollbars=yes,status=no,location=no,toolbars=yes,height=500,width=800&#39;); return false;&quot;&gt;link text&lt;/a&gt;</span></blockquote>
<div><br></div><div>This seems to also work, but am not sure about recommending a double-encoding strategy.  For one, it adds another level of complexity that could potentially lead to problems down the road.  Secondly, isn&#39;t double-encoding usually frowned upon as a solution? </div>
<div><br></div><div><br></div><div>Please let me know if any of this does not make sense, or if I can provide you with any additional information.</div><div><br></div><div><br></div><div>Thanks, <br>Matt</div></span>