fix: prevent EIP-712 permit display value spoofing via decoy nested field#965
Open
devin-ai-integration[bot] wants to merge 1 commit into
Open
fix: prevent EIP-712 permit display value spoofing via decoy nested field#965devin-ai-integration[bot] wants to merge 1 commit into
devin-ai-integration[bot] wants to merge 1 commit into
Conversation
…ield (bug) Co-Authored-By: Kylie Chang <kylie.chang@cognition.ai>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
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.
Description
Security fix. The typed-data (EIP-712) permit confirmation UI could display a token amount that diverges from the amount actually being signed, letting a malicious dApp trick a user into approving a large/unlimited allowance while the wallet shows a tiny one.
Root cause (
app/components/Views/confirmations/utils/signature.ts): to preserve precision for integers larger thanNumber.MAX_SAFE_INTEGER,parseAndNormalizeSignTypedDataoverwroteresult.message.valuewith the result of a regex run over the raw request string:[^}]*is greedy and backtracks to the last"value":<15+ digits>before the first}. A dApp can append a decoy nested struct so the regex captures the decoy instead of the real top-level permit value:The decoy field isn't in
types[primaryType], so it's stripped from the EIP-712 hash and ignored by the signer — the user sees ~0.0001 tokens but signs 9e20. Both confirmation surfaces (the messageDataTree/TokenValueand the permit simulation) consume this same poisoned value, so no field shows the true amount.Solution
Stop reconstructing the displayed value from a separate regex over the raw text. The native
JSON.parsealready reads the correct top-levelmessage.value(it only loses precision by coercing to scientific notation). So we derive the precise string from a second, structurally-identical parse of the same payload with every numeric literal rewritten as a quoted string:Because the precise value comes from a real parse at the correct structural position, it always equals the value
JSON.parse(and the signer) sees — a decoy nestedvalue, key reordering, or avaluesubstring inside another string field can no longer divert the displayed amount. Large-integer precision is still preserved (the original motivation).REGEX_MESSAGE_VALUE_LARGE/extractLargeMessageValueare removed.Only
parseAndNormalizeSignTypedDatais touched; the existing truthy guard (if (result.message?.value)) and all consumers are unchanged.Related issues
Fixes: EIP-712 permit confirmation displays attacker-spoofable token value (display diverges from signed amount)
Manual testing steps
eth_signTypedData_v4for an EIP-2612Permitwhose message is{"value":900000000000000000000,"a":{"value":100000000000000}}.9e20), not the decoy1e14.Screenshots/Recordings
Before
Displayed/simulated allowance shows the tiny decoy amount while the signed value is large/unlimited.
After
Displayed/simulated allowance matches the actual signed
message.value.Pre-merge author checklist
Pre-merge reviewer checklist
Link to Devin session: https://app.devin.ai/sessions/d17444b2cbcd48a78d98e35222a35ed8
Requested by: @kylie-chang
Devin Review