diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d9bba504f0..6981aed941 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - `vm_sufficient_daily_backup_retention_period` check for Azure provider [(#8200)](https://github.com/prowler-cloud/prowler/pull/8200) - `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) - Bedrock AgentCore privilege escalation combination for AWS provider [(#8526)](https://github.com/prowler-cloud/prowler/pull/8526) +- Add User Email and APP name/installations information in GitHub provider [(#8501)](https://github.com/prowler-cloud/prowler/pull/8501) - Remove standalone iam:PassRole from privesc detection and add missing patterns [(#8530)](https://github.com/prowler-cloud/prowler/pull/8530) - `eks_cluster_deletion_protection_enabled` check for AWS provider [(#8536)](https://github.com/prowler-cloud/prowler/pull/8536) - ECS privilege escalation patterns (StartTask and RunTask) for AWS provider [(#8541)](https://github.com/prowler-cloud/prowler/pull/8541) diff --git a/prowler/lib/outputs/finding.py b/prowler/lib/outputs/finding.py index a3ba6271dd..c7e1e1f05b 100644 --- a/prowler/lib/outputs/finding.py +++ b/prowler/lib/outputs/finding.py @@ -19,6 +19,7 @@ from prowler.lib.outputs.compliance.compliance import get_check_compliance from prowler.lib.outputs.utils import unroll_tags from prowler.lib.utils.utils import dict_to_lowercase, get_nested_attribute from prowler.providers.common.provider import Provider +from prowler.providers.github.models import GithubAppIdentityInfo, GithubIdentityInfo class Finding(BaseModel): @@ -250,15 +251,16 @@ class Finding(BaseModel): output_data["resource_name"] = check_output.resource_name output_data["resource_uid"] = check_output.resource_id - if hasattr(provider.identity, "account_name"): + if isinstance(provider.identity, GithubIdentityInfo): # GithubIdentityInfo (Personal Access Token, OAuth) output_data["account_name"] = provider.identity.account_name output_data["account_uid"] = provider.identity.account_id - elif hasattr(provider.identity, "app_id"): + output_data["account_email"] = provider.identity.account_email + elif isinstance(provider.identity, GithubAppIdentityInfo): # GithubAppIdentityInfo (GitHub App) - # TODO: Get Github App name - output_data["account_name"] = f"app-{provider.identity.app_id}" + output_data["account_name"] = provider.identity.app_name output_data["account_uid"] = provider.identity.app_id + output_data["installations"] = provider.identity.installations output_data["region"] = check_output.owner diff --git a/prowler/lib/outputs/html/html.py b/prowler/lib/outputs/html/html.py index 7b4fb87601..d7006b8cad 100644 --- a/prowler/lib/outputs/html/html.py +++ b/prowler/lib/outputs/html/html.py @@ -41,7 +41,7 @@ class HTML(Output): {finding_status} {finding.metadata.Severity.value} {finding.metadata.ServiceName} - {":".join([finding.resource_metadata['file_path'], "-".join(map(str, finding.resource_metadata['file_line_range']))]) if finding.metadata.Provider == "iac" else finding.region.lower()} + {":".join([finding.resource_metadata["file_path"], "-".join(map(str, finding.resource_metadata["file_line_range"]))]) if finding.metadata.Provider == "iac" else finding.region.lower()} {finding.metadata.CheckID.replace("_", "_")} {finding.metadata.CheckTitle} {finding.resource_uid.replace("<", "<").replace(">", ">").replace("_", "_")} @@ -558,10 +558,65 @@ class HTML(Output): try: if hasattr(provider.identity, "account_name"): # GithubIdentityInfo (Personal Access Token, OAuth) - account_display = provider.identity.account_name + account_info_items = f""" +
  • + GitHub account: {provider.identity.account_name} +
  • + """ + # Add email if available + if ( + hasattr(provider.identity, "account_email") + and provider.identity.account_email + ): + account_info_items += f""" +
  • + GitHub account email: {provider.identity.account_email} +
  • """ elif hasattr(provider.identity, "app_id"): # GithubAppIdentityInfo (GitHub App) - account_display = f"app-{provider.identity.app_id}" + # Assessment items: App Name and Installations + account_info_items = f""" +
  • + GitHub App Name: {provider.identity.app_name} +
  • """ + # Add installations if available + if ( + hasattr(provider.identity, "installations") + and provider.identity.installations + ): + installations_display = ", ".join(provider.identity.installations) + account_info_items += f""" +
  • + Installations: {installations_display} +
  • """ + else: + account_info_items += """ +
  • + Installations: No installations found +
  • """ + + # Credentials items: Authentication method and App ID + credentials_items = f""" +
  • + GitHub authentication method: {provider.auth_method} +
  • +
  • + GitHub App ID: {provider.identity.app_id} +
  • """ + else: + # Fallback for other identity types + account_info_items = "" + credentials_items = f""" +
  • + GitHub authentication method: {provider.auth_method} +
  • """ + + # For PAT/OAuth, use default credentials structure + if hasattr(provider.identity, "account_name"): + credentials_items = f""" +
  • + GitHub authentication method: {provider.auth_method} +
  • """ return f"""
    @@ -569,11 +624,8 @@ class HTML(Output):
    GitHub Assessment Summary
    -
    @@ -582,11 +634,8 @@ class HTML(Output):
    GitHub Credentials
    -