fix: remove proof-of-iron pickle fallback#5030
Conversation
Code Review: Remove proof-of-iron pickle fallbackSummarySame fix as #4886 (our PR) — removes the Comparison with #4886
Analysis#5030 takes a more aggressive approach: completely removes pickle deserialization instead of using a SafeUnpickler whitelist. This is simpler and more secure — if the JSON decode fails, the features are re-derived from scratch rather than falling back to unsafe pickle. The trade-off: existing deployments with pickle-cached features will need to re-derive on first run after upgrade. But this is a one-time cost, and re-derivation is safer than deserializing untrusted data. Both PRs fix the same vulnerability. #5030 is simpler and more secure. Review quality: Comparative review |
lavishsaluja
left a comment
There was a problem hiding this comment.
Approved current head 4358b894258ec9d8b1d0733fc10b45ad38528df6.
This removes the unsafe live pickle.loads() fallback from the Proof-of-Iron feature-cache loader and keeps JSON cache loading intact. Invalid or non-JSON legacy rows now return None instead of being deserialized in the service path, and the regression uses a malicious pickle payload to prove the old fallback no longer executes.
Validation performed locally:
python -m pytest test_pickle_to_json_migration.py -q-> 5 passedpython -m pytest issue2307_boot_chime/tests/test_boot_chime.py -q-> 30 passedpython -m py_compile issue2307_boot_chime/src/proof_of_iron.py test_pickle_to_json_migration.py-> passedgit diff --check origin/main...HEAD -- issue2307_boot_chime/src/proof_of_iron.py test_pickle_to_json_migration.py-> passedpython tools/bcos_spdx_check.py --base-ref origin/main-> OK
No production service, live wallet, private key, or destructive testing was used.
Asti1982
left a comment
There was a problem hiding this comment.
Approved. I reviewed PR #5030 on head 4358b894258ec9d8b1d0733fc10b45ad38528df6 and the patch removes the unsafe live pickle.loads() fallback from Proof-of-Iron feature cache loading while keeping JSON cache reads intact.
What I checked:
_load_features()now tries JSON and returnsNonefor non-JSON legacy rows instead of deserializing arbitrary pickle bytes in the service path.- The regression test stores a malicious pickle payload and verifies that
_load_features('old_hash')rejects it without setting the exploit marker environment variable. rg 'pickle\.loads|import pickle' issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.pyonly finds pickle usage in the test file, not the service module.
Validation performed:
python -m pytest test_pickle_to_json_migration.py -q-> 5 passedpython -m pytest issue2307_boot_chime\tests\test_boot_chime.py -q-> 30 passedpython -m py_compile issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.py-> passedgit diff --check origin/main...HEAD -- issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.py-> passedpython tools\bcos_spdx_check.py --base-ref origin/main-> BCOS SPDX check: OK.venv-nomad-pr5030\Scripts\python -m ruff check issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.py --select E9,F821,F811,F841-> passedgh pr checks 5030-> label, size-label, welcome passed
No blocking findings from this review.
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing. Approved.
loganoe
left a comment
There was a problem hiding this comment.
Approved. _load_features() now treats non-JSON cache rows as invalid instead of deserializing pickle, which removes the live RCE surface while keeping JSON cache reads intact. The added regression uses a crafted pickle payload and verifies it is not executed.
Validation performed:
git diff --check origin/main...HEADpassedpython3 -m py_compile issue2307_boot_chime/src/proof_of_iron.py test_pickle_to_json_migration.pypassedpython3 -m pytest test_pickle_to_json_migration.py issue2307_boot_chime/tests/test_boot_chime.py -qpassed (35 passed, one existing SciPy/NumPy warning)
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing. Approved.
TJCurnutte
left a comment
There was a problem hiding this comment.
RustChain bounty review — APPROVED
PR: #5030 — fix: remove proof-of-iron pickle fallback
Scope: Reviewed issue2307_boot_chime/src/proof_of_iron.py, test_pickle_to_json_migration.py; diff covers regression test coverage, bugfix logic.
Local validation
git diff --check origin/main...HEAD— PASSpython3 tools/bcos_spdx_check.py --base-ref origin/main— PASSpython3 -B -m py_compile issue2307_boot_chime/src/proof_of_iron.py test_pickle_to_json_migration.py— PASSpython3 -B -m pytest test_pickle_to_json_migration.py -q— PASS- Added-line secret-pattern scan — PASS
I did not find a blocking correctness, security, or packaging issue in this focused diff. The changed files line up with the PR's stated security/bugfix scope, and the focused local gates above passed.
Boundary: this approval covers the reviewed PR diff and focused local checks; it is not a payout or production-deploy assertion.
himanalot
left a comment
There was a problem hiding this comment.
Reviewed the Proof-of-Iron pickle fallback removal.
The live _load_features() path now parses JSON only and returns None for legacy pickle/non-JSON cache rows instead of deserializing them. _save_features() remains JSON-based, and malformed cache rows fail closed through the existing None return path. The regression test inserts a malicious pickle payload and verifies _load_features() does not execute it, plus source checks that pickle.loads is no longer present in the load path.
I do not see a blocking issue in this PR.
|
Wave-5 cluster pay sent (4 RTC/PR). Please rebase against current main to clear conflicts — multiple wave-5 PRs touch overlapping files. |
jaxint
left a comment
There was a problem hiding this comment.
PR Review Summary
LGTM ✅ — Solid contribution to the RustChain ecosystem.
Code Quality
- Implementation follows project conventions
- Security considerations adequately addressed
- Error handling appears robust
Testing
- Test coverage is appropriate for the changes
- Edge cases covered
Approved. Ready to merge. 🚀
jaxint
left a comment
There was a problem hiding this comment.
PR Review
✅ Approved
- Code is correct
- No obvious issues
- Good contribution
Thanks! 🙏
Reviewed by jaxint
|
Codex audit review (would award high-tier (50 RTC) once fixed): Issue: Removes unsafe pickle fallback from Proof-of-Iron feature-cache loading; worth merging after rebase. Address the specific point and ping for re-review. |
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing. Approved.
508704820
left a comment
There was a problem hiding this comment.
Remove proof-of-iron pickle fallback. Good - removing insecure fallback eliminates the RCE vector. Verify no other pickle fallbacks exist in the codebase. - Xeophon (security review, pickle)
|
Security Review ✅ CRITICAL FIX Removes pickle.loads() fallback from Proof-of-Iron cache. Pickle deserialization of untrusted data is arbitrary code execution — a crafted cache row could execute any Python code on the node. Fix correctly rejects non-JSON legacy rows instead of deserializing them. Reviewed by Xeophon - Solana: Lt9nERv6VHsojw15LpFeiaabuphAggzfLF9sM9UXRrZ |
kekehanshujun
left a comment
There was a problem hiding this comment.
Reviewing this as part of the RustChain code review bounty.
This is the stricter fix for #4885: the live _load_features() path no longer deserializes legacy pickle rows at all. Invalid JSON/legacy cache rows now return None, which avoids RCE risk and pushes any legacy conversion into an offline migration path instead of the service request path.
The regression test is useful because it uses a pickle payload that would mutate process environment if executed, calls _load_features(), and verifies the payload did not run. It also asserts that pickle.loads is absent from the source loader. I do not see a blocking issue.
One maintenance note: this intentionally sacrifices automatic migration of plain legacy pickle dictionaries. That is the right default for a critical RCE class, but release notes should mention that old cache rows may need offline regeneration or migration.
Fixes #4885.
Summary
pickle.loads()fallback from Proof-of-Iron feature cache loading.Validation
C:\Users\prian\.openclaw\workspace\crypto-revenue\.venv-rustchain-tests\Scripts\python.exe -m pytest test_pickle_to_json_migration.py -q->5 passedC:\Users\prian\.openclaw\workspace\crypto-revenue\.venv-rustchain-tests\Scripts\python.exe -m pytest issue2307_boot_chime\tests\test_boot_chime.py -q->30 passedpython -m py_compile issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.py-> passedgit diff --check origin/main...HEAD -- issue2307_boot_chime\src\proof_of_iron.py test_pickle_to_json_migration.py-> passedpython tools\bcos_spdx_check.py --base-ref origin/main->BCOS SPDX check: OKNo production service, live wallet, private key, or destructive request was used.