feat(security): Soroban deployment fingerprinting and contract upgrade detection - #1075
Merged
Conversation
Implements MDTechLabs#1066 and MDTechLabs#1065. MDTechLabs#1066 — Deterministic fingerprints for Soroban deployments over the fields that define a deployment's identity: contract address, network, wasm hash, spec version and a canonical digest of the interface surface. Observation-time context is deliberately excluded so the same deployment seen twice fingerprints identically. Approved fingerprints are stored per contract and network, revocation is retained for audit, and the verifier reports approved / mismatch / revoked / unknown separately with the specific differences. MDTechLabs#1065 — Upgrade detection compares each observation against the tracked fingerprint, classifies what changed (wasm, spec version, functions added or removed, events, error codes, redeploy), grades severity, records the event, flags every integration that depended on the previous deployment, and notifies the registered monitoring sinks. A removed function is critical; new code behind an unchanged interface is major, since nothing visible would otherwise stop it being trusted. 116 tests pass. tsc --strict and eslint are clean over the new files.
|
@ThatCodeBabe Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two closely related pieces of the same defence, so they ship together: fingerprinting establishes what an approved deployment is, and upgrade detection notices when a configured contract stops being it.
Closes #1066
Closes #1065
#1066 — Deployment fingerprinting
src/security/contracts/fingerprints/,src/contracts/verification/A fingerprint is a sha256 over exactly the fields that define a deployment's identity — contract address, network, wasm hash, spec version, and a canonical digest of the interface surface. Observation-time context (
observedAt,deployedAt,txHash, deployer) is deliberately excluded: the same deployment read from two nodes at two times must fingerprint identically, or every comparison is a false alarm.Determinism is enforced where it can quietly break:
0xstripped.address|network|hash, so no field value can impersonate another deployment by containing the separator.ApprovedFingerprintStoreholds what an operator approved, scoped per contract and network. Re-approving updates rather than duplicating (and un-revokes, since that is an explicit decision to trust again); revoked records are retained rather than deleted, because "approved and then revoked" is a materially different answer from "never heard of it". Persistence is left to the caller viasnapshot()/restore().SorobanDeploymentVerifierreturns four distinct statuses rather than a boolean, because they call for different responses:approvedmismatchrevokedunknown#1065 — Upgrade detection
src/security/contracts/upgrades/soroban/,src/contracts/monitoring/SorobanUpgradeDetectortracks configured contracts and compares each observation by fingerprint, not by any single field — so an upgrade that keeps the interface identical, the case most likely to go unnoticed, is still caught.Indicators: wasm hash changed, spec version changed, functions added, functions removed, events changed, error codes changed, redeployed. Severity:
Every integration that depended on the previous deployment is flagged for review. A second upgrade while a flag is open does not raise a duplicate — it raises the existing flag to the worst severity seen, and never lowers it. Flags clear only when an operator re-approves, and cleared flags stay in the audit list.
ContractUpgradeMonitorowns scheduling and fan-out only:unapproved-deploymentis emitted for anything not approved.Verification
One thing worth flagging, since it affects how much the green check above is worth: CI runs
pnpm run buildandcargo test, and that build isnest build --path apps/api/tsconfig.json, whoseincludeis./src/**/*.tsandpackages/utils/src/**— the repo-rootsrc/tree, where this work and most other feature code lives, is never compiled by CI, and jest never runs at all. So CI would be green for this PR whether or not the code compiles. That is why the numbers above are from running the suite locally. Happy to add apnpm teststep and widen the build in a separate PR if you want it — it seemed wrong to slip a CI change into a feature branch.