Skip to content

known_hosts: Add full key validation - #85723

Draft
GideonBear wants to merge 1 commit into
ansible:develfrom
GideonBear:fix-known-hosts-footgun
Draft

known_hosts: Add full key validation#85723
GideonBear wants to merge 1 commit into
ansible:develfrom
GideonBear:fix-known-hosts-footgun

Conversation

@GideonBear

Copy link
Copy Markdown
SUMMARY

When the key parameter to known_hosts contains a newline (\n or \r to be thorough), fail the module.
Keys may not contain newlines, and only a single key may be supplied. A newline in the key parameter may indicate the user is attempting to supply multiple keys. Example of faulty usage:

- name: Get host key
  ansible.builtin.command: ssh-keyscan -q 172.17.0.1
  changed_when: false
  register: host_key

- name: Add host key to known_hosts
  ansible.builtin.known_hosts:
    path: "/whatever/known_hosts"
    name: 172.17.0.1
    key: "{{ host_key.stdout }}"  # Note that the output of ssh-keyscan contains multiple keys by default
    state: present

This previously silently worked in some cases, and had silently incorrect behavior in others. This is due to any trailing parts of the key being ignored, and being split on any whitespace (including newlines).
Now, this fails with Argument 'key' contains newlines. This module only accepts a single key..

I added an integration test for this.

Concerns/questions:

  • Am I correct in assuming a key may never contain a newline?
  • This is technically a breaking change, but only breaks already silently broken tasks.
  • Right now, the check is implemented in normalize_known_hosts_key, which also handles normalizing for the output of ssh-keygen. Since the key that's passed into there (l) is .split('\n') it can never contain a newline, and this is thus safe to do; but it might have benefit to do separate this anyway.
  • Improvements to the error message are welcome!

Closes #85637

ISSUE TYPE
  • Bugfix Pull Request

@ansibot ansibot added bug This issue/PR relates to a bug. needs_triage Needs a first human triage before being processed. module This issue/PR relates to a module. has_issue labels Aug 23, 2025
@s-hertel s-hertel removed the needs_triage Needs a first human triage before being processed. label Aug 26, 2025
"""
key = key.strip() # trim trailing newline
if "\n" in key or "\r" in key:
module.fail_json(msg="Argument 'key' contains newlines. This module only accepts a single key.")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just rstrip \r from the key after split, there is no case in which \n should make it to this point as we split on it before calling the function. No need for errors, \r is invalid in the middle of the key but it is probably part of the line break if it was saved from a Windows machine, that case we can optimize for, any other case should fail on key/file validation

@GideonBear GideonBear Aug 26, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we split on key before calling normalize_known_hosts_key? Do you mean line 259? That's only on the output of ssh-keygen, not the module argument key.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, mixed those, still, this is not something we should validate this way, we either do full 'correct key format' validation or leave as is

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not something we should validate this way, we either do full 'correct key format' validation or leave as is

Sure, I'm up for implementing full validation. But out of curiosity, why? What's wrong with a simple check for a footgun (specifically passing multiple keys) if you know it's never valid?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is piecemeal, we would keep adding each case as it appears and make a tangle of the code, while a full format validation should cover all cases off the bat in a much cleaner way

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair!
I'll mark this as draft and start working on full validation. I will also take a look at other issues to see if they could be solved at once.

@GideonBear
GideonBear marked this pull request as draft August 26, 2025 16:28
@GideonBear GideonBear changed the title known_hosts: Fail when key contains newlines known_hosts: Add full key validation Aug 26, 2025
Comment on lines +313 to +314
if "\n" in key or "\r" in key:
module.fail_json(msg="Argument 'key' contains newlines. This module only accepts a single key.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not do this in the function called sanity_check instead? It's already responsible for validating some aspects of the key, and then we wouldn't need to thread the module through this function.

+    if len(key.splitlines()) > 1:
+        module.fail_json(msg="Argument 'key' contains newlines. This module only accepts a single key.")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I missed that. But I assume that doesn't invalidate @bcoca's criticism?

@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Sep 5, 2025
@ansibot ansibot added the needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html label Oct 3, 2025
@ansibot ansibot added the stale_pr This PR has not been pushed to for more than one year. label Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug This issue/PR relates to a bug. has_issue module This issue/PR relates to a module. needs_rebase https://docs.ansible.com/ansible/devel/dev_guide/developing_rebasing.html stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. stale_pr This PR has not been pushed to for more than one year.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ansible.builtin.known_hosts: Footgun when supplying multiple keys

4 participants