-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experimental proof-of-concept of contextual autoescaping in PUG #2895
Conversation
For your three examples:
I suggest starting separate threads for any of these you wish to discuss further. |
I split out an issue for discussing The current PR does actually post-process Per interpolation in |
no, I don't want to add modes to pug. I only ever want to have one "latest" version of pug. What we could do is deprecate and ultimately error on escaped interpolation inside script/style tags and instead tell people to choose between the more obviously unsafe unescaped interpolation, and some new contextual interpolation |
Fair enough. Scheduled deprecation seems like a fine idea for unsafe features. Would it make sense to also have a scheduled ramp-up to contextual mode?
|
It doesn't need to be a mode, we can just add the new syntax - possibly in a major version if the code would previously have been valid. As long as the syntax is obscure enough I suspect we won't need to be that gradual in implementing it. |
How about I separate out all the changes to produce a semantically-neutral PR that just provides the hooks that enable the rest? I can also file an issue to capture discussion on spread syntax if that'd be helpful and maybe do some implementation work. |
Yes, implementation work for spread would be awesome. |
See lexer implementation here: pugjs/pug-lexer#52 |
This consolidates code generator code that produces instructions to append content to the output and allows customizing it. This enables features like pugjs#2895 which distinguishes between strings definitely authored by the template author and those possibly controlled by an attacker to escape strings in context. This approach allows the same hooks to both handle idiomatic pug like ```pug a [href=x] ``` and inlne html like ```html <a href="#{x}"> ``` See also pugjs#2952
Separated hooks out into #2958 |
This is a proof of concept, and is not presented as ready for merging in its current form.
Make it easier to write XSS-free PUG frontends by removing a couple
of major XSS vectors
filtered so that
javascript:
URLs will not cause execution.This is the single largest XSS vector after injecting
<script>
&attributes(...)
are now checked so that an attacker whocontrols a key and value cannot inject JavaScript via
event handlers attributes.
<script>
elements is JSON escaped.For example, given the template
without this change results in
but with these changes produces
This adds a
packages/pug-autoesc
which implements a contextualautoescaper similar to:
html/template
It modifies the code generating code in
pug-code-gen
andpug-attrs
to consolidate code that appends output to
pug_html
so that, whenoptions.bufferHooksExperimental
is present, the generated codeinstead can write to a buffer object.
packages/pug-autoesc
defines such a buffer class.It modifies
packages/pug-runtime
to make the buffer class anda few supporting functions available at runtime.
Similar systems allow type-safe exceptions to the rule via typed
strings like Angular's [SafeValue][] type as detailed in "Securing
the Tangled Web".
Should the runtime check if
require('@angular/platform-browser')
succeeds at runtime and treat such values as privileged when
such values are written at runtime.
SafeValue: https://angular.io/api/platform-browser/SafeValue
Once we have context about which scripts and styles are under
template author control, we can also make it easier to deploy
the templates under a Content-Security-Policy.
Would PUG users benefit from auto-noncing?
Pug has a plugin mechanism that can operate on the source files,
token stream, ASTs, or generated JS.
This proof-of-concept is not written as a plugin. Instead it
uses hooks so that generated code of the form
(
pug_html = pug_html + ...
) can be replaced with writesthat accumulate content onto a buffer along with information
about whether that content comes from the template author or
not.
It might be possible to implement equivalent functionality as an
AST plugin that adds calls to filter functions to the AST.
Doing this conservatively might require complicated static analysis
that is aware of template inheritance and which takes into account
the contexts in which mixins are called.
If this approach is taken, the AST pass first need to translate
constructs like
to
or just reject them, and behave similarly on unescaped buffered code
interpolations like
p != thereBeTagsOfUnkownProvenanceHere
Doing things this way would make the functioning of the plugin
dependent on any later AST processing plugins, and it would have to
panic if there are new kinds of AST nodes added to be conservative.