Exposed in Translation: Weblate Static Asset Bypass
Vulnerability ID: CVE-2026-21889
CVSS Score: 2.3
Published: 2026-01-14
A classic architectural disconnect between the web server and the application logic allows unauthenticated users to access private project screenshots in Weblate by bypassing Django's access controls entirely.
TL;DR
Weblate, a popular localization tool, relied on the web server (Nginx/Apache) to serve media files directly for performance. This created a bypass where private screenshots were served as public static assets, completely ignoring application-level permissions. An attacker who can guess or discover the filename of a screenshot can view it without authentication. The fix involves moving media serving back into the application layer.
Technical Details
- CWE: CWE-284 (Improper Access Control)
- CVSS v4.0: 2.3 (Low)
- Attack Vector: Network
- Attack Complexity: High (Requires guessing filenames)
- Privileges: None / Low
- Status: Patched
Affected Systems
- Weblate < 5.15.2
-
Weblate: < 5.15.2 (Fixed in:
5.15.2)
Code Analysis
Commit: a6eb5fd
Implemented ScreenshotView to enforce permissions and removed static media serving recommendations
class ScreenshotView(ScreenshotBaseView):
def get(self, request: AuthenticatedHttpRequest, *args, **kwargs) -> FileResponse:
obj = self.get_object()
return FileResponse(obj.image.open()...
Mitigation Strategies
- Upgrade Weblate to version 5.15.2+
- Remove static media aliases from Nginx/Apache configuration
- Audit existing media files for sensitive data exposure
Remediation Steps:
- Pull the latest Weblate docker image or upgrade via pip.
- Edit the Nginx configuration file (usually in /etc/nginx/sites-enabled/).
- Remove the 'location /media/' block entirely.
- Restart the Nginx service.
- Verify that accessing a screenshot URL directly now requires a session cookie.
References
Read the full report for CVE-2026-21889 on our website for more details including interactive diagrams and full exploit analysis.
Top comments (0)