Release asset "external" indicator can be fooled using the "permanent link" feature
Summary
GitLab releases can included asset links, which are arbitrary links provided by the end user.
If the link is "external" - meaning it links to something outside of the current project - the page renders a small arrow icon to indicate that it links to something outside of GitLab (and should therefore be treated with caution):
In the screenshot above, the first link is an "internal" link, and the second is an "external" link.
However, using the permanent links to release assets feature, a user can create a new link that can proxy to any other link. This new link can be used to create a second asset link, which GitLab will recognize as "internal".
For a live demo, visit https://gitlab.com/nfriend/release-test/-/releases/v5.14 and click on "An internal link" (it's not malicious, I promise
More generally, the permanent links to release assets feature can be used to disguise malicious URLs and make them look (more) legitimate. This may have implications for other areas of the product.
Steps to reproduce
Using the Release API, create a release like this:
{
"tag_name": "v5.14",
"ref": "master",
"name": "A release with some suspicious asset link redirects",
"assets": {
"links": [
{ "name": "v5.14.js.map", "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "filepath": "/an/internal/link" },
{ "name": "An internal link", "url": "https://gitlab.com/nfriend/release-test/-/releases/v5.14/downloads/an/internal/link" }
]
}
}
Example Project
See https://gitlab.com/nfriend/release-test/-/releases/v5.14 for a live example.
What is the current bug behavior?
GitLab interprets the URL as "internal" and doesn't render the "external" warning icon next to the link.
What is the expected correct behavior?
GitLab recognizes that the URL ultimately redirects to an external location and labels the asset as "external".
Output of checks
This bug happens on GitLab.com.
Implementation plan
- Treat all release asset links as external
- Deprecate the
external
field in GraphQL and public APIs