Skip to content

Commit

Permalink
feat(python): add permissive cross domain policy rule (CWE-942) (#427)
Browse files Browse the repository at this point in the history
  • Loading branch information
elsapet authored May 30, 2024
1 parent 097b916 commit 049e52d
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 0 deletions.
58 changes: 58 additions & 0 deletions rules/python/django/permissive_allow_origin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
imports:
- python_shared_django_http_response
- python_shared_lang_import2
patterns:
- pattern: $<RESPONSE>.headers[$<ALLOW_ORIGIN>] = $<...>$<VALUE>$<...>
filters:
- variable: RESPONSE
detection: python_shared_django_http_response
scope: cursor
- variable: ALLOW_ORIGIN
string_regex: (?i)\Aaccess-control-allow-origin\z
- variable: VALUE
string_regex: \A\*\z
- pattern: |
$<RESPONSE>($<...> headers={$<...>$<ALLOW_ORIGIN>: $<...>$<VALUE>$<...>} $<...>)
filters:
- variable: RESPONSE
detection: python_shared_lang_import2
scope: cursor
filters:
- variable: MODULE1
values: [django]
- variable: MODULE2
values: [http]
- variable: NAME
values: [HttpResponse]
- variable: ALLOW_ORIGIN
string_regex: (?i)\Aaccess-control-allow-origin\z
- variable: VALUE
string_regex: \A\*\z
languages:
- python
severity: medium
metadata:
description: Permissive Access-Control-Allow-Origin configuration
remediation_message: |-
## Description
A permissive Access-Control-Allow-Origin configuration can expose your application to security risks. When this header is set to "*", it means your application's responses can be accessed by any website, potentially leading to unauthorized access to sensitive information.
## Remediations
- **Do not** set the Access-Control-Allow-Origin header to "*". This overly permissive setting can make your application vulnerable to attacks.
```python
response.headers['Access-Control-Allow-Origin'] = '*' # unsafe
```
- **Do** restrict the Access-Control-Allow-Origin header to only allow specific, trusted origins that need access to your application. This minimizes the risk of sensitive data exposure.
```python
response.headers['Access-Control-Allow-Origin'] = 'myapp.example.com'
```
## References
- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing)
cwe_id:
- 942
id: python_django_permissive_allow_origin
documentation_url: https://docs.bearer.com/reference/rules/python_django_permissive_allow_origin
52 changes: 52 additions & 0 deletions rules/python/lang/permissive_allow_origin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
imports:
- python_shared_lang_instance
- python_shared_lang_import2
patterns:
- pattern: $<HANDLER>.send_header($<ALLOW_ORIGIN>, $<...>$<VALUE>$<...>)
filters:
- variable: ALLOW_ORIGIN
string_regex: (?i)\Aaccess-control-allow-origin\z
- variable: VALUE
string_regex: \A\*\z
- variable: HANDLER
detection: python_shared_lang_instance
scope: cursor
filters:
- variable: CLASS
detection: python_shared_lang_import2
scope: cursor
filters:
- variable: MODULE1
values: [http]
- variable: MODULE2
values: [server]
- variable: NAME
values: [BaseHTTPRequestHandler]
languages:
- python
severity: medium
metadata:
description: Permissive Access-Control-Allow-Origin configuration
remediation_message: |-
## Description
A permissive Access-Control-Allow-Origin configuration can expose your application to security risks. When this header is set to "*", it means your application's responses can be accessed by any website, potentially leading to unauthorized access to sensitive information.
## Remediations
- **Do not** set the Access-Control-Allow-Origin header to "*". This overly permissive setting can make your application vulnerable to attacks.
```python
self.send_header('Access-Control-Allow-Origin', '*') # unsafe
```
- **Do** restrict the Access-Control-Allow-Origin header to only allow specific, trusted origins that need access to your application. This minimizes the risk of sensitive data exposure.
```python
self.send_header('Access-Control-Allow-Origin', 'myapp.example.com');
```
## References
- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing)
cwe_id:
- 942
id: python_lang_permissive_allow_origin
documentation_url: https://docs.bearer.com/reference/rules/python_lang_permissive_allow_origin
20 changes: 20 additions & 0 deletions tests/python/django/permissive_allow_origin/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("permissive_allow_origin", () => {
const testCase = "main.py"

const results = invoke(testCase)

expect(results).toEqual({
Missing: [],
Extra: []
})
})
})
16 changes: 16 additions & 0 deletions tests/python/django/permissive_allow_origin/testdata/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Use bearer:expected python_django_permissive_allow_origin to flag expected findings

from django.http import HttpResponse

response = HttpResponse()
# bearer:expected python_django_permissive_allow_origin
response.headers['access-control-allow-origin'] = '*'

# bearer:expected python_django_permissive_allow_origin
HttpResponse(headers={"Access-Control-Allow-Origin": "*"})

# ok
response = HttpResponse()
response.headers['access-control-allow-origin'] = 'https://my-example-site.com'

HttpResponse(headers={"Access-Control-Allow-Origin": "https://my-example-site.com"
20 changes: 20 additions & 0 deletions tests/python/lang/permissive_allow_origin/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("permissive_allow_origin", () => {
const testCase = "main.py"

const results = invoke(testCase)

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

class BadClass(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
# bearer:expected python_lang_permissive_allow_origin
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()

class OkClass(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.send_header('Access-Control-Allow-Origin', 'https://my-example-site.com')
self.end_headers()

0 comments on commit 049e52d

Please sign in to comment.