Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
bd46c8ab
Commit
bd46c8ab
authored
Oct 17, 2017
by
Jen-Shin Lin
Committed by
Stan Hu
Oct 17, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge branch 'security-10-1' into '10-1-stable'
Security fixes for 10.1 RC See merge request gitlab/gitlabhq!2209
parent
9978ef98
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
141 additions
and
80 deletions
+141
-80
app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
...ascripts/filtered_search/filtered_search_visual_tokens.js
+2
-2
app/controllers/projects/application_controller.rb
app/controllers/projects/application_controller.rb
+0
-10
app/controllers/projects_controller.rb
app/controllers/projects_controller.rb
+10
-0
app/models/concerns/storage/legacy_namespace.rb
app/models/concerns/storage/legacy_namespace.rb
+2
-0
app/models/note.rb
app/models/note.rb
+1
-1
app/services/system_note_service.rb
app/services/system_note_service.rb
+0
-7
changelogs/unreleased/38126-security-username-change.yml
changelogs/unreleased/38126-security-username-change.yml
+5
-0
changelogs/unreleased/fix-arbitrary-redirect-vulnerability.yml
...elogs/unreleased/fix-arbitrary-redirect-vulnerability.yml
+5
-0
changelogs/unreleased/rs-sanitize-unicode-in-protocol.yml
changelogs/unreleased/rs-sanitize-unicode-in-protocol.yml
+5
-0
lib/banzai/filter/sanitization_filter.rb
lib/banzai/filter/sanitization_filter.rb
+12
-2
spec/controllers/profiles_controller_spec.rb
spec/controllers/profiles_controller_spec.rb
+38
-6
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+29
-28
spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
...pts/filtered_search/filtered_search_visual_tokens_spec.js
+23
-0
spec/lib/banzai/filter/sanitization_filter_spec.rb
spec/lib/banzai/filter/sanitization_filter_spec.rb
+5
-0
spec/models/namespace_spec.rb
spec/models/namespace_spec.rb
+4
-10
spec/services/system_note_service_spec.rb
spec/services/system_note_service_spec.rb
+0
-14
No files found.
app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
View file @
bd46c8ab
...
...
@@ -123,8 +123,8 @@ class FilteredSearchVisualTokens {
/* eslint-disable no-param-reassign */
tokenValueContainer
.
dataset
.
originalValue
=
tokenValue
;
tokenValueElement
.
innerHTML
=
`
<img class="avatar s20" src="
${
user
.
avatar_url
}
" alt="
${
user
.
name
}
's avatar
">
${
user
.
name
}
<img class="avatar s20" src="
${
user
.
avatar_url
}
" alt="">
${
_
.
escape
(
user
.
name
)
}
`
;
/* eslint-enable no-param-reassign */
})
...
...
app/controllers/projects/application_controller.rb
View file @
bd46c8ab
...
...
@@ -2,7 +2,6 @@ class Projects::ApplicationController < ApplicationController
include
RoutableActions
skip_before_action
:authenticate_user!
before_action
:redirect_git_extension
before_action
:project
before_action
:repository
layout
'project'
...
...
@@ -11,15 +10,6 @@ class Projects::ApplicationController < ApplicationController
private
def
redirect_git_extension
# Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
redirect_to
url_for
(
params
.
merge
(
format:
nil
))
if
params
[
:format
]
==
'git'
end
def
project
return
@project
if
@project
return
nil
unless
params
[
:project_id
]
||
params
[
:id
]
...
...
app/controllers/projects_controller.rb
View file @
bd46c8ab
...
...
@@ -4,6 +4,7 @@ class ProjectsController < Projects::ApplicationController
include
PreviewMarkdown
before_action
:authenticate_user!
,
except:
[
:index
,
:show
,
:activity
,
:refs
]
before_action
:redirect_git_extension
,
only:
[
:show
]
before_action
:project
,
except:
[
:index
,
:new
,
:create
]
before_action
:repository
,
except:
[
:index
,
:new
,
:create
]
before_action
:assign_ref_vars
,
only:
[
:show
],
if: :repo_exists?
...
...
@@ -389,4 +390,13 @@ class ProjectsController < Projects::ApplicationController
def
project_export_enabled
render_404
unless
current_application_settings
.
project_export_enabled?
end
def
redirect_git_extension
# Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
redirect_to
request
.
original_url
.
sub
(
/\.git\/?\Z/
,
''
)
if
params
[
:format
]
==
'git'
end
end
app/models/concerns/storage/legacy_namespace.rb
View file @
bd46c8ab
...
...
@@ -7,6 +7,8 @@ module Storage
raise
Gitlab
::
UpdatePathError
.
new
(
'Namespace cannot be moved, because at least one project has tags in container registry'
)
end
expires_full_path_cache
# Move the namespace directory in all storage paths used by member projects
repository_storage_paths
.
each
do
|
repository_storage_path
|
# Ensure old directory exists before moving it
...
...
app/models/note.rb
View file @
bd46c8ab
...
...
@@ -169,7 +169,7 @@ class Note < ActiveRecord::Base
end
def
cross_reference?
system
?
&&
SystemNoteService
.
cross_reference?
(
note
)
system
?
&&
matches_cross_reference_regex?
end
def
diff_note?
...
...
app/services/system_note_service.rb
View file @
bd46c8ab
...
...
@@ -162,7 +162,6 @@ module SystemNoteService
# "changed time estimate to 3d 5h"
#
# Returns the created Note object
def
change_time_estimate
(
noteable
,
project
,
author
)
parsed_time
=
Gitlab
::
TimeTrackingFormatter
.
output
(
noteable
.
time_estimate
)
body
=
if
noteable
.
time_estimate
==
0
...
...
@@ -188,7 +187,6 @@ module SystemNoteService
# "added 2h 30m of time spent"
#
# Returns the created Note object
def
change_time_spent
(
noteable
,
project
,
author
)
time_spent
=
noteable
.
time_spent
...
...
@@ -453,10 +451,6 @@ module SystemNoteService
end
end
def
cross_reference?
(
note_text
)
note_text
=~
/\A
#{
cross_reference_note_prefix
}
/i
end
# Check if a cross-reference is disallowed
#
# This method prevents adding a "mentioned in !1" note on every single commit
...
...
@@ -486,7 +480,6 @@ module SystemNoteService
# mentioner - Mentionable object
#
# Returns Boolean
def
cross_reference_exists?
(
noteable
,
mentioner
)
# Initial scope should be system notes of this noteable type
notes
=
Note
.
system
.
where
(
noteable_type:
noteable
.
class
)
...
...
changelogs/unreleased/38126-security-username-change.yml
0 → 100644
View file @
bd46c8ab
---
title
:
Move project repositories between namespaces when renaming users
merge_request
:
author
:
type
:
security
changelogs/unreleased/fix-arbitrary-redirect-vulnerability.yml
0 → 100644
View file @
bd46c8ab
---
title
:
Prevent an open redirect on project pages
merge_request
:
author
:
type
:
security
changelogs/unreleased/rs-sanitize-unicode-in-protocol.yml
0 → 100644
View file @
bd46c8ab
---
title
:
Prevent a persistent XSS in user-provided markup
merge_request
:
author
:
type
:
security
lib/banzai/filter/sanitization_filter.rb
View file @
bd46c8ab
...
...
@@ -75,9 +75,19 @@ module Banzai
begin
node
[
'href'
]
=
node
[
'href'
].
strip
uri
=
Addressable
::
URI
.
parse
(
node
[
'href'
])
uri
.
scheme
=
uri
.
scheme
.
downcase
if
uri
.
scheme
node
.
remove_attribute
(
'href'
)
if
UNSAFE_PROTOCOLS
.
include?
(
uri
.
scheme
)
return
unless
uri
.
scheme
# Remove all invalid scheme characters before checking against the
# list of unsafe protocols.
#
# See https://tools.ietf.org/html/rfc3986#section-3.1
scheme
=
uri
.
scheme
.
strip
.
downcase
.
gsub
(
/[^A-Za-z0-9\+\.\-]+/
,
''
)
node
.
remove_attribute
(
'href'
)
if
UNSAFE_PROTOCOLS
.
include?
(
scheme
)
rescue
Addressable
::
URI
::
InvalidURIError
node
.
remove_attribute
(
'href'
)
end
...
...
spec/controllers/profiles_controller_spec.rb
View file @
bd46c8ab
require
(
'spec_helper'
)
describe
ProfilesController
do
describe
"PUT update"
do
it
"allows an email update from a user without an external email address"
do
user
=
create
(
:user
)
describe
ProfilesController
,
:request_store
do
let
(
:user
)
{
create
(
:user
)
}
describe
'PUT update'
do
it
'allows an email update from a user without an external email address'
do
sign_in
(
user
)
put
:update
,
...
...
@@ -29,7 +30,7 @@ describe ProfilesController do
expect
(
user
.
unconfirmed_email
).
to
eq
nil
end
it
"ignores an email update from a user with an external email address"
do
it
'ignores an email update from a user with an external email address'
do
stub_omniauth_setting
(
sync_profile_from_provider:
[
'ldap'
])
stub_omniauth_setting
(
sync_profile_attributes:
true
)
...
...
@@ -46,7 +47,7 @@ describe ProfilesController do
expect
(
ldap_user
.
unconfirmed_email
).
not_to
eq
(
'john@gmail.com'
)
end
it
"ignores an email and name update but allows a location update from a user with external email and name, but not external location"
do
it
'ignores an email and name update but allows a location update from a user with external email and name, but not external location'
do
stub_omniauth_setting
(
sync_profile_from_provider:
[
'ldap'
])
stub_omniauth_setting
(
sync_profile_attributes:
true
)
...
...
@@ -65,4 +66,35 @@ describe ProfilesController do
expect
(
ldap_user
.
location
).
to
eq
(
'City, Country'
)
end
end
describe
'PUT update_username'
do
let
(
:namespace
)
{
user
.
namespace
}
let
(
:project
)
{
create
(
:project_empty_repo
,
namespace:
namespace
)
}
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
let
(
:new_username
)
{
'renamedtosomethingelse'
}
it
'allows username change'
do
sign_in
(
user
)
put
:update_username
,
user:
{
username:
new_username
}
user
.
reload
expect
(
response
.
status
).
to
eq
(
302
)
expect
(
user
.
username
).
to
eq
(
new_username
)
end
it
'moves dependent projects to new namespace'
do
sign_in
(
user
)
put
:update_username
,
user:
{
username:
new_username
}
user
.
reload
expect
(
response
.
status
).
to
eq
(
302
)
expect
(
gitlab_shell
.
exists?
(
project
.
repository_storage_path
,
"
#{
new_username
}
/
#{
project
.
path
}
.git"
)).
to
be_truthy
end
end
end
spec/controllers/projects/issues_controller_spec.rb
View file @
bd46c8ab
...
...
@@ -850,47 +850,48 @@ describe Projects::IssuesController do
describe
'GET #discussions'
do
let!
(
:discussion
)
{
create
(
:discussion_note_on_issue
,
noteable:
issue
,
project:
issue
.
project
)
}
before
do
project
.
add_developer
(
user
)
sign_in
(
user
)
end
it
'returns discussion json'
do
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
expect
(
JSON
.
parse
(
response
.
body
).
first
.
keys
).
to
match_array
(
%w[id reply_id expanded notes individual_note]
)
end
context
'with cross-reference system note'
,
:request_store
do
let
(
:new_issue
)
{
create
(
:issue
)
}
let
(
:cross_reference
)
{
"mentioned in
#{
new_issue
.
to_reference
(
issue
.
project
)
}
"
}
context
'when authenticated'
do
before
do
create
(
:discussion_note_on_issue
,
:system
,
noteable:
issue
,
project:
issue
.
project
,
note:
cross_reference
)
project
.
add_developer
(
user
)
sign_in
(
user
)
end
it
'
filters notes that the user should not see
'
do
it
'
returns discussion json
'
do
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
expect
(
JSON
.
parse
(
response
.
body
).
count
).
to
eq
(
1
)
expect
(
json_response
.
first
.
keys
).
to
match_array
(
%w[id reply_id expanded notes individual_note]
)
end
it
'does not result in N+1 queries'
do
# Instantiate the controller variables to ensure QueryRecorder has an accurate base count
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
context
'with cross-reference system note'
,
:request_store
do
let
(
:new_issue
)
{
create
(
:issue
)
}
let
(
:cross_reference
)
{
"mentioned in
#{
new_issue
.
to_reference
(
issue
.
project
)
}
"
}
RequestStore
.
clear!
before
do
create
(
:discussion_note_on_issue
,
:system
,
noteable:
issue
,
project:
issue
.
project
,
note:
cross_reference
)
end
control_count
=
ActiveRecord
::
QueryRecorder
.
new
do
it
'filters notes that the user should not see'
do
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
end
.
count
RequestStore
.
clear!
expect
(
JSON
.
parse
(
response
.
body
).
count
).
to
eq
(
1
)
end
create_list
(
:discussion_note_on_issue
,
2
,
:system
,
noteable:
issue
,
project:
issue
.
project
,
note:
cross_reference
)
it
'does not result in N+1 queries'
do
# Instantiate the controller variables to ensure QueryRecorder has an accurate base count
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
expect
{
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
}.
not_to
exceed_query_limit
(
control_count
)
RequestStore
.
clear!
control_count
=
ActiveRecord
::
QueryRecorder
.
new
do
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
end
.
count
RequestStore
.
clear!
create_list
(
:discussion_note_on_issue
,
2
,
:system
,
noteable:
issue
,
project:
issue
.
project
,
note:
cross_reference
)
expect
{
get
:discussions
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
issue
.
iid
}.
not_to
exceed_query_limit
(
control_count
)
end
end
end
end
...
...
spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
View file @
bd46c8ab
...
...
@@ -791,6 +791,29 @@ describe('Filtered Search Visual Tokens', () => {
expect
(
tokenValueElement
.
innerText
.
trim
()).
toBe
(
dummyUser
.
name
);
const
avatar
=
tokenValueElement
.
querySelector
(
'
img.avatar
'
);
expect
(
avatar
.
src
).
toBe
(
dummyUser
.
avatar_url
);
expect
(
avatar
.
alt
).
toBe
(
''
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
escapes user name when creating token
'
,
(
done
)
=>
{
const
dummyUser
=
{
name
:
'
<script>
'
,
avatar_url
:
`
${
gl
.
TEST_HOST
}
/mypics/avatar.png`
,
};
const
{
tokenValueContainer
,
tokenValueElement
}
=
findElements
(
authorToken
);
const
tokenValue
=
tokenValueElement
.
innerText
;
usersCacheSpy
=
(
username
)
=>
{
expect
(
`@
${
username
}
`
).
toBe
(
tokenValue
);
return
Promise
.
resolve
(
dummyUser
);
};
subject
.
updateUserTokenAppearance
(
tokenValueContainer
,
tokenValueElement
,
tokenValue
)
.
then
(()
=>
{
expect
(
tokenValueElement
.
innerText
.
trim
()).
toBe
(
dummyUser
.
name
);
tokenValueElement
.
querySelector
(
'
.avatar
'
).
remove
();
expect
(
tokenValueElement
.
innerHTML
.
trim
()).
toBe
(
_
.
escape
(
dummyUser
.
name
));
})
.
then
(
done
)
.
catch
(
done
.
fail
);
...
...
spec/lib/banzai/filter/sanitization_filter_spec.rb
View file @
bd46c8ab
...
...
@@ -217,6 +217,11 @@ describe Banzai::Filter::SanitizationFilter do
output:
'<img>'
},
'protocol-based JS injection: Unicode'
=>
{
input:
%Q(<a href="
\u
0001java
\u
0003script:alert('XSS')">foo</a>)
,
output:
'<a>foo</a>'
},
'protocol-based JS injection: spaces and entities'
=>
{
input:
'<a href="  javascript:alert(\'XSS\');">foo</a>'
,
output:
'<a href="">foo</a>'
...
...
spec/models/namespace_spec.rb
View file @
bd46c8ab
...
...
@@ -4,6 +4,7 @@ describe Namespace do
include
ProjectForksHelper
let!
(
:namespace
)
{
create
(
:namespace
)
}
let
(
:gitlab_shell
)
{
Gitlab
::
Shell
.
new
}
describe
'associations'
do
it
{
is_expected
.
to
have_many
:projects
}
...
...
@@ -153,25 +154,18 @@ describe Namespace do
end
end
describe
'#move_dir'
do
describe
'#move_dir'
,
:request_store
do
let
(
:namespace
)
{
create
(
:namespace
)
}
let!
(
:project
)
{
create
(
:project_empty_repo
,
namespace:
namespace
)
}
before
do
allow
(
namespace
).
to
receive
(
:path_changed?
).
and_return
(
true
)
end
it
"raises error when directory exists"
do
expect
{
namespace
.
move_dir
}.
to
raise_error
(
"namespace directory cannot be moved"
)
end
it
"moves dir if path changed"
do
n
ew_path
=
namespace
.
full_path
+
"_new"
n
amespace
.
update_attributes
(
path:
namespace
.
full_path
+
'_new'
)
allow
(
namespace
).
to
receive
(
:full_path_was
).
and_return
(
namespace
.
full_path
)
allow
(
namespace
).
to
receive
(
:full_path
).
and_return
(
new_path
)
expect
(
namespace
).
to
receive
(
:remove_exports!
)
expect
(
namespace
.
move_dir
).
to
be_truthy
expect
(
gitlab_shell
.
exists?
(
project
.
repository_storage_path
,
"
#{
namespace
.
path
}
/
#{
project
.
path
}
.git"
)).
to
be_truthy
end
context
"when any project has container images"
do
...
...
spec/services/system_note_service_spec.rb
View file @
bd46c8ab
...
...
@@ -502,20 +502,6 @@ describe SystemNoteService do
end
end
describe
'.cross_reference?'
do
it
'is truthy when text begins with expected text'
do
expect
(
described_class
.
cross_reference?
(
'mentioned in something'
)).
to
be_truthy
end
it
'is truthy when text begins with legacy capitalized expected text'
do
expect
(
described_class
.
cross_reference?
(
'mentioned in something'
)).
to
be_truthy
end
it
'is falsey when text does not begin with expected text'
do
expect
(
described_class
.
cross_reference?
(
'this is a note'
)).
to
be_falsey
end
end
describe
'.cross_reference_disallowed?'
do
context
'when mentioner is not a MergeRequest'
do
it
'is falsey'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment