github-advanced-security[bot] commented on code in PR #49257: URL: https://github.com/apache/airflow/pull/49257#discussion_r2043003325
########## airflow-core/src/airflow/models/taskinstance.py: ########## @@ -3174,7 +2757,83 @@ :param exception: the exception sent in the email :param task: """ - return _get_email_subject_content(task_instance=self, exception=exception, task=task) + # For a ti from DB (without ti.task), return the default value + if task is None: + task = getattr(self, "task") + use_default = task is None + exception_html = str(exception).replace("\n", "<br>") + + default_subject = "Airflow alert: {{ti}}" + # For reporting purposes, we report based on 1-indexed, + # not 0-indexed lists (i.e. Try 1 instead of + # Try 0 for the first attempt). + default_html_content = ( + "Try {{try_number}} out of {{max_tries + 1}}<br>" + "Exception:<br>{{exception_html}}<br>" + 'Log: <a href="{{ti.log_url}}">Link</a><br>' + "Host: {{ti.hostname}}<br>" + 'Mark success: <a href="{{ti.mark_success_url}}">Link</a><br>' + ) + + default_html_content_err = ( + "Try {{try_number}} out of {{max_tries + 1}}<br>" + "Exception:<br>Failed attempt to attach error logs<br>" + 'Log: <a href="{{ti.log_url}}">Link</a><br>' + "Host: {{ti.hostname}}<br>" + 'Mark success: <a href="{{ti.mark_success_url}}">Link</a><br>' + ) + + additional_context: dict[str, Any] = { + "exception": exception, + "exception_html": exception_html, + "try_number": self.try_number, + "max_tries": self.max_tries, + } + + if use_default: + default_context = {"ti": self, **additional_context} + jinja_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), autoescape=True + ) + subject = jinja_env.from_string(default_subject).render(**default_context) + html_content = jinja_env.from_string(default_html_content).render(**default_context) + html_content_err = jinja_env.from_string(default_html_content_err).render(**default_context) + + else: + from airflow.sdk.definitions._internal.templater import SandboxedEnvironment + from airflow.utils.context import context_merge + + if TYPE_CHECKING: + assert self.task + + # Use the DAG's get_template_env() to set force_sandboxed. Don't add + # the flag to the function on task object -- that function can be + # overridden, and adding a flag breaks backward compatibility. + dag = self.task.get_dag() + if dag: + jinja_env = dag.get_template_env(force_sandboxed=True) + else: + jinja_env = SandboxedEnvironment(cache_size=0) + jinja_context = self.get_template_context() + context_merge(jinja_context, additional_context) + + def render(key: str, content: str) -> str: + if conf.has_option("email", key): + path = conf.get_mandatory_value("email", key) + try: + with open(path) as f: + content = f.read() + except FileNotFoundError: + log.warning("Could not find email template file '%s'. Using defaults...", path) + except OSError: + log.exception("Error while using email template %s. Using defaults...", path) Review Comment: ## Clear-text logging of sensitive information This expression logs [sensitive data (secret)](1) as clear text. This expression logs [sensitive data (secret)](2) as clear text. [Show more details](https://github.com/apache/airflow/security/code-scanning/467) ########## airflow-core/src/airflow/models/taskinstance.py: ########## @@ -3174,7 +2757,83 @@ :param exception: the exception sent in the email :param task: """ - return _get_email_subject_content(task_instance=self, exception=exception, task=task) + # For a ti from DB (without ti.task), return the default value + if task is None: + task = getattr(self, "task") + use_default = task is None + exception_html = str(exception).replace("\n", "<br>") + + default_subject = "Airflow alert: {{ti}}" + # For reporting purposes, we report based on 1-indexed, + # not 0-indexed lists (i.e. Try 1 instead of + # Try 0 for the first attempt). + default_html_content = ( + "Try {{try_number}} out of {{max_tries + 1}}<br>" + "Exception:<br>{{exception_html}}<br>" + 'Log: <a href="{{ti.log_url}}">Link</a><br>' + "Host: {{ti.hostname}}<br>" + 'Mark success: <a href="{{ti.mark_success_url}}">Link</a><br>' + ) + + default_html_content_err = ( + "Try {{try_number}} out of {{max_tries + 1}}<br>" + "Exception:<br>Failed attempt to attach error logs<br>" + 'Log: <a href="{{ti.log_url}}">Link</a><br>' + "Host: {{ti.hostname}}<br>" + 'Mark success: <a href="{{ti.mark_success_url}}">Link</a><br>' + ) + + additional_context: dict[str, Any] = { + "exception": exception, + "exception_html": exception_html, + "try_number": self.try_number, + "max_tries": self.max_tries, + } + + if use_default: + default_context = {"ti": self, **additional_context} + jinja_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), autoescape=True + ) + subject = jinja_env.from_string(default_subject).render(**default_context) + html_content = jinja_env.from_string(default_html_content).render(**default_context) + html_content_err = jinja_env.from_string(default_html_content_err).render(**default_context) + + else: + from airflow.sdk.definitions._internal.templater import SandboxedEnvironment + from airflow.utils.context import context_merge + + if TYPE_CHECKING: + assert self.task + + # Use the DAG's get_template_env() to set force_sandboxed. Don't add + # the flag to the function on task object -- that function can be + # overridden, and adding a flag breaks backward compatibility. + dag = self.task.get_dag() + if dag: + jinja_env = dag.get_template_env(force_sandboxed=True) + else: + jinja_env = SandboxedEnvironment(cache_size=0) + jinja_context = self.get_template_context() + context_merge(jinja_context, additional_context) + + def render(key: str, content: str) -> str: + if conf.has_option("email", key): + path = conf.get_mandatory_value("email", key) + try: + with open(path) as f: + content = f.read() + except FileNotFoundError: + log.warning("Could not find email template file '%s'. Using defaults...", path) Review Comment: ## Clear-text logging of sensitive information This expression logs [sensitive data (secret)](1) as clear text. This expression logs [sensitive data (secret)](2) as clear text. [Show more details](https://github.com/apache/airflow/security/code-scanning/466) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@airflow.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org