bug: reject non-positive amounts in deposit/withdraw/transfer - #298
Open
devin-ai-integration[bot] wants to merge 3 commits into
Open
devin-ai-integration[bot] wants to merge 3 commits into
devin-ai-integration[bot] wants to merge 3 commits into
Conversation
…he rendered balance is re-read from the database Co-Authored-By: Achal Channarasappa <achal.channarasappa@cognition.ai>
…story writes commit or roll back together Co-Authored-By: Achal Channarasappa <achal.channarasappa@cognition.ai>
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.
Summary
deposit,withdraw, andtransferAmountnever validated the sign ofamount. The insufficient-funds guard isbalance.compareTo(amount) < 0, which is always false for a negative amount, so any authenticated user could POST/transferwithtoUsername=<victim>&amount=-100:from.balance.subtract(-100)credited the attacker andto.balance.add(-100)debited an arbitrary victim account.withdrawwith a negative amount likewise inflated the caller's own balance.Fix is a single guard in the service layer (the only place all three mutations converge), executed before any balance read or repository write:
called at the top of
deposit,withdraw, andtransferAmount. Zero andnullare rejected too.Controller error path.
BankController.depositpreviously had notry/catch, so the new exception would have surfaced as a 500. All three mutating endpoints now handle failure the same way: onRuntimeExceptiontheyredirect:/dashboardwith the message as a flash attribute (RedirectAttributes.addFlashAttribute("error", …)) instead of renderingdashboarddirectly with the in-requestAccountobject. Rendering in-request could show a balance that had been mutated in memory before a repository write failed; the redirect forcesGET /dashboardto re-read the account from the database.dashboard.htmlalready renders${error}.Atomicity.
deposit,withdraw, andtransferAmountare@Transactional, so the balance save(s) and the transaction-history write commit or roll back as one unit; a failure after the balance write no longer leaves a balance without its history row (or, for transfers, one side moved and the other not).New
AccountServiceAmountValidationTest(Mockito, no Spring context — the existing app test needs a live MySQL) covers the theft path (negative transfer throws and touches neither repository), zero/null, negative withdraw/deposit, plus happy paths for all three operations.Verification:
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 mvn -Dtest=AccountServiceAmountValidationTest test— Tests run: 8, Failures: 0, Errors: 0, Skipped: 0. The repository has no test CI (the only check is Snyk), so this local run is the test evidence.Re-run on the PR head (
fc622dd, after the redirect and@Transactionalcommits):mvn -B -Dtest=AccountServiceAmountValidationTest test— Tests run: 8, Failures: 0, Errors: 0, Skipped: 0 (surefire reportTEST-com.[REDACTED SECRET].bankapp.service.AccountServiceAmountValidationTest.xml).Devin-Org: engineering
Link to Devin session: https://app.devin.ai/sessions/d40b21770ac144aa9a39abb9cfca43e3
Open in Devin Desktop: https://app.devin.ai/desktop/session/d40b21770ac144aa9a39abb9cfca43e3?variant=devin
Requested by: @achalc