mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
fix: guard POST keywords & allow co-maintainers to see keyword form
This addresses a severe security issue, which is omitted from this git message for obscurity purposes. Otherwise, it allows co-maintainers to see the keyword form when viewing a package they co-maintain. Closes #378 Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
7b047578fd
commit
7a52da5587
4 changed files with 28 additions and 5 deletions
|
@ -96,6 +96,12 @@ async def pkgbase_keywords(request: Request, name: str,
|
||||||
keywords: str = Form(default=str())):
|
keywords: str = Form(default=str())):
|
||||||
pkgbase = get_pkg_or_base(name, PackageBase)
|
pkgbase = get_pkg_or_base(name, PackageBase)
|
||||||
|
|
||||||
|
approved = [pkgbase.Maintainer] + [c.User for c in pkgbase.comaintainers]
|
||||||
|
has_cred = creds.has_credential(request.user, creds.PKGBASE_SET_KEYWORDS,
|
||||||
|
approved=approved)
|
||||||
|
if not has_cred:
|
||||||
|
return Response(status_code=HTTPStatus.UNAUTHORIZED)
|
||||||
|
|
||||||
# Lowercase all keywords. Our database table is case insensitive,
|
# Lowercase all keywords. Our database table is case insensitive,
|
||||||
# and providing CI duplicates of keywords is erroneous.
|
# and providing CI duplicates of keywords is erroneous.
|
||||||
keywords = set(k.lower() for k in keywords.split())
|
keywords = set(k.lower() for k in keywords.split())
|
||||||
|
|
|
@ -33,10 +33,10 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if pkgbase.keywords.count() or request.user.has_credential(creds.PKGBASE_SET_KEYWORDS, approved=[pkgbase.Maintainer]) %}
|
{% if pkgbase.keywords.count() or request.user.has_credential(creds.PKGBASE_SET_KEYWORDS, approved=[pkgbase.Maintainer] + comaintainers) %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ "Keywords" | tr }}:</th>
|
<th>{{ "Keywords" | tr }}:</th>
|
||||||
{% if request.user.has_credential(creds.PKGBASE_SET_KEYWORDS, approved=[pkgbase.Maintainer]) %}
|
{% if request.user.has_credential(creds.PKGBASE_SET_KEYWORDS, approved=[pkgbase.Maintainer] + comaintainers) %}
|
||||||
<td>
|
<td>
|
||||||
<form method="post"
|
<form method="post"
|
||||||
action="/pkgbase/{{ pkgbase.Name }}/keywords"
|
action="/pkgbase/{{ pkgbase.Name }}/keywords"
|
||||||
|
|
|
@ -1378,7 +1378,8 @@ def test_pkgbase_keywords(client: TestClient, user: User, package: Package):
|
||||||
keywords = root.xpath('//a[@class="keyword"]')
|
keywords = root.xpath('//a[@class="keyword"]')
|
||||||
assert len(keywords) == 0
|
assert len(keywords) == 0
|
||||||
|
|
||||||
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
maint = package.PackageBase.Maintainer
|
||||||
|
cookies = {"AURSID": maint.login(Request(), "testPassword")}
|
||||||
post_endpoint = f"{endpoint}/keywords"
|
post_endpoint = f"{endpoint}/keywords"
|
||||||
with client as request:
|
with client as request:
|
||||||
resp = request.post(post_endpoint, data={
|
resp = request.post(post_endpoint, data={
|
||||||
|
@ -1408,7 +1409,8 @@ def test_pkgbase_empty_keywords(client: TestClient, user: User, package: Package
|
||||||
keywords = root.xpath('//a[@class="keyword"]')
|
keywords = root.xpath('//a[@class="keyword"]')
|
||||||
assert len(keywords) == 0
|
assert len(keywords) == 0
|
||||||
|
|
||||||
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
maint = package.PackageBase.Maintainer
|
||||||
|
cookies = {"AURSID": maint.login(Request(), "testPassword")}
|
||||||
post_endpoint = f"{endpoint}/keywords"
|
post_endpoint = f"{endpoint}/keywords"
|
||||||
with client as request:
|
with client as request:
|
||||||
resp = request.post(post_endpoint, data={
|
resp = request.post(post_endpoint, data={
|
||||||
|
@ -1426,3 +1428,16 @@ def test_pkgbase_empty_keywords(client: TestClient, user: User, package: Package
|
||||||
expected = ["abc", "bar", "foo", "test"]
|
expected = ["abc", "bar", "foo", "test"]
|
||||||
for i, keyword in enumerate(keywords):
|
for i, keyword in enumerate(keywords):
|
||||||
assert keyword.text.strip() == expected[i]
|
assert keyword.text.strip() == expected[i]
|
||||||
|
|
||||||
|
|
||||||
|
def test_unauthorized_pkgbase_keywords(client: TestClient, package: Package):
|
||||||
|
with db.begin():
|
||||||
|
user = db.create(User, Username="random_user", Email="random_user",
|
||||||
|
Passwd="testPassword")
|
||||||
|
|
||||||
|
cookies = {"AURSID": user.login(Request(), "testPassword")}
|
||||||
|
with client as request:
|
||||||
|
pkgbase = package.PackageBase
|
||||||
|
endp = f"/pkgbase/{pkgbase.Name}/keywords"
|
||||||
|
response = request.post(endp, cookies=cookies)
|
||||||
|
assert response.status_code == HTTPStatus.UNAUTHORIZED
|
||||||
|
|
|
@ -282,7 +282,8 @@ def test_package_details(user: User, package: Package):
|
||||||
"git_clone_uri_anon": GIT_CLONE_URI_ANON,
|
"git_clone_uri_anon": GIT_CLONE_URI_ANON,
|
||||||
"git_clone_uri_priv": GIT_CLONE_URI_PRIV,
|
"git_clone_uri_priv": GIT_CLONE_URI_PRIV,
|
||||||
"pkgbase": package.PackageBase,
|
"pkgbase": package.PackageBase,
|
||||||
"pkg": package
|
"pkg": package,
|
||||||
|
"comaintainers": [],
|
||||||
})
|
})
|
||||||
|
|
||||||
base = base_template("partials/packages/details.html")
|
base = base_template("partials/packages/details.html")
|
||||||
|
@ -316,6 +317,7 @@ def test_package_details_filled(user: User, package: Package):
|
||||||
"git_clone_uri_priv": GIT_CLONE_URI_PRIV,
|
"git_clone_uri_priv": GIT_CLONE_URI_PRIV,
|
||||||
"pkgbase": package.PackageBase,
|
"pkgbase": package.PackageBase,
|
||||||
"pkg": package,
|
"pkg": package,
|
||||||
|
"comaintainers": [],
|
||||||
"licenses": package.package_licenses,
|
"licenses": package.package_licenses,
|
||||||
"provides": package.package_relations.filter(
|
"provides": package.package_relations.filter(
|
||||||
PackageRelation.RelTypeID == PROVIDES_ID),
|
PackageRelation.RelTypeID == PROVIDES_ID),
|
||||||
|
|
Loading…
Add table
Reference in a new issue