diff options
| author | Martin Trigaux <mat@odoo.com> | 2021-03-02 14:18:13 +0000 |
|---|---|---|
| committer | Martin Trigaux <mat@odoo.com> | 2021-03-05 13:08:29 +0000 |
| commit | 2daf3e6b19f323e824d5d843c8ad9484382ab8a1 (patch) | |
| tree | 2f19589937bb4abc36889d081cd3c211787662ff /doc/reference | |
| parent | 9529e29615699942aac89099cd37144e052b9004 (diff) | |
[ADD] doc: section on Escaping vs Sanitizing
Source https://github.com/odoo/enterprise/pull/15297#issuecomment-768985663
closes odoo/odoo#67363
X-original-commit: d767e01ca02b702dbef22451fc1c72c996192708
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Diffstat (limited to 'doc/reference')
| -rw-r--r-- | doc/reference/security.rst | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/doc/reference/security.rst b/doc/reference/security.rst index 6e072372257..7c235b08338 100644 --- a/doc/reference/security.rst +++ b/doc/reference/security.rst @@ -257,6 +257,73 @@ While formatting the template differently would prevent such vulnerabilities. font-weight: bold; } +Escaping vs Sanitizing +---------------------- + +.. important:: + + Escaping is always 100% mandatory when you mix data and code, no matter how + safe the data + +**Escaping** converts *TEXT* to *CODE*. It is absolutely mandatory to do it +every time you mix *DATA/TEXT* with *CODE* (e.g. generating HTML or python code +to be evaluated inside a `safe_eval`), because *CODE* always requires *TEXT* to +be encoded. It is critical for security, but it's also a question of +correctness. Even when there is no security risk (because the text is 100% +guarantee to be safe or trusted), it is still required (e.g. to avoid breaking +the layout in generated HTML). + +Escaping will never break any feature, as long as the developer identifies which +variable contains *TEXT* and which contains *CODE*. + +.. code-block:: python + + >>> from odoo.tools import html_escape, html_sanitize + >>> data = "<R&D>" # `data` is some TEXT coming from somewhere + + # Escaping turns it into CODE, good! + >>> code = html_escape(data) + >>> code + '<R&D>' + + # Now you can mix it with other code... + >>> self.message_post(body="<strong>%s</strong>" % code) + +**Sanitizing** converts *CODE* to *SAFER CODE* (but not necessary *safe* code). +It does not work on *TEXT*. Sanitizing is only necessary when *CODE* is +untrusted, because it comes in full or in part from some user-provided data. If +the user-provided data is in the form of *TEXT* (e.g. the content from a form +filled by a user), and if that data was correctly escaped before putting it in +*CODE*, then sanitizing is useless (but can still be done). If however, the +user-provided data was **not escaped**, then sanitizing will **not** work as +expected. + +.. code-block:: python + + # Sanitizing without escaping is BROKEN: data is corrupted! + >>> html_sanitize(data) + '' + + # Sanitizing *after* escaping is OK! + >>> html_sanitize(code) + '<p><R&D></p>' + +Sanitizing can break features, depending on whether the *CODE* is expected to +contain patterns that are not safe. That's why `fields.Html` and +`tools.html_sanitize()` have options to fine-tune the level of sanitization for +styles, etc. Those options have to be carefully considered depending on where +the data comes from, and the desired features. The sanitization safety is +balanced against sanitization breakages: the safer the sanitisation the more +likely it is to break things. + +.. code-block:: python + + >>code = "<p class='text-warning'>Important Information</p>" + # this will remove the style, which may break features + # but is necessary if the source is untrusted + >> html_sanitize(code, strip_classes=True) + '<p>Important Information</p>' + Evaluating content ------------------ Some may want to ``eval`` to parse user provided content. Using ``eval`` should |
