Skip to content
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

[Alerts] unable to use a context variable with an embedded newline in a webhook action #79371

Closed
pmuellr opened this issue Oct 2, 2020 · 8 comments · Fixed by #83919
Closed
Assignees
Labels
Feature:Alerting R&D Research and development ticket (not meant to produce code, but to make a decision) Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams)

Comments

@pmuellr
Copy link
Member

pmuellr commented Oct 2, 2020

Working with a customer, and though I don't know for sure this is their problem, feels like it probably is.

They are using a webhook action, with a JSON mustache template, that works in one case, but when they add an additional context variable to one of the property values in the JSON, they are getting a 500 response from the service they are calling.

My guess is the variable contains a " character. If so, it would end up rendering invalid JSON.

Eg,

template: {"foo": "{{context.bar}}"}

if context.bar evaluates to the string xyz, the result of rendering the template will be {"foo": "xyz"}, which is fine.

if context.bar evaluates to the string x"z, the result of rendering the template will be {"foo": "x"z"}, which is no longer valid JSON, and won't be usable in any webhook expecting JSON.

I don't know of any work-around for this ATM, nor am I sure how we can make fixes to make this work, given the way the mustache templating currently works with alert params.

@pmuellr pmuellr added Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) Project:Alerting labels Oct 2, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-alerting-services (Team:Alerting Services)

@pmuellr
Copy link
Member Author

pmuellr commented Oct 6, 2020

Turns out it wasn't a " char, but a new line char \n - same problem, yields invalid JSON as you can't use multi-line strings in JSON.

@pmuellr
Copy link
Member Author

pmuellr commented Oct 6, 2020

To be able to handle this, we're going to need to do different escaping for different types of content - at least Slack markdown, "regular" markdown (for email), JSON for the index action and webhook, and perhaps others for webhook (XML?).

There is a way to customize the "escaper" in the mustache module we're using, shown here:

  // Export the escaping function so that the user may override it.
  // See https://github.com/janl/mustache.js/issues/244
  mustache.escape = escapeHtml;

The referenced issue contains some discussion, none terribly useful for us ATM, other than indicating this facility exists.

It appears that mustache doesn't do any context switches (async, callbacks, etc), so in theory we can change the escaper before calling into mustache, then change it back when we're done, without affecting any other callers of the module. Kinda awful, but should work.

We'll need to build out the escapers we need, and I think we'll need to allow webhook action to indicate WHICH escaper to use; we could try to guess via a provided content-type header, but I'd guess that's not used all the time. Feels like the "escaper" to use for webhook is going to have to be a config property.

@pmuellr
Copy link
Member Author

pmuellr commented Oct 6, 2020

I should note that this assumes customers that customers aren't relying on other "structure" in their context variables. Eg, in theory you could do this with a JSON mustache template string, or similar, with the idea being that context.additionalProperties could be set to the string"bar": "foo":

{
  "foo": "bar",
  {{context.additionalProperties}}
}

I would be very surprised if there was an existing context variable that could be used in that situation today, but hopefully you get the gist.

The intention would be that you can only use context variables where "plain text strings" (or numbers, or booleans) could be used, no embedded markup/structuring .

@pmuellr
Copy link
Member Author

pmuellr commented Oct 6, 2020

Another thought is to use a different templating system - depending on if it was wildly different than mustache, we might need to allow the customer to choose which one to use, which would get complicated. There are some templating systems that allow you to filter the value with additional built-in functions, I think typically using a | char as a separator. Eg, you could imagine

{{context.someVariable | trimString | escapeForJSON}}

where trimString and escapeForJSON are functions we provide, that do what you would expect, so the resulting value would be trimmed and then JSON-escaped before rendered into the template.

@pmuellr pmuellr changed the title [Alerts] unable to use a double quote char in a context variable in a webhook action [Alerts] unable to use a context variable with an embedded newline in a webhook action Oct 7, 2020
@pmuellr
Copy link
Member Author

pmuellr commented Oct 22, 2020

I took a look at handlebars as a replacement for mustache, but two things:

  • there are existing security concerns using it
  • it's waaaay more complicated, and I don't really want to put more complication in front of users; it's really designed for developers, not as a end-user templating story

@pmuellr
Copy link
Member Author

pmuellr commented Oct 22, 2020

I started looking into a story where we can allow actions to determine how to escape strings in their parameters. Probably this would evolve to the point where an action type would need to declare an entrypoint to "expand it's templates", and then can expand whatever params they want (and NOT expand params they DON'T want - something we don't support today!), and indicate how to do escaping of the content.

Initial bits in a branch here: master...pmuellr:actions/per-type-mustache-escaping

@pmuellr
Copy link
Member Author

pmuellr commented Nov 10, 2020

In addition to the story outlined in #79371 (comment), which I think we should certainly do long-term, wondering if there's a simpler fix for short-term, since this is a pretty serious issue. Mainly affects JSON-based actions - webhook and index.

pmuellr added a commit to pmuellr/kibana that referenced this issue Dec 8, 2020
resolves elastic#79371
resolves elastic#75601
resolves elastic#62928

In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates.  Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library.  The default mustache
templating used html escaping.

Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`.  If not
provided, the previous recursive rendering is done, but now with
no escaping at all.

For elastic#75601, added toString() methods to mustache object variables
which allow them to be used in a template and expanded to
JSON, for experimentation / discovery of context variables.

For elastic#62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred.  Useful
to diagnose problems with invalid mustache templates.
pmuellr added a commit to pmuellr/kibana that referenced this issue Dec 8, 2020
resolves elastic#79371
resolves elastic#62928

In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates.  Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library.  The default mustache
templating used html escaping.

Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`.  If not
provided, the previous recursive rendering is done, but now with
no escaping at all.

For elastic#62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred.  Useful
to diagnose problems with invalid mustache templates.
pmuellr added a commit that referenced this issue Dec 15, 2020
… parameter templates (#83919)

resolves #79371
resolves #62928

In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates.  Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library.  The default mustache
templating used html escaping.

Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`.  If not
provided, the previous recursive rendering is done, but now with
no escaping at all.

For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred.  Useful
to diagnose problems with invalid mustache templates.
pmuellr added a commit to pmuellr/kibana that referenced this issue Dec 15, 2020
… parameter templates (elastic#83919)

resolves elastic#79371
resolves elastic#62928

In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates.  Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library.  The default mustache
templating used html escaping.

Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`.  If not
provided, the previous recursive rendering is done, but now with
no escaping at all.

For elastic#62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred.  Useful
to diagnose problems with invalid mustache templates.
pmuellr added a commit that referenced this issue Dec 15, 2020
… parameter templates (#83919) (#85901)

resolves #79371
resolves #62928

In this PR, we allow action types to determine how to escape the
variables used in their parameters, when rendered as mustache
templates.  Prior to this, action parameters were recursively
rendered as mustache templates using the default mustache
templating, by the alerts library.  The default mustache
templating used html escaping.

Action types opt-in to the new capability via a new optional
method in the action type, `renderParameterTemplates()`.  If not
provided, the previous recursive rendering is done, but now with
no escaping at all.

For #62928, changed the mustache template rendering to be
replaced with the error message, if an error occurred,
so at least you can now see that an error occurred.  Useful
to diagnose problems with invalid mustache templates.
@kobelb kobelb added the needs-team Issues missing a team label label Jan 31, 2022
@botelastic botelastic bot removed the needs-team Issues missing a team label label Jan 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Alerting R&D Research and development ticket (not meant to produce code, but to make a decision) Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams)
Projects
None yet
4 participants