Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/Semgrep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Name of this GitHub Actions workflow.
name: Semgrep

on:
# Scan changed files in PRs (diff-aware scanning):
# The branches below must be a subset of the branches above
pull_request:
branches: ["master", "main"]
push:
branches: ["master", "main"]
schedule:
- cron: '0 6 * * *'


permissions:
contents: read

jobs:
semgrep:
# User definable name of this GitHub Actions job.
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
name: semgrep/ci
# If you are self-hosting, change the following `runs-on` value:
runs-on: ubuntu-latest

container:
# A Docker image with Semgrep installed. Do not change this.
image: returntocorp/semgrep

# Skip any PR created by dependabot to avoid permission issues:
if: (github.actor != 'dependabot[bot]')

steps:
# Fetch project source with GitHub Actions Checkout.
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
# Run the "semgrep ci" command on the command line of the docker image.
- run: semgrep ci --sarif --output=semgrep.sarif
env:
# Add the rules that Semgrep uses by setting the SEMGREP_RULES environment variable.
SEMGREP_RULES: p/default # more at semgrep.dev/explore

- name: Upload SARIF file for GitHub Advanced Security Dashboard
uses: github/codeql-action/upload-sarif@6c089f53dd51dc3fc7e599c3cb5356453a52ca9e # v2.20.0
with:
sarif_file: semgrep.sarif
if: always()
34 changes: 34 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Reporting Security Vulnerabilities

BrowserStack Community take all security vulnerabilities seriously. Thank you for improving the security of our open source software. We appreciate your efforts and responsible disclosure. We will make every effort to acknowledge your contributions.

Please do NOT raise a GitHub Issue to report a security vulnerability. If you believe you have found a security vulnerability, report it by emailing the BrowserStack security team at:

security@browserstack.com

Please include as much of the information listed below as you can to help us better understand and resolve the issue:

* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
* Full paths of source file(s) related to the manifestation of the issue
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

# Please don't do the following

- Do not take advantage of the vulnerability or problem you have discovered.
- Do not reveal the problem to others until it has been resolved.
- Do not use other channels or contact project contributors directly.

# Disclosure Policy

When the security team receives a security bug report, they will assign it to the concerned team. This team will coordinate the fix and release process, involving the following steps:

* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* These fixes will be released as fast as possible.

**Vulnerabilities found in this software are not eligible for any kind of bounty rewards and BrowserStack will not be responsible for issuing any CVE for the found security issue.**
59 changes: 50 additions & 9 deletions confluence/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import requests

from Access.base_email_access.access import BaseEmailAccess
from EnigmaAutomation.settings import ACCESS_MODULES
from enigma_automation.settings import ACCESS_MODULES
from . import constants

logger = logging.getLogger(__name__)
Expand All @@ -18,18 +18,23 @@ class Confluence(BaseEmailAccess):
urlpatterns = []

def _get_confluence_config(self):
"""Returns confluence module config."""
return ACCESS_MODULES.get(self.tag(), {})

def _get_admin_email(self):
"""Returns admin email from config."""
return self._get_confluence_config()["ADMIN_EMAIL"]

def _get_api_token(self):
"""Returns API token from config."""
return self._get_confluence_config()["API_TOKEN"]

def _get_base_url(self):
"""Returns base URL for confluence from config."""
return self._get_confluence_config()["CONFLUENCE_BASE_URL"]

def can_auto_approve(self):
"""Returns true or false as if required to auto approve or manual approval."""
return False

def fetch_access_request_form_path(self):
Expand Down Expand Up @@ -83,6 +88,11 @@ def validate_request(self, access_labels_data, request_user, is_group=False):
return valid_access_label_array

def __in_access_types(self, access_type):
"""
Takes in an access type and checks if it is present in a list of access types.

access_type: Specifies the type of access being requested or checked for.
"""
return access_type in ["View Access", "Edit Access", "Admin Access"]

def get_label_desc(self, access_label):
Expand Down Expand Up @@ -155,13 +165,13 @@ def __approve_space_access(
return json.loads(response.text)["message"].split(" ")[-1]
logger.error(
"Could not approve permission %s for response %s",
str(permission), str(response.text)
str(permission),
str(response.text),
)
return False
except Exception as ex:
logger.error(
"Could not approve permission %s for error %s",
str(permission), str(ex)
"Could not approve permission %s for error %s", str(permission), str(ex)
)
return False

Expand All @@ -185,7 +195,8 @@ def __revoke_space_access(self, space_key, permission_id):
except Exception as ex:
logger.error(
"Could not approve permission %s for error %s",
str(permission_id), str(ex)
str(permission_id),
str(ex),
)
return False

Expand Down Expand Up @@ -237,6 +248,11 @@ def access_request_data(self, request, is_group=False):
return available_spaces

def __get_accesses_with_type(self, access_type):
"""
returns a list of accesses with a specified access type.

access_type: Specifies the type of access being searched for.
"""
view_permissions = [
{"key": "read", "target": "space"},
{"key": "delete", "target": "space"},
Expand Down Expand Up @@ -329,8 +345,10 @@ def approve(
def __send_approve_email(self, user, request_id, access_type, approver):
"""Generates and sends email in access grant."""
targets = self.email_targets(user)
subject = (f"Approved Access: {request_id} for access to"
f" {self.access_desc()} for user {user.email}")
subject = (
f"Approved Access: {request_id} for access to"
f" {self.access_desc()} for user {user.email}"
)

body = self.__generate_string_from_template(
filename="confluence/approve_email.html",
Expand All @@ -341,6 +359,12 @@ def __send_approve_email(self, user, request_id, access_type, approver):
self.email_via_smtp(targets, subject, body)

def __generate_string_from_template(self, filename, **kwargs):
"""
Generates a string from a template file using keyword arguments.

filename: The filename parameter is a string that represents the name of the file that
contains the template for generating the string.
"""
template = loader.get_template(filename)
vals = {}
for key, value in kwargs.items():
Expand Down Expand Up @@ -392,9 +416,19 @@ def access_desc(self):
return "Confluence Access Module"

def get_identity_template(self):
"""
Returns path to identity form template.
"""
return "confluence/identity_form.html"

def __is_valid_identity(self, id, email):
"""
The function checks if a given identity and email are valid.

id: A unique identifier for a user or entity in a system. It

email: An email address.
"""
auth = HTTPBasicAuth(
self._get_admin_email(),
self._get_api_token(),
Expand All @@ -417,11 +451,18 @@ def __is_valid_identity(self, id, email):
return True

def verify_identity(self, request, email):
id = request["confluence_id"]
"""
Takes in a request and an email address as parameters and verifies the identity
associated with the email.

email: The email parameter is a string that represents the email address of the user
whose identity needs to be verified.
"""
confluence_id = request["confluence_id"]
if not self.__is_valid_identity(id, email):
return None

return {"id": id}
return {"id": confluence_id}

def tag(self):
"""Returns confluence access tag."""
Expand Down