Skip to content

Commit

Permalink
feat: raw html using user input rule
Browse files Browse the repository at this point in the history
  • Loading branch information
didroe committed May 20, 2024
1 parent d299d7a commit fa0da07
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
41 changes: 41 additions & 0 deletions rules/python/lang/raw_html_using_user_input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
imports:
- python_shared_common_html_user_input
patterns:
- pattern: $<STRING>
filters:
- variable: STRING
string_regex: <\w+(\s[^>]*)?>
- variable: STRING
detection: python_shared_common_html_user_input
scope: result
severity: high
metadata:
description: "Unsanitized user input in raw HTML strings (XSS)"
remediation_message: |-
## Description
Including unsanitized user input in HTML exposes your application to cross-site scripting (XSS) attacks. This vulnerability allows attackers to inject malicious scripts into web pages viewed by other users.
## Remediations
- **Do not** include user input directly in HTML strings. This practice can lead to XSS vulnerabilities.
```python
html = f"<h1>{user_input}</h1>" # unsafe
```
- **Do** use a framework or templating language that automatically handles the encoding and sanitization of user input when constructing HTML. This approach minimizes the risk of XSS attacks.
- **Do** sanitize user input if you must use HTML strings directly. Utilize libraries designed for input sanitization to ensure that user input does not contain malicious content.
```python
from html_sanitizer import Sanitizer
sanitizer = Sanitizer()
sanitized_value = sanitizer.sanitize(user_input)
html = f"<h1>{sanitized_value}</h1>"
```
## References
- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)
cwe_id:
- 79
id: python_lang_raw_html_using_user_input
documentation_url: https://docs.bearer.com/reference/rules/python_lang_raw_html_using_user_input
25 changes: 24 additions & 1 deletion rules/python/shared/common/html_user_input.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,38 @@ type: shared
languages:
- python
imports:
- python_shared_lang_import1
- python_shared_common_user_input
- python_shared_django_html_sanitizer
sanitizer: python_shared_common_html_user_input_sanitizer
patterns:
- pattern: $<USER_INPUT>
filters:
- variable: USER_INPUT
detection: python_shared_common_user_input
scope: cursor
sanitizer: python_shared_django_html_sanitizer
auxiliary:
- id: python_shared_common_html_user_input_sanitizer
patterns:
- pattern: $<DJANGO_SANITIZER>
filters:
- variable: DJANGO_SANITIZER
detection: python_shared_django_html_sanitizer
scope: cursor_strict
- pattern: $<SANITIZER>.sanitize($<_>)
filters:
- variable: SANITIZER
detection: python_shared_lang_instance
scope: cursor
filters:
- variable: CLASS
detection: python_shared_lang_import1
scope: cursor
filters:
- variable: MODULE1
values: [html_sanitizer]
- variable: NAME
values: [Sanitizer]
metadata:
description: "Python HTML user input."
id: python_shared_common_html_user_input
20 changes: 20 additions & 0 deletions tests/python/lang/raw_html_using_user_input/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const {
createNewInvoker,
getEnvironment,
} = require("../../../helper.js")
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname)

describe(ruleId, () => {
const invoke = createNewInvoker(ruleId, ruleFile, testBase)

test("raw_html_using_user_input", () => {
const testCase = "main.py"

const results = invoke(testCase)

expect(results).toEqual({
Missing: [],
Extra: []
})
})
})
13 changes: 13 additions & 0 deletions tests/python/lang/raw_html_using_user_input/testdata/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from html_sanitizer import Sanitizer

user_input = input()

def bad():
# bearer:expected python_lang_raw_html_using_user_input
html = f"<strong>{user_input}</strong>"

def ok():
sanitizer = Sanitizer()
sanitized_value = sanitizer.sanitize(user_input)

html = f"<strong>{sanitized_value}</strong>"

0 comments on commit fa0da07

Please sign in to comment.