Repository: starship/starship
File: src/modules/aws.rs (Rust)

Code before:
    let credentials = get_creds(context, aws_creds);

    let empty_section = ini::Properties::new();
    // We use the aws_profile here because `get_profile_config()` treats None
    // as "special" and falls back to the "[default]"; otherwise this tries
    // to look up "[profile default]" which doesn't exist
    let config_section = get_profile_config(config, aws_profile).or(Some(&empty_section))?;

    let default_profile = "default".to_string();
    let credential_profile = aws_profile.unwrap_or(&default_profile);

    // credentials are optional; if we can't find the credential file,
    // we work with just the config and treat the credential section as
    // empty
    let credential_section = match credentials {
        Some(credentials) => credentials
            .section(Some(credential_profile))
            .or(Some(&empty_section))?,
        None => &empty_section,
    };

    Some(
        config_section.contains_key("credential_process")
            || config_section.contains_key("sso_start_url")
            || credential_section.contains_key("credential_process")
            || credential_section.contains_key("sso_start_url"),
    )
}

fn has_defined_credentials(
    context: &Context,
    aws_profile: &Option<Profile>,
    aws_creds: &AwsCredsFile,
) -> Option<bool> {
    let valid_env_vars = [
        "AWS_ACCESS_KEY_ID",
        "AWS_SECRET_ACCESS_KEY",
        "AWS_SESSION_TOKEN",
    ];

    // accept if set through environment variable
    if valid_env_vars
        .iter()
        .any(|env_var| context.get_env(env_var).is_some())
    {
        return Some(true);
    }

    let creds = get_creds(context, aws_creds)?;
    let section = get_profile_creds(creds, aws_profile)?;
    Some(section.contains_key("aws_access_key_id"))

Review comment (security):
`has_credential_process_or_sso` has been mostly concerned with the config file and `has_defined_credentials` with the credentials file. Given that, please move the `has_defined_credentials` into `has_defined_credentials` or change this function to first do the check on the config file and either return on success, or follow up with the credentials file check.

Code after:
    let credentials = get_creds(context, aws_creds);

    let empty_section = ini::Properties::new();
    // We use the aws_profile here because `get_profile_config()` treats None
    // as "special" and falls back to the "[default]"; otherwise this tries
    // to look up "[profile default]" which doesn't exist
    let config_section = get_profile_config(config, aws_profile).or(Some(&empty_section))?;

    let credential_section = match credentials {
        Some(credentials) => get_profile_creds(credentials, aws_profile),
        None => None,
    };

    Some(
        config_section.contains_key("credential_process")
            || config_section.contains_key("sso_start_url")
            || credential_section?.contains_key("credential_process")
            || credential_section?.contains_key("sso_start_url"),
    )
}

fn has_defined_credentials(
    context: &Context,
    aws_profile: Option<&Profile>,
    aws_creds: &AwsCredsFile,
) -> Option<bool> {
    let valid_env_vars = [
        "AWS_ACCESS_KEY_ID",
        "AWS_SECRET_ACCESS_KEY",
        "AWS_SESSION_TOKEN",
    ];

    // accept if set through environment variable
    if valid_env_vars
        .iter()
        .any(|env_var| context.get_env(env_var).is_some())
    {
        return Some(true);
    }

    let creds = get_creds(context, aws_creds)?;
    let section = get_profile_creds(creds, aws_profile)?;
    Some(section.contains_key("aws_access_key_id"))
}

pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
    let mut module = context.new_module("aws");
    let config: AwsConfig = AwsConfig::try_load(module.config);

    let aws_config = OnceCell::new();
    let aws_creds = OnceCell::new();