|
40 | 40 | end
|
41 | 41 |
|
42 | 42 | describe "GET /auth/handshake" do
|
| 43 | + before do |
| 44 | + ENV['TRAVIS_SITE'] = 'org' |
| 45 | + end |
| 46 | + after do |
| 47 | + ENV['TRAVIS_SITE'] = nil |
| 48 | + end |
| 49 | + |
43 | 50 | describe 'evil hackers messing with the state' do
|
44 | 51 | it 'does not succeed if state cookie mismatches' do
|
45 | 52 | Travis.redis.sadd('github:states', 'github-state')
|
|
50 | 57 | end
|
51 | 58 | end
|
52 | 59 |
|
53 |
| - describe 'evil hackers messing with redirection' do |
| 60 | + describe 'On org, evil hackers messing with redirection' do |
54 | 61 | before do
|
55 | 62 | WebMock.stub_request(:post, "https://foobar.com/access_token_path")
|
56 | 63 | .to_return(status: 200, body: 'access_token=token&token_type=bearer')
|
|
109 | 116 | end
|
110 | 117 | end
|
111 | 118 |
|
| 119 | + describe 'On com and enterprise, evil hackers messing with redirection' do |
| 120 | + before do |
| 121 | + WebMock.stub_request(:post, "https://foobar.com/access_token_path") |
| 122 | + .to_return(status: 200, body: 'access_token=token&token_type=bearer') |
| 123 | + |
| 124 | + WebMock.stub_request(:get, "https://api.github.com/user?per_page=100") |
| 125 | + .to_return( |
| 126 | + status: 200, |
| 127 | + body: JSON.dump(name: 'Piotr Sarnacki', login: 'drogus', gravatar_id: '123', id: 456, foo: 'bar'), headers: {'X-OAuth-Scopes' => 'repo, user, new_scope'} |
| 128 | + ) |
| 129 | + |
| 130 | + cookie_jar['travis.state-github'] = state |
| 131 | + Travis.redis.sadd('github:states', state) |
| 132 | + ENV['TRAVIS_SITE'] = nil |
| 133 | + end |
| 134 | + |
| 135 | + after do |
| 136 | + Travis.redis.srem('github:states', state) |
| 137 | + end |
| 138 | + |
| 139 | + context 'when redirect uri is correct' do |
| 140 | + let(:state) { 'github-state:::https://travis-ci.com/?any=params' } |
| 141 | + |
| 142 | + it 'it does allow redirect' do |
| 143 | + response = get "/auth/handshake/github?code=1234&state=#{URI.encode(state)}" |
| 144 | + expect(response.status).to eq(200) |
| 145 | + end |
| 146 | + end |
| 147 | + |
| 148 | + context 'when redirect uri is not allowed' do |
| 149 | + let(:state) { 'github-state:::https://dark-corner-of-web.com/' } |
| 150 | + |
| 151 | + it 'does not allow redirect' do |
| 152 | + response = get "/auth/handshake/github?code=1234&state=#{URI.encode(state)}" |
| 153 | + expect(response.status).to eq(401) |
| 154 | + expect(response.body).to eq("target URI not allowed") |
| 155 | + end |
| 156 | + end |
| 157 | + |
| 158 | + context 'when script tag is injected into redirect uri' do |
| 159 | + let(:state) { 'github-state:::https://travis-ci.com/<sCrIpt' } |
| 160 | + |
| 161 | + it 'does not allow redirect' do |
| 162 | + response = get "/auth/handshake/github?code=1234&state=#{URI.encode(state)}" |
| 163 | + expect(response.status).to eq(401) |
| 164 | + expect(response.body).to eq("target URI not allowed") |
| 165 | + end |
| 166 | + end |
| 167 | + |
| 168 | + context 'when onerror tag is injected into redirect uri' do |
| 169 | + let(:state) { 'github-state:::https://travis-ci.com/<img% src="" onerror="badcode()"' } |
| 170 | + |
| 171 | + it 'does not allow redirect' do |
| 172 | + response = get "/auth/handshake/github?code=1234&state=#{URI.encode(state)}" |
| 173 | + expect(response.status).to eq(401) |
| 174 | + expect(response.body).to eq("target URI not allowed") |
| 175 | + end |
| 176 | + end |
| 177 | + end |
| 178 | + |
112 | 179 | describe 'with insufficient oauth permissions' do
|
113 | 180 | before do
|
114 | 181 | Travis.redis.sadd('github:states', 'github-state')
|
|
0 commit comments