Cache Invalidation Hardening — recipe/_api.py FIPS Fix + Test Fix
Source: review-decisions audit (2026-05-05) — adversarial review confirmed | Scope: small
Validated Findings
[F24] recipe/_api.py: add usedforsecurity=False to hashlib.md5 call
File: src/autoskillit/recipe/_api.py:118 | Severity: warning/defense
hashlib.md5(str(entries).encode()).hexdigest() has no usedforsecurity keyword argument. On FIPS-140 hardened systems (RHEL 8+), OpenSSL rejects MD5 calls lacking usedforsecurity=False with ValueError: [digital envelope routines] unsupported. The hash is purely for cache invalidation — non-cryptographic use.
Fix: Add usedforsecurity=False parameter. Project targets Python >=3.11 (pyproject.toml:25), so the parameter is supported.
# Before:
hashlib.md5(str(entries).encode()).hexdigest()
# After:
hashlib.md5(str(entries).encode(), usedforsecurity=False).hexdigest()
[F23] tests/recipe: replace time.sleep mtime hack with os.utime()
File: tests/recipe/test_api.py:743 | Severity: warning/tests
time.sleep(0.01) is used to force an mtime change between two writes of identical content. On 1-second-resolution filesystems (HFS+, some ext4 mount configs), 10 ms will not advance mtime, causing intermittent h1 == h2 assertion failures.
Fix: Use os.utime() with an explicit offset instead of sleeping:
# Before:
time.sleep(0.01)
f.write_text("name: test\\n") # same content, new mtime
# After:
f.write_text("name: test\\n") # same content
stat = f.stat()
os.utime(f, ns=(stat.st_atime_ns, stat.st_mtime_ns + 1_000_000_000)) # +1 second
Adversarial Review Notes
- F24 confirmed: AGREE — genuine FIPS compliance issue, trivial fix
- F23 confirmed: AGREE — architecturally insufficient sleep, though works on project's WSL2/tmpfs CI
- F03 (mtime_ns without st_size) was downgraded to info/cohesion and excluded from this ticket —
_file_size() IS already used for the recipe-file cache path (lines 349-358); the omission from _compute_registry_hash is a consistency gap on a low-churn path, not a hot-path correctness bug
Cache Invalidation Hardening — recipe/_api.py FIPS Fix + Test Fix
Source: review-decisions audit (2026-05-05) — adversarial review confirmed | Scope: small
Validated Findings
[F24] recipe/_api.py: add usedforsecurity=False to hashlib.md5 call
File:
src/autoskillit/recipe/_api.py:118| Severity: warning/defensehashlib.md5(str(entries).encode()).hexdigest()has nousedforsecuritykeyword argument. On FIPS-140 hardened systems (RHEL 8+), OpenSSL rejects MD5 calls lackingusedforsecurity=FalsewithValueError: [digital envelope routines] unsupported. The hash is purely for cache invalidation — non-cryptographic use.Fix: Add
usedforsecurity=Falseparameter. Project targets Python >=3.11 (pyproject.toml:25), so the parameter is supported.[F23] tests/recipe: replace time.sleep mtime hack with os.utime()
File:
tests/recipe/test_api.py:743| Severity: warning/teststime.sleep(0.01)is used to force an mtime change between two writes of identical content. On 1-second-resolution filesystems (HFS+, some ext4 mount configs), 10 ms will not advance mtime, causing intermittenth1 == h2assertion failures.Fix: Use
os.utime()with an explicit offset instead of sleeping:Adversarial Review Notes
_file_size()IS already used for the recipe-file cache path (lines 349-358); the omission from_compute_registry_hashis a consistency gap on a low-churn path, not a hot-path correctness bug