---
title: Do Not Allow SSH Environment Options
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: Docs > Datadog Security > OOTB Rules > Do Not Allow SSH Environment Options
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# Do Not Allow SSH Environment Options
 
## Description{% #description %}

Ensure that users are not able to override environment variables of the SSH daemon.

The default SSH configuration disables environment processing. The appropriate configuration is used if no value is set for `PermitUserEnvironment`.

To explicitly disable Environment options, add or correct the following `/etc/ssh/sshd_config.d/00-complianceascode-hardening.conf`:

```
PermitUserEnvironment no
```

## Rationale{% #rationale %}

SSH environment options potentially allow users to bypass access restriction in some configurations.

## Remediation{% #remediation %}

### Shell script{% #shell-script %}

The following script can be run on the host to remediate the issue.

```bash
#!/bin/bash

# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}' 'linux-base' 2>/dev/null | grep -q '^installed$'; then

mkdir -p /etc/ssh/sshd_config.d
chmod 0700 /etc/ssh/sshd_config.d
touch /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
chmod 0600 /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
LC_ALL=C sed -i "/^\s*PermitUserEnvironment\s\+/Id" "/etc/ssh/sshd_config"
LC_ALL=C sed -i "/^\s*PermitUserEnvironment\s\+/Id" "/etc/ssh/sshd_config.d"/*.conf
# sshd reads /etc/ssh/sshd_config.d through an Include line of /etc/ssh/sshd_config.
if grep -Eiqs '^\s*Include\s+/etc/ssh/sshd_config\.d/\*\.conf' /etc/ssh/sshd_config; then
    if [ -e "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf" ] ; then
        LC_ALL=C sed -i "/^\s*PermitUserEnvironment\s\+/Id" "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"
    else
        touch "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"
        chmod 0644 "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"

    cp "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf" "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf.bak"
    # Insert at the beginning of the file
    printf '%s\n' "PermitUserEnvironment no" > "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"
    cat "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf.bak" >> "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf.bak"
else
    if [ -e "/etc/ssh/sshd_config" ] ; then
        LC_ALL=C sed -i "/^\s*PermitUserEnvironment\s\+/Id" "/etc/ssh/sshd_config"
    else
        touch "/etc/ssh/sshd_config"
        chmod 0600 "/etc/ssh/sshd_config"
    fi
    # make sure file has newline at the end
    sed -i -e '$a\' "/etc/ssh/sshd_config"

    cp "/etc/ssh/sshd_config" "/etc/ssh/sshd_config.bak"
    # Insert at the beginning of the file
    printf '%s\n' "PermitUserEnvironment no" > "/etc/ssh/sshd_config"
    cat "/etc/ssh/sshd_config.bak" >> "/etc/ssh/sshd_config"
    # Clean up after ourselves.
    rm "/etc/ssh/sshd_config.bak"
fi

else
    >&2 echo 'Remediation is not applicable, nothing was done'
fi
```

### Ansible playbook{% #ansible-playbook %}

The following playbook can be run with Ansible to remediate the issue.

