Back to Checks
aws

Glue ETL job has no secrets in default arguments

glue_etl_jobs_no_secrets_in_arguments
Service: glueSeverity: critical
OfficialBuilt-inVerified
Categories:secrets
Resource Type:Other

AWS Glue ETL jobs are inspected for default arguments (DefaultArguments) that resemble secrets (keys, tokens, passwords).

Such values indicate sensitive data is stored directly in job arguments instead of being sourced securely from AWS Secrets Manager or Systems Manager Parameter Store.

Risk

Plaintext secrets in default arguments reduce confidentiality: values can be viewed in consoles, CLI output, and CloudTrail logs. Compromised credentials enable unauthorized AWS actions, data exfiltration, and lateral movement across the environment.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks glue_etl_jobs_no_secrets_in_arguments

Recommendation

Store secrets in AWS Secrets Manager or AWS Systems Manager Parameter Store and reference them by name or ARN in job arguments instead of embedding plaintext values. Enforce least privilege on the Glue job IAM role, rotate secrets regularly, and avoid logging or exporting argument values.

Remediation

CLI

aws glue update-job --job-name <job_name> --job-update '{"DefaultArguments":{"--secret_name":"{{resolve:secretsmanager:my-secret}}"}}'

Terraform

resource "aws_glue_job" "example" {
  name     = "<job_name>"
  role_arn = "<role_arn>"

  command {
    script_location = "s3://<bucket>/script.py"
  }

  default_arguments = {
    "--secret_name" = aws_secretsmanager_secret_version.example.secret_string  # Reference secret from Secrets Manager instead of plaintext
  }
}

NativeIaC

Resources:
  GlueJob:
    Type: AWS::Glue::Job
    Properties:
      Name: <job_name>
      Role: <role_arn>
      Command:
        Name: glueetl
        ScriptLocation: "s3://<bucket>/script.py"
      DefaultArguments:
        "--secret_name": !Sub "{{resolve:secretsmanager:${MySecret}}}"  # Reference secret from Secrets Manager instead of plaintext

Other

1Open the AWS Glue console and go to Jobs
2Select the job and click Edit
3Under Job parameters, identify any arguments containing sensitive values
4Store those values in AWS Secrets Manager or Systems Manager Parameter Store
5Update the job arguments to reference the secret by name or ARN instead of the plaintext value
6Save the job

Check Code

import json

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.lib.utils.utils import (
    SecretsScanError,
    annotate_verified_secrets,
    detect_secrets_scan_batch,
)
from prowler.providers.aws.services.glue.glue_client import glue_client


class glue_etl_jobs_no_secrets_in_arguments(Check):
    """Check if Glue ETL jobs have secrets in their default arguments.

    Scans the DefaultArguments of each Glue job for hardcoded credentials,
    tokens, passwords, and other sensitive values that should be stored in
    Secrets Manager or Parameter Store instead.
    """

    def execute(self):
        findings = []
        secrets_ignore_patterns = glue_client.audit_config.get(
            "secrets_ignore_patterns", []
        )
        validate = glue_client.audit_config.get("secrets_validate", False)
        jobs = list(glue_client.jobs)

        # Collect every default argument across all jobs and scan them in batched
        # Kingfisher invocations instead of one subprocess per argument. Findings
        # are keyed by (job index, argument name).
        def payloads():
            for job_index, job in enumerate(jobs):
                if job.arguments:
                    for arg_name, arg_value in job.arguments.items():
                        yield (job_index, arg_name), json.dumps({arg_name: arg_value})

        scan_error = None
        try:
            batch_results = detect_secrets_scan_batch(
                payloads(), excluded_secrets=secrets_ignore_patterns, validate=validate
            )
        except SecretsScanError as error:
            batch_results = {}
            scan_error = error

        for job_index, job in enumerate(jobs):
            report = Check_Report_AWS(metadata=self.metadata(), resource=job)
            report.status = "PASS"
            report.status_extended = (
                f"No secrets found in Glue job {job.name} default arguments."
            )

            if job.arguments and scan_error:
                report.status = "MANUAL"
                report.status_extended = (
                    f"Could not scan Glue job {job.name} default arguments for "
                    f"secrets: {scan_error}; manual review is required."
                )
                findings.append(report)
                continue

            if job.arguments:
                secrets_found = []
                all_secrets = []
                for arg_name in job.arguments:
                    detect_secrets_output = batch_results.get((job_index, arg_name))
                    if detect_secrets_output:
                        all_secrets.extend(detect_secrets_output)
                        secrets_found.extend(
                            [
                                f"{secret['type']} in argument {arg_name}"
                                for secret in detect_secrets_output
                            ]
                        )

                if secrets_found:
                    report.status = "FAIL"
                    report.status_extended = f"Potential secrets found in Glue job {job.name} default arguments: {', '.join(secrets_found)}."
                    annotate_verified_secrets(report, all_secrets)

            findings.append(report)

        return findings