CVE-2023-3906 is a major security issue in GitLab Enterprise Edition (EE), specifically in its asset proxy component. This vulnerability, caused by improper input validation, affects all GitLab EE versions from 12.3 up to but not including 16.2.8, 16.3 up to 16.3.5, and 16.4 up to 16.4.1. In plain English: if you’re running one of these versions, your server is at risk.

This bug allows any authenticated user to bypass the asset proxy by crafting special image URLs. With this, an attacker could potentially leak internal IPs, expose your systems to SSRF (Server Side Request Forgery), or even host malicious images.

References

- GitLab Security Advisory
- CVE Details Page (CVE-2023-3906)

How Does It Work? Understanding Asset Proxy

What’s the asset proxy?
GitLab’s asset proxy feature is designed to help protect users by fetching and caching images embedded in Markdown (or other content) from external sources. This ensures your users don’t leak their IPs or interact with malicious content directly.

Suppose you embed an image like this

!diagram

Normally, GitLab fetches and caches this image through its own asset proxy, sanitizing the URL and validating the remote resource. But, with CVE-2023-3906, an attacker can trick GitLab into skipping the asset proxy altogether.

Exploit Details: Bypassing the Asset Proxy

When GitLab parses an external image URL, it should validate and rewrite it to pass through the proxy. The vulnerable versions improperly handle some crafted URLs — meaning the asset proxy can be skipped.

Let’s say your GitLab asset proxy is at

https://gitlab.example.com/assets/proxy/

You should not be able to embed direct images from the internet or, worse, from your private network. But with CVE-2023-3906, an attacker might use special characters, encoding, or malformed URLs that trick GitLab into accepting a raw image URL.

Sample Markdown Attack

!Bypass

Or, using other bypass tricks with unusual URL encoding, crafted for the vulnerable parser

!Bypass SSRF

What does GitLab do?

- Instead of proxying/caching the image, GitLab allows it to render directly.

Let’s try it with a basic HTML snippet in an issue, merge request, or README

!SSRF Test

If your server is running on a cloud provider (like AWS), this URL could retrieve sensitive metadata. In a properly secured GitLab, the request goes through the proxy and is filtered, blocking internal IP ranges by default.

But with the bug, if you see the image loaded directly, the asset proxy has been bypassed. Logging and network traces confirm the direct connection.

Here’s some pseudocode demonstrating what a vulnerable backend check might look like

# example: flawed input validation
def is_url_allowed(url):
    # Only checks for http/https, and maybe some bad host patterns
    if url.startswith('http://';) or url.startswith('https://';):
        return True
    return False

# an attacker might encode or mangle the URL to bypass naive checks

In reality, the vulnerability is in how GitLab parses and canonicalizes the URLs, not properly catching all the edge cases.

Leak Internal Data: Point the image URL at your internal services (e.g., Jenkins, private APIs).

- Phish Credentials: Trick users into clicking on or auto-loading malicious pages/images.
- Worms and Bots: Use bypassed proxy to reach and scan internal systems through your GitLab instance.

Remember: An attacker must be authenticated on your GitLab instance (e.g., have an account).

Conclusion

CVE-2023-3906 is a strong reminder of how small parsing problems can open big security gaps, especially in widely-used software. If you run GitLab EE, take a moment right now to check your version and upgrade if needed. Even with authentication needed, these issues can be chained with other bugs, so don’t take chances.

Stay safe, and always keep your dependencies up to date!

Further Reading

- GitLab Official Blog on Security Releases
- How GitLab Asset Proxy Works (Docs)
- OWASP SSRF Guide


Questions? Drop them below — let’s keep our platforms secure, together.

Timeline

Published on: 09/29/2023 07:15:00 UTC
Last modified on: 10/02/2023 19:42:00 UTC