```go
- name: Gather the package facts
  package_facts:
    manager: auto
  tags:
  - CJIS-5.5.6
  - DISA-STIG-UBTU-22-255025
  - NIST-800-53-AC-17(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - PCI-DSS-Req-2.2.4
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sshd_do_not_permit_user_env

- name: Do Not Allow SSH Environment Options - Check if /etc/ssh/sshd_config includes
    /etc/ssh/sshd_config.d
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: (?i)^\s*Include\s+/etc/ssh/sshd_config\.d/\*\.conf
    state: absent
  check_mode: true
  changed_when: false
  failed_when: false
  register: _sshd_config_includes_config_dir
  when: '"linux-base" in ansible_facts.packages'
  tags:
  - CJIS-5.5.6
  - DISA-STIG-UBTU-22-255025
  - NIST-800-53-AC-17(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - PCI-DSS-Req-2.2.4
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sshd_do_not_permit_user_env

- name: Do Not Allow SSH Environment Options - Set the parameter PermitUserEnvironment
    in /etc/ssh/sshd_config.d
  block:

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured in /etc/ssh/sshd_config
    ansible.builtin.lineinfile:
      path: /etc/ssh/sshd_config
      regexp: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
      state: absent
    check_mode: true
    changed_when: false
    register: _config_file_has_parameter

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured in /etc/ssh/sshd_config.d
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
      patterns: '*.conf'
    register: _config_dir_has_parameter

  - name: Do Not Allow SSH Environment Options - Count the lines that configure the
      parameter PermitUserEnvironment in /etc/ssh/sshd_config.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
      state: absent
    check_mode: true
    changed_when: false
    loop: '{{ _config_dir_has_parameter.files }}'
    register: _config_dir_parameter_lines

  - name: Do Not Allow SSH Environment Options - Check if /etc/ssh/sshd_config exists
    ansible.builtin.stat:
      path: /etc/ssh/sshd_config
    register: _config_file_exists

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured correctly in /etc/ssh/sshd_config
    ansible.builtin.lineinfile:
      path: /etc/ssh/sshd_config
      regexp: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+no$
      state: absent
    check_mode: true
    changed_when: false
    register: _config_file_correctly
    when: _config_file_exists.stat.exists

  - name: Do Not Allow SSH Environment Options - Check if the parameter PermitUserEnvironment
      is configured correctly in /etc/ssh/sshd_config.d
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config.d
      contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+no$
      patterns: '*.conf'
    register: _config_dir_correctly

  - name: Do Not Allow SSH Environment Options
    block:

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        mode: '0600'
        state: absent

    - name: Check if /etc/ssh/sshd_config.d exists
      ansible.builtin.stat:
        path: /etc/ssh/sshd_config.d
      register: _etc_ssh_sshd_config_d_exists

    - name: Check if the parameter PermitUserEnvironment is present in /etc/ssh/sshd_config.d
      ansible.builtin.find:
        paths: /etc/ssh/sshd_config.d
        recurse: 'yes'
        follow: 'no'
        contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        patterns: '*.conf'
      register: _etc_ssh_sshd_config_d_has_parameter
      when: _etc_ssh_sshd_config_d_exists.stat.isdir is defined and _etc_ssh_sshd_config_d_exists.stat.isdir

    - name: Remove parameter from files in /etc/ssh/sshd_config.d
      ansible.builtin.lineinfile:
        path: '{{ item.path }}'
        create: false
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        mode: '0600'
        state: absent
      with_items: '{{ _etc_ssh_sshd_config_d_has_parameter.files | default([]) }}'
      when: _etc_ssh_sshd_config_d_has_parameter.matched > 0

    - name: Insert correct line to /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
        create: true
        regexp: (?i)(?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
        mode: '0600'
        line: PermitUserEnvironment no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
    when:
    - _config_file_correctly is not skipped
    - (_config_file_correctly.found == 0 and _config_dir_correctly.matched == 0) or
      ((_config_file_has_parameter.found | int) + (_config_dir_parameter_lines.results
      | map(attribute='found') | map('int') | sum)) != 1

  - name: Do Not Allow SSH Environment Options - set file mode for /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
    ansible.builtin.file:
      path: /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
      mode: '0600'
      state: touch
      modification_time: preserve
      access_time: preserve
  when:
  - '"linux-base" in ansible_facts.packages'
  - (_sshd_config_includes_config_dir.found | default(0) | int) > 0
  tags:
  - CJIS-5.5.6
  - DISA-STIG-UBTU-22-255025
  - NIST-800-53-AC-17(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - PCI-DSS-Req-2.2.4
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sshd_do_not_permit_user_env

- name: Do Not Allow SSH Environment Options - Set the parameter PermitUserEnvironment
    in /etc/ssh/sshd_config
  block:

  - name: Do Not Allow SSH Environment Options - Find the files of /etc/ssh/sshd_config.d
      that set the parameter PermitUserEnvironment
    ansible.builtin.find:
      paths:
      - /etc/ssh/sshd_config.d
      patterns: '*.conf'
      contains: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
    register: _sshd_config_dir_sets_parameter

  - name: Do Not Allow SSH Environment Options - Remove the parameter PermitUserEnvironment
      from the files of /etc/ssh/sshd_config.d
    ansible.builtin.lineinfile:
      path: '{{ item.path }}'
      regexp: (?i)^\s*{{ "PermitUserEnvironment"| regex_escape }}\s+
      state: absent
    loop: '{{ _sshd_config_dir_sets_parameter.files }}'

  - name: Do Not Allow SSH Environment Options
    block:

    - name: Check for duplicate values
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitUserEnvironment\s+
        mode: '0600'
        state: absent
      check_mode: true
      changed_when: false
      register: dupes

    - name: Deduplicate values from /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitUserEnvironment\s+
        mode: '0600'
        state: absent
      when: dupes.found is defined and dupes.found > 1

    - name: Insert correct line to /etc/ssh/sshd_config
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        create: true
        regexp: (?i)(?i)^\s*PermitUserEnvironment\s+
        mode: '0600'
        line: PermitUserEnvironment no
        state: present
        insertbefore: BOF
        validate: /usr/sbin/sshd -t -f %s
  when:
  - '"linux-base" in ansible_facts.packages'
  - (_sshd_config_includes_config_dir.found | default(0) | int) == 0
  tags:
  - CJIS-5.5.6
  - DISA-STIG-UBTU-22-255025
  - NIST-800-53-AC-17(a)
  - NIST-800-53-CM-6(a)
  - NIST-800-53-CM-7(a)
  - NIST-800-53-CM-7(b)
  - PCI-DSS-Req-2.2.4
  - PCI-DSSv4-2.2
  - PCI-DSSv4-2.2.6
  - low_complexity
  - low_disruption
  - medium_severity
  - no_reboot_needed
  - restrict_strategy
  - sshd_do_not_permit_user_env
```
