Repository: Nukesor/pueue (language: rust)

Issue:
HTML escaping of callback arguments
It seems the existing callback templating will HTML-escape the output. 

For example, the callback from the Wiki:
`callback: '/path/to/callback "{{id}}" "{{command}}" "{{path}}" "{{result}}" "{{group}}" "{{start}}" "{{end}}"'`
, for a command such as `pueue add "sleep 1 && echo hi"` will provide `command` as `sleep 1 &amp;&amp; echo hi` to the callback script. This extends to a bunch of common characters like instances of a single quote `'` becoming `&#x27`, and also to all the possible task fields you can provide to the callback, including `output`.

**This escaping can be avoided by using triple braces rather than double braces for the templating.**

While this behavior seems to be the default for Handlebars https://handlebarsjs.com/guide/expressions.html#html-escaping, I wasn't familiar and spent some time hunting things down. **I think there should be a note in the Wiki in the callback section**, perhaps something like:

> Note that the above Handlebars templating with double braces `{{ variable }}` will HTML-escape the output. Avoid this by using triple braces `{{{ variable }}}`.

, particularly since it isn't mentioned what provides the templating (nor do I necessarily think it should be). Perhaps the triple braces should even be used in the examples, but maybe the other notification examples rely it. 

Note that other places in the code will outright disable this escaping such as:

https://github.com/Nukesor/pueue/blame/afcd28dbb8789b89ed3e2023996f9c0830bb9554/pueue_lib/src/process_helper/mod.rs#L63-L65

I think giving users the option to automatically escape the output is fine though, so not advocating for this to be done for the callback processing. Opened the issue since a) not sure if random contributions to Wiki are okay and b) searchability/exposure for others that might have this issue. 


### Steps to reproduce

1. Add callback to config file such as `callback: 'echo "{{command}}" > ~/callback.txt'`
2. Run a command with HTML characters `pueue add "sleep 1 && echo hi"`
3. Observe output in `output.txt` as `sleep 1 &amp;&amp; echo hi`

### Debug logs (if relevant)

_No response_

### Operating system

RHEL7, WSL2

### Pueue version

v3.4.1

### Additional context

_No response_


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9536b51ed..9fcb738f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,10 +35,6 @@ Upon updating Pueue, the previous state will be wiped, resulting in a clean slat
 
 TLDR: The new task state representation is more verbose but significantly cleaner and fixes some bugs. It breaks compatibility with old states, so ensure there are no important tasks in your queue before updating. You'll also need to recreate groups.
 
-### Fixed
-
-- Fixed delay after sending process related commands from client. [#548](https://github.com/Nukesor/pueue/pull/548)
-
 ### Change
 
 - **Breaking**: Refactor internal task state. Some task variables have been moved into the `TaskStatus` enum, which now enforces various invariants during compile time via the type system.
@@ -59,6 +55,11 @@ TLDR: The new task state representation is more verbose but significantly cleane
 - Add `command` filter to `pueue status`. [#524](https://github.com/Nukesor/pueue/issues/524) [#560](https://github.com/Nukesor/pueue/pull/560)
 - Allow `pueue status` to order tasks by `enqueue_at`. [#554](https://github.com/Nukesor/pueue/issues/554)
 
+### Fixed
+
+- Fixed delay after sending process related commands from client. [#548](https://github.com/Nukesor/pueue/pull/548)
+- Callback templating arguments were html escaped by accident. [#564](https://github.com/Nukesor/pueue/pull/564)
+
 ## \[3.4.1\] - 2024-06-04
 
 ### Added
diff --git a/pueue/src/daemon/callbacks.rs b/pueue/src/daemon/callbacks.rs
index 338b025fd..5d620eab7 100644
--- a/pueue/src/daemon/callbacks.rs
+++ b/pueue/src/daemon/callbacks.rs
@@ -55,6 +55,7 @@ pub fn build_callback_command(
     // Init Handlebars. We set to strict, as we want to show an error on missing variables.
     let mut handlebars = Handlebars::new();
     handlebars.set_strict_mode(true);
+    handlebars.register_escape_fn(handlebars::no_escape);
 
     // Add templating variables.
     let mut parameters = HashMap::new();


Test patch: