Skip to content

ENG-8830 fix(network-ops): make certipy stdin confirmation uniform and hang-safe - #179

Merged
thomasqbrady merged 2 commits into
mainfrom
eng-8830-certipy-uniform-confirm
Oct 16, 2026
Merged

thomasqbrady merged 2 commits into
mainfrom
eng-8830-certipy-uniform-confirm

Conversation

@thomasqbrady

Copy link
Copy Markdown
Contributor

Summary

The certipy_* tools were inconsistent about answering certipy's interactive prompts. certipy_auth / certipy_cert / certipy_req (and the high-level certipy_request_certificate / certipy_certificate_auth helpers) piped "y" to stdin; certipy_account / certipy_ca / certipy_find / certipy_template passed input=None.

input=None leaves the child's stdin inherited, so when certipy prompts (e.g. "overwrite the saved PFX/ccache?") the tool blocks until the 20s command timeout and surfaces as a timeout failure rather than doing anything useful.

This makes every certipy_* tool default to the same confirmation through one documented _CONFIRM_INPUT constant, so stdin is always written and closed and no tool can hang on a prompt.

Why this shape

  • Kept the family-wide input: str | None parameter rather than switching to a confirm: bool, so certipy stays uniform with its siblings (impacket, bloodyad, coercion, krbrelayx), which all take input and guard the same prompt-hang this way.
  • An empty string falls back to the confirm default on purpose: execute() only writes-and-closes stdin for a truthy input, so forwarding "" would reopen the hang. Callers decline by passing an explicit answer like "n"; the docstrings say so.
  • The relay action is exempt — it's a streaming listener that never reads stdin.

Changes

  • tools/certipy.py: single _CONFIRM_INPUT default applied at every non-relay execute() call; removed the two hardcoded input="y"; uniform signatures; docstrings describe the default and how to override.
  • capability.yaml: 2.1.10 → 2.1.11 (behavior change to the public tool surface).
  • tests/test_tool_fixes.py: regression tests for the uniform default, explicit/empty overrides, and the relay exemption.

Testing

  • pytest tests/test_tool_fixes.py — 84 passed.
  • pre-commit (ruff, ruff-format, gitleaks) clean; dreadnode capability validate passes.
  • Verified out-of-band against a real prompting subprocess: with an inherited blocking stdin, input=None hangs to the timeout while the new "y" default returns immediately.

…fe (ENG-8830)

The certipy_* tools were split on auto-answering certipy's interactive
prompts: certipy_auth/cert/req (and the high-level request/auth helpers)
piped "y" to stdin, while certipy_account/ca/find/template passed input=None.
The None path leaves stdin inherited, so when certipy prompts (e.g. overwrite
a saved PFX/ccache) the tool blocks until the 20s command timeout and surfaces
as a timeout failure.

Make every certipy_* tool default to the same confirmation via a single,
documented _CONFIRM_INPUT constant, so stdin is always written and closed and
no tool can hang on a prompt. Behavior stays overridable through the existing
family-wide `input` parameter (pass "n" to decline); an empty string falls back
to the confirm default because execute() only closes stdin for a truthy input.
The relay action is exempt — it is a streaming listener that never reads stdin.

Bumps network-ops to 2.1.11 and adds regression tests covering the uniform
default, explicit/empty overrides, and the relay exemption.

@mkultraWasHere mkultraWasHere left a comment

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.

nice

…orm-confirm

# Conflicts:
#	capabilities/network-ops/capability.yaml
@thomasqbrady
thomasqbrady merged commit f1cffac into main Oct 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants