Commit Graph
751 Commits
Author SHA1 Message Date
Justin BollingerandClaude 24e574bc8e fix(ui): print picker grids once and report rejected menu keys
The re-prompt loops repainted the whole multicolumn wordlist grid after every
typo, burying the error message under dozens of entries. Hoist the grid and the
p/q legend out of the loop so only the prompt repeats.

ollama_attack's loop also fell through to a silent redraw on an unrecognised
key, leaving no way to tell a rejected key from a repainted prompt.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:33:11 -04:00
Justin BollingerandClaude 07ca6ba7e3 fix(ui): route ollama/omen submenus through interactive_menu; re-prompt pickers on invalid input
- ollama_attack: convert generation-mode menu to interactive_menu with
  dynamic items list (option 3 only present when cracked file exists);
  cancel via 99 or Escape; re-prompts in a while loop
- omen_attack: convert existing-model menu to interactive_menu; cancel
  via 99 or Escape (replaces hard-coded "3. Cancel"); re-prompts in loop
- _omen_pick_training_wordlist: replace abort-on-invalid with re-prompt
  loop; add explicit 'q' cancel key so users can exit without being
  trapped; callers already handle None correctly
- _markov_pick_training_source: same re-prompt-loop + 'q' cancel fix;
  callers already handle None correctly
- Update all affected tests to patch interactive_menu at
  hate_crack.attacks.interactive_menu (module-level import path) and
  drive follow-up prompts via builtins.input
- Add new tests: arrow-menu reach, Escape/99 cancel, re-prompt loop
  coverage for both pickers, and conditional option-3 key presence

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:31:04 -04:00
Justin BollingerandClaude 39e0dd956a feat(llm): add cracked-password generation mode to the LLM attack
Adds a third LLM Attack generation mode ("cracked") that samples the
plaintexts already recovered this session from <hashfile>.out and asks the
model to infer the target organization's password conventions and emit new
candidates in the same style.

- llm.py: new _CRACKED_PROMPT (offensive candidate generation, explicitly
  not the denylist-oriented _WORDLIST_PROMPT), a _PROMPTS mode->prompt map,
  and a "cracked" branch in _build_request that tells the model not to
  repeat already-cracked passwords.
- main.py: extract the wordlist sampling logic into the shared module-level
  helper _sample_plaintext_file(path, cap, source_label) and call it from
  both the wordlist and cracked branches of hcatOllama; guard missing and
  empty .out files.
- attacks.py: offer mode 3 only when <hashfile>.out exists and is non-empty
  (matching _markov_pick_training_source), with a clear message otherwise.
- README: document the three modes and the widened ollamaMaxSampleLines
  scope.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:18:52 -04:00
Justin BollingerandClaude 86fac864a0 fix(ui): clear spinner line after joining its thread
Clearing before the join left a race in the normal path: a spinner thread
sitting just past its stop_event.is_set() check could repaint the line after
the erase, leaving the terminal dirty. Join first so no further writes are
possible, and nest the erase in a finally so an interrupted join (hate_crack
raises DoubleInterrupt on a second SIGINT) still leaves a clean line.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:13:23 -04:00
Justin BollingerandClaude 142c1fc99f refactor: address code-quality review findings on ui-polish branch
- Remove review-artifact "Defect 2" comment in main.py:2076; replace with
  accurate description of the invalid-cap fallback.  Same label removed from
  the test section header in test_ollama_wordlist_sampling.py.
- Lift nested _usable helper to module-level _usable_plaintext in main.py,
  placed alongside the other private wordlist helpers after _wordlist_path.
  Add six direct unit tests covering blank, whitespace, plain, hash:pw,
  multi-colon, and empty-plaintext cases.
- Move spinner line-clear before thread.join() in progress.py so the terminal
  is cleaned up even if join() is interrupted by a DoubleInterrupt/second Ctrl-C.
  Add test_tty_clears_line_even_if_join_raises to cover this path.
- Replace time.sleep-based elapsed-counter test with a deterministic version
  that patches time.monotonic; assert on actual rendered format with r"\d+s".
  Drop the misleading 0.05s sleep in test_tty_clears_line_on_exit (shorter
  than one tick, so no frame was ever guaranteed).
- Add missing ollama* keys to hate_crack/config.json.example (package-data
  copy); root config.json.example already had them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 18:08:11 -04:00
