fix(optional-skills): add HMAC integrity check before pickle.loads in show_snapshot - #34986
fix(optional-skills): add HMAC integrity check before pickle.loads in show_snapshot#34986ErnestHysa wants to merge 2 commits into
Conversation
|
The HMAC verification order defeats its own security purpose. The PR calls The original code already has a Additionally: To make this work correctly, the HMAC would need to be stored in a sidecar file or in a non-pickle outer envelope (e.g., a JSON header with the HMAC + base64-encoded pickle payload), so integrity can be verified without unpickling first. |
The previous implementation called pickle.loads(raw_bytes) to extract the 'hmac' field from the unpickled dict, then compared it to a recomputed HMAC. This is the exact attack surface pickle.loads is supposed to defend against — the integrity check happens *after* the untrusted code has already executed, defeating the purpose entirely. This commit moves the HMAC to a sidecar file (`snapshot.pkl.hmac`) and verifies the raw file bytes against the sidecar before any unpickling. Sidecar format: a single line of hex SHA-256 HMAC-SHA256, written by the producer with the same secret. If the sidecar is missing, verification fails closed. Also removes the unused base64 import.
|
@liuhao1024 — you were right: the previous code called Reworked in commit 44ce026. The HMAC is now stored in a sidecar file ( About the Smoke tests:
|
|
@alt-glitch — addressed in commit 44ce026. You were right: the previous approach was logically flawed (pickle.loads ran before the HMAC check). Reworked to use a sidecar |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for correcting the original verification ordering: the sidecar approach verifies raw bytes before unpickling.
Problems
- The reader change is not paired with a producer.
optional-skills/research/darwinian-evolver/templates/custom_problem_template.py:231writes onlyiteration_<n>.pkl; the newshow_snapshot.pylogic requiresiteration_<n>.pkl.hmacwheneverHERMES_SNAPSHOT_SECRETis set. Consequently, all snapshots generated by the shipped template fail closed with a missing-sidecar error. tests/skills/test_darwinian_evolver_skill.py:64-74only syntax-checks the scripts. Add behavioral coverage for valid, missing, and tampered sidecars, including a check thatpickle.loadsis never reached after a verification failure.- The documented command at
optional-skills/research/darwinian-evolver/SKILL.md:107-112does not document the new sidecar setup and omits the existing required--i-trust-this-fileflag.
Suggested changes
- Implement and document the matching sidecar producer, then test the complete producer/reader contract.
Current main already requires an explicit trust acknowledgement before its pickle.loads calls (show_snapshot.py:42-62, added by 0a2ee71cc). This is an automated hermes-sweeper review.
| secret = os.environ.get(HERMES_SNAPSHOT_SECRET) | ||
| if secret: | ||
| hmac_path = args.snapshot.with_suffix(args.snapshot.suffix + ".hmac") | ||
| if not hmac_path.exists(): |
There was a problem hiding this comment.
No shipped producer writes this sidecar: templates/custom_problem_template.py:231 writes only the .pkl bytes. With HERMES_SNAPSHOT_SECRET enabled, every documented snapshot therefore exits here. Please add the matching producer and behavioral tests before requiring this file.
Summary\n\nAdds HMAC-SHA256 integrity verification before calling
pickle.loads()on untrusted snapshot files inoptional-skills/research/darwinian-evolver/scripts/show_snapshot.py.\n\n## Changes\n\n- WhenHERMES_SNAPSHOT_SECRETenv var is set: verifies the snapshot's HMAC signature before unpickling. Rejects the file if the HMAC is missing or doesn't match.\n- WhenHERMES_SNAPSHOT_SECRETis not set: emits a warning to stderr that integrity verification is skipped.\n\n## Security Fix (PICKLE-001)\n\nWithout HMAC verification, a MITM or compromised output directory could swap a benign snapshot for a malicious one. The new integrity check gatespickle.loads()behind a cryptographic HMAC computed with a shared secret.\n\n## Test Plan\n\n1. Run withoutHERMES_SNAPSHOT_SECRETset — should emit a warning but still run.\n2. SetHERMES_SNAPSHOT_SECRETand run on a snapshot with an invalid HMAC — should exit with an error.\n3. SetHERMES_SNAPSHOT_SECRETand run on a snapshot with a valid HMAC — should pass verification and proceed.\n\nFixes PICKLE-001.