mirror of
https://github.com/ansible/ansible
synced 2026-06-19 07:35:52 +00:00
[stable-2.16] Fix CVE-2026-11332 - prevent role requirements from configuring git (#87074)
* Fix CVE-2026-11332 - prevent role requirements from configuring git (#87070) * Pass malformed role requirements as positional arguments to prevent arbitrary git configuration * Add test coverage, checking for specific errors and that git clone is always followed by -- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua> (cherry picked from commitedee59aa15) * Fix ansible-galaxy-role test isolating stderr (#87085) Follow up to #87070 to fix the test Fix ansible-galaxy-role test isolating stder Remove new feature to backport as-is (cherry picked from commitbebae770d3) --------- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
security_fixes:
|
||||
- ansible-galaxy install - Ensure role requirements are passed as positional arguments to :command:`git clone`. Previously, a malicious role author could inject arbitrary git configuration in role dependencies. (CVE-2026-11332)
|
||||
@@ -74,7 +74,7 @@ def scm_archive_resource(src, scm='git', name=None, version='HEAD', keep_scm_met
|
||||
elif scm == 'hg':
|
||||
clone_cmd.append('--insecure')
|
||||
|
||||
clone_cmd.extend([src, name])
|
||||
clone_cmd.extend(['--', src, name])
|
||||
|
||||
run_scm_cmd(clone_cmd, tempdir)
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
- vars:
|
||||
invalid_git_opts: '-ccore.sshCommand=sh -c "id > {{ remote_tmp_dir }}/role_exe"'
|
||||
# use SSH protocol to test core.sshCommand is not configured
|
||||
dummy_repo: git@github.com:ansible/nosuchrepo.git
|
||||
block:
|
||||
- name: Ensure git is installed
|
||||
package:
|
||||
name: git
|
||||
when: ansible_distribution not in ["MacOSX", "Alpine"]
|
||||
register: git_install
|
||||
|
||||
- name: Create invalid requirements file
|
||||
copy:
|
||||
dest: "{{ remote_tmp_dir }}/invalid-requirements.yml"
|
||||
content: |
|
||||
- src: {{ invalid_git_opts }}
|
||||
scm: git
|
||||
name: {{ dummy_repo }}
|
||||
- src: {{ dummy_repo }}
|
||||
scm: git
|
||||
name: {{ invalid_git_opts }}
|
||||
|
||||
- name: Attempt to install invalid role requirements
|
||||
command: ansible-galaxy install -r {{ remote_tmp_dir }}/invalid-requirements.yml --ignore-errors
|
||||
register: result
|
||||
environment:
|
||||
ANSIBLE_NOCOLOR: True
|
||||
ANSIBLE_FORCE_COLOR: False
|
||||
|
||||
- name: Validate git core.sshCommand did not run
|
||||
stat:
|
||||
path: "{{ remote_tmp_dir }}/role_exe"
|
||||
register: stat_result
|
||||
failed_when: stat_result.stat.exists
|
||||
|
||||
- name: Verify the invalid field is treated as a single positional argument (repo or dest)
|
||||
assert:
|
||||
that:
|
||||
- stderr is search(error1)
|
||||
- stderr is search(error2)
|
||||
- (stderr | regex_findall("git clone") | length) == (stderr | regex_findall("git clone --") | length) == 2
|
||||
vars:
|
||||
stderr: "{{ result.stderr | regex_replace('\\n', ' ') }}"
|
||||
error1: "repository '{{ invalid_git_opts }}' does not exist"
|
||||
error2: "Cloning into '{{ invalid_git_opts }}'"
|
||||
|
||||
always:
|
||||
- name: Uninstall git if it was installed
|
||||
package:
|
||||
name: git
|
||||
state: absent
|
||||
when: git_install is changed | default(false)
|
||||
@@ -70,3 +70,4 @@
|
||||
|
||||
- import_tasks: dir-traversal.yml
|
||||
- import_tasks: valid-role-symlinks.yml
|
||||
- import_tasks: git-config-injection.yml
|
||||
|
||||
Reference in New Issue
Block a user