Justin BollingerandClaude fef606dbf4 fix(llm): fix stride sampling exactness, zero-cap crash, and test quality
- Defect 1 (main.py): Replace floating-point stride loop with exact
  floor(k * total / cap) index formula so sampling always returns
  EXACTLY cap items for any 1 <= cap <= total_usable, including the
  stride < 2 regime where the old approach returned cap-1 items.

- Defect 2 (main.py): Validate ollamaMaxSampleLines before computing
  the stride; values <= 0 are nonsensical and fall back to 500
  (same as the default) rather than raising ZeroDivisionError.

- Defect 3 (test_progress_spinner.py): Rewrite test_non_tty_no_extra_thread
  to patch threading.Thread and assert it was never called, so the test
  actually fails when the spinner starts a thread in the non-TTY path.

- Defect 4 (test_progress_spinner.py): Simplify test_non_tty_prints_message
  to use monkeypatch.setattr instead of the dead mock.patch.object +
  manual assign/restore layering; removes two # type: ignore comments.

- docs(README.md): Document ollamaMaxSampleLines alongside ollamaNumCtx /
  ollamaTimeout in the Ollama Configuration section.

- tests: Add boundary-case tests for stride < 2 (total==cap, total==cap+1,
  total=3/cap=2, cap=1) and zero-cap fallback; make
  test_ollama_max_sample_lines_default exercise behaviour rather than
  the ambient config value.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:57:09 -04:00
Justin BollingerandClaude e5e1107359 fix(llm): add spinner during Ollama generation and cap wordlist sample
Defect 1 — hcatOllama showed a plain print then blocked silently for
up to 300 s while waiting for the LLM.  A new generic context manager
`hate_crack/progress.py::spinner()` now runs a daemon thread that
repaints a single line with a frame + elapsed-seconds counter every
~120 ms.  TTY guard ensures non-TTY/test environments get a single
plain print instead of ANSI control characters.  The line is erased
with \033[2K\r on exit (normal and exceptional).

Defect 2 — the wordlist path materialised every line in memory and
built a prompt that could massively overflow ollamaNumCtx on large
wordlists.  The path now does a two-pass evenly-spaced sample: pass 1
counts usable lines, pass 2 stride-selects up to `ollamaMaxSampleLines`
(default 500, new config key) spread across the full file.  When no
capping occurs the message reads "Loaded N passwords"; when capping
occurs it reads "Sampled N of M passwords".

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:49:24 -04:00
Justin BollingerandClaude e88315dfb9 build: pin local uv Python to 3.13
requires-python is ">=3.13", so a fresh worktree's "uv sync --dev" picks the
newest interpreter on the box - currently CPython 3.15.0a7 - and the build
fails because pyo3 0.26 (via jiter/fastuuid/pydantic-core) does not support
3.15 yet:

    error: failed to run custom build command for `pyo3-ffi v0.26.0`

CI already pins 3.13 via setup-uv, so this only bit local worktrees. Pinning
matches CI and leaves requires-python alone.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:39:20 -04:00
Justin BollingerandClaude 549c5a0a64 fix(llm): bound Ollama requests with a configurable timeout
The Atomic Agents client was built with no timeout, so an Ollama server that
accepted the TCP connection but never replied (most commonly a large model still
loading into VRAM) left the CLI blocked in agent.run() forever. The caller's
`except Exception` handler only ever fired on connection-refused.

- llm.generate_candidates() takes a `timeout` parameter (default
  DEFAULT_TIMEOUT_SECONDS = 300.0) and forwards it to the OpenAI client.
- openai.APITimeoutError is translated into a new domain-level
  llm.LLMTimeoutError so main.py need not import openai itself, keeping the
  atomic-agents/instructor dependency isolated to llm.py as documented.
- hcatOllama passes the new `ollamaTimeout` config value and prints
  timeout-specific guidance (elapsed seconds, VRAM-loading hint, the setting to
  raise) instead of the misleading "ensure Ollama is running" message.
- Documented `ollamaTimeout` in config.json.example and README.

Also closes two test gaps: the defensive `except ValueError` handler in
hcatOllama now has coverage, and the misleadingly-named `test_unknown_mode_raises`
is split into explicit unit tests of _build_request's mode validation. Ticked the
completed steps in the LLM Atomic Agents plan doc.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:17:58 -04:00
Justin BollingerandClaude e49be6122a build(deps): declare instructor, openai, and pydantic explicitly
hate_crack/llm.py imports all three directly, but only atomic-agents was
declared -- they were available purely as transitive deps. A future
atomic-agents release that loosened its coupling to any of them would make
`uv sync` silently omit it and break `import hate_crack.llm` at runtime.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 17:07:19 -04:00
Justin BollingerandClaude 81577ae060 Merge branch 'main' into feature/llm-atomic-agents
Conflicts resolved:
- CHANGELOG.md: kept both [2.12.0] (branch) and [2.11.4] (main), newest first
- pyproject.toml: kept main's tighter version pins (click>=8.4.2, requests>=2.34.2,
  packaging>=26.2, pytest-cov==7.1.0) and the branch's atomic-agents>=2.0.0 dep

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 16:57:24 -04:00
Justin BollingerandGitHub a99b36369a Merge pull request #125 from trustedsec/dependabot/uv/click-gte-8.4.2
chore(deps): update click requirement from >=8.0.0 to >=8.4.2
2026-07-24 16:51:02 -04:00
Justin BollingerandGitHub 9674f991b3 Merge pull request #124 from trustedsec/dependabot/uv/requests-gte-2.34.2
chore(deps): update requests requirement from >=2.31.0 to >=2.34.2
2026-07-24 16:50:47 -04:00
Justin BollingerandGitHub 8906636ec4 Merge pull request #123 from trustedsec/dependabot/uv/packaging-gte-26.2
chore(deps): update packaging requirement from >=21.0 to >=26.2
2026-07-24 16:50:31 -04:00
Justin BollingerandGitHub 6a7a2a5f47 Merge pull request #122 from trustedsec/dependabot/uv/pytest-cov-7.1.0
chore(deps-dev): bump pytest-cov from 7.0.0 to 7.1.0
2026-07-24 16:50:15 -04:00
Justin BollingerandGitHub cf6c9c2f8b Merge pull request #121 from trustedsec/dependabot/github_actions/softprops/action-gh-release-3.0.2
chore(ci): bump softprops/action-gh-release from 2.6.2 to 3.0.2
2026-07-24 16:49:55 -04:00
dependabot[bot]andGitHub b385f391a4 chore(deps): update click requirement from >=8.0.0 to >=8.4.2
Updates the requirements on [click](https://github.com/pallets/click) to permit the latest version.
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.md)
- [Commits](https://github.com/pallets/click/compare/8.0.0...8.4.2)

---
updated-dependencies:
- dependency-name: click
  dependency-version: 8.4.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 20:48:13 +00:00
dependabot[bot]andGitHub 9297670980 chore(deps): update requests requirement from >=2.31.0 to >=2.34.2
Updates the requirements on [requests](https://github.com/psf/requests) to permit the latest version.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.31.0...v2.34.2)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.34.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 20:48:08 +00:00
dependabot[bot]andGitHub 14c332d2b1 chore(deps): update packaging requirement from >=21.0 to >=26.2
Updates the requirements on [packaging](https://github.com/pypa/packaging) to permit the latest version.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/21.0...26.2)

---
updated-dependencies:
- dependency-name: packaging
  dependency-version: '26.2'
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 20:48:07 +00:00
dependabot[bot]andGitHub 415255e1ec chore(deps-dev): bump pytest-cov from 7.0.0 to 7.1.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 7.0.0 to 7.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v7.0.0...v7.1.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 7.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 20:48:01 +00:00
dependabot[bot]andGitHub ba6bb999bb chore(ci): bump softprops/action-gh-release from 2.6.2 to 3.0.2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.6.2 to 3.0.2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/3bb12739c298aeb8a4eeaf626c5b8d85266b0e65...3d0d9888cb7fd7b750713d6e236d1fcb99157228)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-24 20:47:32 +00:00
Justin BollingerandGitHub ca1eea6d5e Merge pull request #120 from trustedsec/fix/ci-hardening
fix(ci): add test CI, repair auto-tag releases, harden action pins (2.11.4)
v2.11.4
2026-07-24 16:47:01 -04:00
Justin BollingerandClaude 665c8ab47c fix(ci): add test CI, repair auto-tag releases, harden action pins (2.11.4)
The repo had no CI: ruff/ty/pytest ran only in local prek pre-push hooks, so
a commit pushed without hooks installed reached main unvalidated -- and
auto-tag would then cut a release from it. Adds ci.yml (ruff, ty, pytest on
3.13) and gates tagging on it.

Auto-tagged versions also never produced a release. The tag is pushed with
the default GITHUB_TOKEN, and GitHub suppresses workflow triggers for
GITHUB_TOKEN-created events, so the tag-triggered release.yml never fired --
v2.11.3 was tagged with no release. auto-tag now creates the release itself,
idempotently; release.yml stays as the manual-tag path.

Also fixes version logic that matched the `!` breaking marker but only ever
bumped minor (and never saw BREAKING CHANGE: footers, since only subjects
were inspected), serializes concurrent merges that both computed the same
tag, and repins softprops/action-gh-release from an arbitrary master commit
to v2.6.2 with all workflows on one actions/checkout version.

Clears the pre-existing ty error in notify/tailer.py that would have made
the new type-check step red: _read_new_lines read self._file_pos
(int | None) while its only None-guard lived in the caller, so the position
is passed in explicitly as an int. Behavior unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 16:39:59 -04:00
Justin BollingerandClaude Opus 4.8 f424783eb2 style(llm): drop vestigial global hcatProcess in hcatOllama
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:15:10 -04:00
Justin BollingerandClaude Opus 4.8 519d395708 docs(llm): document Atomic Agents refactor, new default model, wordlist mode (2.12.0)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:11:26 -04:00
Justin BollingerandClaude Opus 4.8 bcea02b2e7 test(llm): cover wordlist-mode abort when no wordlist picked
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:10:39 -04:00
Justin BollingerandClaude Sonnet 4.6 a4da571ab4 feat(llm): add wordlist (denylist) mode to LLM attack menu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 12:08:20 -04:00
Justin BollingerandClaude Opus 4.8 d6da721414 feat(llm): default Ollama model to qwen2.5:32b for structured output
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:06:29 -04:00
Justin BollingerandClaude Opus 4.8 93960e2d58 test(llm): cover per-rule hashcat loop and hash:password stripping
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 12:06:12 -04:00
Justin BollingerandClaude Sonnet 4.6 4df1121051 refactor(llm): delegate candidate generation to llm module; drop auto-pull
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 11:59:04 -04:00
Justin BollingerandClaude Opus 4.8 9dd6ad746f style(llm): drop noise Any annotation on agent result
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 11:52:32 -04:00
Justin BollingerandClaude Sonnet 4.6 a57a4165f1 refactor(llm): validate AgentConfig in prod; spec-mock the client in tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 11:50:19 -04:00
Justin BollingerandClaude Sonnet 4.6 1cc71abfef feat(llm): structured candidate generation module via Atomic Agents
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-24 11:48:19 -04:00
Justin Bollinger 66e6d593c4 build(deps): add atomic-agents for structured LLM candidate generation 2026-07-24 11:45:24 -04:00
Justin BollingerandGitHub a0dc56ce08 Merge pull request #117 from trustedsec/fix/cleanup-rules-mode
fix(rules): pass required mode arg to cleanup-rules.bin (2.11.3)
v2.11.3
2026-07-24 11:29:20 -04:00
Justin BollingerandClaude Opus 4.8 fe206420e9 fix(rules): pass required mode arg to cleanup-rules.bin (2.11.3)
cleanup-rules.bin requires a mode argument (1=CPU, 2=GPU) and exits with
usage text otherwise, so Rule File Tools cleanup always failed. Pass the
mode (defaulting to GPU) so cleanup actually runs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 11:28:56 -04:00
Justin Bollinger 04be489c60 Merge branch 'fix/upload-counts' (2.11.2) v2.11.2 2026-07-23 14:26:31 -04:00
Justin BollingerandClaude Opus 4.8 a15860a63e feat(hashview): report cracked-hash upload counts (2.11.2)
The upload previously printed only "✓ Success: OK", so there was no way
to tell how many hashes were accepted. upload_cracked_hashes now surfaces
client-side uploaded/skipped counts in its return value, and the CLI
prints them plus the server's verified/updated/unmatched breakdown when a
newer Hashview reports them (see hashview #355/#356).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 14:26:26 -04:00
Justin Bollinger a14272a058 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	CHANGELOG.md
v2.11.1
2026-07-23 14:00:58 -04:00
Justin Bollinger 4c70185270 Merge branch 'fix/upload-hex-decode' (2.10.11) 2026-07-23 13:59:22 -04:00
Justin BollingerandClaude Opus 4.8 a3ca2a19e8 docs(changelog): add 2.10.11 (Hashview $HEX upload fix + client-side validation)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:59:15 -04:00
Justin BollingerandClaude Opus 4.8 2ed9cc28e6 fix(hashview): decode $HEX[...] before upload for older servers
hate_crack forwarded hashcat's $HEX[...] plaintext verbatim. A Hashview
that verifies plaintext literally hashes the string "$HEX[..]" and
rejects the batch. Decode $HEX to the exact bytes the server must
re-hash and send those on the wire (body is now bytes):

- UTF-16LE modes (NTLM 1000, MSSQL 1731): latin-1 code points -> UTF-8
- raw-byte modes (0/100/300/900/1400/1700): the decoded bytes as-is
- unsafe (embedded CR/LF) or unknown modes: keep the $HEX token verbatim
  and rely on a $HEX-aware server

Also fixes the NTLM validation digest to use latin-1 -> UTF-16LE so
high-byte $HEX plaintexts verify instead of being silently unverifiable.
Verified end-to-end: the emitted wire verifies against both the old
(literal) and new ($HEX-aware) Hashview verifiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:26:09 -04:00
Justin BollingerandGitHub 0a6dfd26fc Merge pull request #116 from trustedsec/feature/shard-multi-part
feat(wordlist): shard into all N parts in one run with numbered filenames
v2.11.0
2026-07-23 13:15:38 -04:00
Justin Bollinger d716f04c86 Merge branch 'fix/upload-hash-validation' 2026-07-23 13:12:41 -04:00
Justin BollingerandClaude Opus 4.8 ecedcbf7dc fix(hashview): validate cracked pairs client-side before upload
upload_cracked_hashes sent every hash:plaintext pair to Hashview
untouched. A single line whose plaintext doesn't match the declared
hash mode (e.g. a stray MD5 hash mixed into an NTLM list) made
Hashview reject the entire batch with an opaque
"Plaintext for hash ... was found to be invalid" error.

Add two client-side guards (default on, disable via validate=False):
1. Length filter — drop hashes whose hex width is wrong for the mode.
2. Plaintext verification — for reproducible fast modes (MD5, SHA1,
   MD4, NTLM, SHA2-256/512) recompute the digest from the plaintext
   ($HEX[...] decoded) and skip pairs that don't match.

Skipped lines are reported with line number and reason instead of
failing the whole upload; raise clearly if nothing valid remains.
Ships a pure-Python MD4 since OpenSSL 3 dropped it from hashlib.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:52:55 -04:00
Justin BollingerandClaude Opus 4.8 5510755c12 feat(wordlist): shard into all N parts in one run with numbered filenames
Shard Wordlist (option 7) now prompts for an output base path and a shard
count, then writes all N interleaved parts as base.001..base.00N in a single
pass instead of one file per modulus/offset invocation. Matches the intended
distributed-cracking workflow: split once, copy one part per node.

Updates tests and README usage docs; bumps CHANGELOG to 2.10.11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 12:51:07 -04:00
Justin Bollinger 1e23199aac Merge branch 'docs/changelog-version-correction' v2.10.10 2026-07-21 18:22:43 -04:00
Justin BollingerandClaude Opus 4.8 eb98103d05 docs: correct CHANGELOG versions (pytest fix is 2.10.10; add 2.10.9)
The auto-tag workflow already published v2.10.9 for Larry's Quick Crack
wordlist fix when main was pushed. Retitle the pytest security bump to
2.10.10 (its actual auto-tag target) and add the missing 2.10.9 entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:22:39 -04:00
Justin Bollinger 5dec58d973 Merge branch 'fix/bump-pytest-9.0.3-v2' 2026-07-21 18:21:01 -04:00
Justin BollingerandClaude Opus 4.8 c312259a86 fix(deps): bump pytest 9.0.2 -> 9.0.3 for GHSA-6w46-j5rx-g56g
The pinned dev/test dependency pytest==9.0.2 is affected by the
vulnerable tmpdir-handling advisory GHSA-6w46-j5rx-g56g (pytest < 9.0.3),
Dependabot alert #1. Bump the pin to 9.0.3 to clear it. Development
scope only (test runner); no runtime dependency change. Full test
suite passes under 9.0.3. (uv.lock is gitignored, so only the
pyproject.toml pin is tracked.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 18:20:55 -04:00