-
Notifications
You must be signed in to change notification settings - Fork 2.6k
fix(oauth2): prevent code injection in OAuth2 callback handling #8360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
abhishekp-bruno
wants to merge
26
commits into
usebruno:main
from
abhishekp-bruno:fix/code-injection-vulnerability
Closed
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
0086ecb
fix(oauth2): prevent code injection in OAuth2 callback handling
abhishekp-bruno 52d82ae
ADD(test-case):oauth2-test-cases-for-state-vulnerability
abhishekp-bruno c32e046
Merge branch 'main' of https://github.com/abhishekp-bruno/bruno into …
abhishekp-bruno 3ec9505
ADD OAuth test cases
abhishekp-bruno b76ac9a
ADD IpcError formating for the error message
abhishekp-bruno 9fd37c8
ADD one more unit test case
abhishekp-bruno 87f6469
ADDED one more test for user supplied state
abhishekp-bruno 23b25b4
Merge branch 'main' of https://github.com/abhishekp-bruno/bruno into …
abhishekp-bruno 515d061
Merge branch 'main' of https://github.com/abhishekp-bruno/bruno into …
abhishekp-bruno d783e82
fix(oauth2): prevent code injection in OAuth2 callback handling
abhishekp-bruno 30fef00
ADD(test-case):oauth2-test-cases-for-state-vulnerability
abhishekp-bruno 4e9c219
ADD OAuth test cases
abhishekp-bruno f880abc
ADD IpcError formating for the error message
abhishekp-bruno 3887423
ADD one more unit test case
abhishekp-bruno 900616a
ADDED one more test for user supplied state
abhishekp-bruno 01fd1e8
feat(ai): OpenAI-compatible endpoints support (#8365)
naman-bruno 224d38d
refactor(migration): extract migration modal (#8359)
naman-bruno d9c0d3b
feat(ai): add AI chat sidebar with code block and diff view component…
naman-bruno c4ad4ba
feat(environments): split variables and secrets into separate tabs (#…
pooja-bruno fe12f34
fix(workspace-watcher): update IPC channel names for environment file…
sanish-bruno 4ca83e0
chore: update to latest stable lodash version (#8350)
sid-bruno 766bc04
test: workspace import and validation testcase (TC-969) (#8349)
mohit-bruno 89fe3bf
feat(ai): mode toggle UI and add AI support for folder & collection (…
naman-bruno 149aca3
feat(variables): persist scripted variable changes by default + re-en…
sanish-bruno 5aa20f4
Merge branch 'main' of https://github.com/abhishekp-bruno/bruno into …
abhishekp-bruno a9595b1
Merge branch 'fix/code-injection-vulnerability' of https://github.com…
abhishekp-bruno File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
122 changes: 122 additions & 0 deletions
122
packages/bruno-electron/tests/utils/oauth2-protocol-handler.spec.js
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| const { | ||
| registerOauth2AuthorizationRequest, | ||
| handleOauth2ProtocolUrl, | ||
| cancelOAuth2AuthorizationRequest, | ||
| isOauth2AuthorizationRequestInProgress | ||
| } = require('../../src/utils/oauth2-protocol-handler'); | ||
|
|
||
| describe('handleOauth2ProtocolUrl - state validation', () => { | ||
| let resolve; | ||
| let reject; | ||
|
|
||
| beforeEach(() => { | ||
| resolve = jest.fn(); | ||
| reject = jest.fn(); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| // Clear any pending request between tests | ||
| if (isOauth2AuthorizationRequestInProgress()) { | ||
| cancelOAuth2AuthorizationRequest(); | ||
| } | ||
| jest.clearAllMocks(); | ||
| }); | ||
|
|
||
| describe('authorization code flow (state in query params)', () => { | ||
| it('should resolve with the code when the returned state matches', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl('bruno://oauth2/callback?code=auth-code-123&state=expected-state'); | ||
|
|
||
| expect(resolve).toHaveBeenCalledWith('auth-code-123'); | ||
| expect(reject).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('should reject when the returned state does not match', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl('bruno://oauth2/callback?code=auth-code-123&state=attacker-state'); | ||
|
|
||
| expect(resolve).not.toHaveBeenCalled(); | ||
| expect(reject).toHaveBeenCalledWith( | ||
| expect.objectContaining({ message: expect.stringContaining('state mismatch') }) | ||
| ); | ||
| }); | ||
|
|
||
| it('should reject when no state is returned but one was expected', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl('bruno://oauth2/callback?code=auth-code-123'); | ||
|
|
||
| expect(resolve).not.toHaveBeenCalled(); | ||
| expect(reject).toHaveBeenCalledWith( | ||
| expect.objectContaining({ message: expect.stringContaining('state mismatch') }) | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe('implicit flow (state in hash fragment)', () => { | ||
| it('should resolve with tokens when the returned state matches', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl( | ||
| 'bruno://oauth2/callback#access_token=token-abc&token_type=bearer&state=expected-state' | ||
| ); | ||
|
|
||
| expect(resolve).toHaveBeenCalledWith( | ||
| expect.objectContaining({ access_token: 'token-abc' }) | ||
| ); | ||
| expect(reject).not.toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('should reject when the hash state does not match', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl( | ||
| 'bruno://oauth2/callback#access_token=token-abc&token_type=bearer&state=attacker-state' | ||
| ); | ||
|
|
||
| expect(resolve).not.toHaveBeenCalled(); | ||
| expect(reject).toHaveBeenCalledWith( | ||
| expect.objectContaining({ message: expect.stringContaining('state mismatch') }) | ||
| ); | ||
| }); | ||
|
|
||
| it('should reject when no hash state is returned but one was expected', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl( | ||
| 'bruno://oauth2/callback#access_token=token-abc&token_type=bearer' | ||
| ); | ||
|
|
||
| expect(resolve).not.toHaveBeenCalled(); | ||
| expect(reject).toHaveBeenCalledWith( | ||
| expect.objectContaining({ message: expect.stringContaining('state mismatch') }) | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe('when no expected state was registered (backward compatibility)', () => { | ||
| it('should resolve without validating state', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, null); | ||
|
|
||
| handleOauth2ProtocolUrl('bruno://oauth2/callback?code=auth-code-123'); | ||
|
|
||
| expect(resolve).toHaveBeenCalledWith('auth-code-123'); | ||
| expect(reject).not.toHaveBeenCalled(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('error responses are handled before state validation', () => { | ||
| it('should reject with the provider error even if state is absent', () => { | ||
| registerOauth2AuthorizationRequest(resolve, reject, null, 'expected-state'); | ||
|
|
||
| handleOauth2ProtocolUrl('bruno://oauth2/callback?error=access_denied'); | ||
|
|
||
| expect(resolve).not.toHaveBeenCalled(); | ||
| expect(reject).toHaveBeenCalledWith( | ||
| expect.objectContaining({ message: expect.stringContaining('Authorization Failed') }) | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.