CVE-2019-12277
Description
Blogifier 2.3 before 2019-05-11 does not properly restrict APIs, as demonstrated by missing checks for .. in a pathname.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Blogifier 2.3 before 2019-05-11 lacks path traversal checks in APIs, allowing attackers to access restricted files via `..` sequences.
The vulnerability in Blogifier 2.3 (before a fix on 2019-05-11) stems from insufficient input validation in its API endpoints. Specifically, the application fails to properly sanitize or restrict pathnames containing .. sequences, which can be used to navigate outside of intended directories [1]. This is a classic path traversal issue arising from missing checks on user-supplied paths when accessing or listing files [2].
An attacker can exploit this by sending crafted API requests that include ../ sequences in the path parameter. The attack does not require authentication if the affected API endpoints are publicly exposed. No special privileges are needed beyond the ability to make HTTP requests to the vulnerable service [1]. The commit addressing this issue shows that sanitization functions like SanitizePath() and SanitizeFileName() were added in the storage service to prevent path traversal [3].
Successful exploitation allows an attacker to read or list files outside the intended asset storage directory. This could include configuration files, application source code, or other sensitive data stored on the server. By traversing the filesystem, an attacker might gain unauthorized access to information that could be used for further attacks, such as credential theft or system compromise [1].
The vulnerability is fixed in Blogifier versions after 2019-05-11. The fix involved adding path sanitization logic to the IStorageService implementation, ensuring that .. sequences are removed or blocked. Users are strongly advised to update to a version newer than 2.3 from that date or later. No workarounds have been documented, making upgrading the recommended action [3].
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
Blogifier.CoreNuGet | < 2.5.5 | 2.5.5 |
Affected products
3- Blogifier/Blogifierdescription
Patches
13e2ae11f6be8Tightening security in APIs
4 files changed · +39 −10
src/Core/Api/AssetsController.cs+8 −5 modified@@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; +using Microsoft.AspNetCore.Authorization; namespace Core.Api { @@ -40,20 +41,20 @@ public async Task<AssetsModel> Get(int page = 1, string filter = "", string sear { if (filter == "filterImages") { - items = await _store.Find(a => a.AssetType == AssetType.Image, pager); + items = await _store.Find(a => a.AssetType == AssetType.Image, pager, "", !User.Identity.IsAuthenticated); } else if (filter == "filterAttachments") { - items = await _store.Find(a => a.AssetType == AssetType.Attachment, pager); + items = await _store.Find(a => a.AssetType == AssetType.Attachment, pager, "", !User.Identity.IsAuthenticated); } else { - items = await _store.Find(null, pager); + items = await _store.Find(null, pager, "", !User.Identity.IsAuthenticated); } } else { - items = await _store.Find(a => a.Title.Contains(search), pager); + items = await _store.Find(a => a.Title.Contains(search), pager, "", !User.Identity.IsAuthenticated); } if (page < 1 || page > pager.LastPage) @@ -110,11 +111,12 @@ public async Task<AssetItem> Pick(string type, string asset, string post) } /// <summary> - /// Upload file(s) to user data store + /// Upload file(s) to user data store, authentication required /// </summary> /// <param name="files">Selected files</param> /// <returns>Success or internal error</returns> [HttpPost("upload")] + [Authorize] public async Task<IActionResult> Upload(ICollection<IFormFile> files) { try @@ -137,6 +139,7 @@ public async Task<IActionResult> Upload(ICollection<IFormFile> files) /// <param name="url">Relative URL of the file to remove</param> /// <returns></returns> [HttpDelete("remove")] + [Authorize] public IActionResult Remove(string url) { try
src/Core/CoreAPI.xml+1 −1 modified@@ -24,7 +24,7 @@ </member> <member name="M:Core.Api.AssetsController.Upload(System.Collections.Generic.ICollection{Microsoft.AspNetCore.Http.IFormFile})"> <summary> - Upload file(s) to user data store + Upload file(s) to user data store, authentication required </summary> <param name="files">Selected files</param> <returns>Success or internal error</returns>
src/Core/Extensions/StringExtensions.cs+16 −0 modified@@ -212,6 +212,22 @@ static string RemoveExtraHyphen(string text) return text; } + public static string SanitizePath(this string str) + { + if (str.Contains("..") || str.Contains("//")) + throw new ApplicationException("Invalid directory path"); + + return str; + } + + public static string SanitizeFileName(this string str) + { + if (str.Contains("..") || str.Contains("//") || str.Count(x => x == '.') > 1) + throw new ApplicationException("Invalid file name"); + + return str; + } + #endregion } } \ No newline at end of file
src/Core/Services/StorageService.cs+14 −4 modified@@ -32,7 +32,7 @@ public interface IStorageService string GetHtmlTemplate(string template); - Task<IEnumerable<AssetItem>> Find(Func<AssetItem, bool> predicate, Pager pager, string path = ""); + Task<IEnumerable<AssetItem>> Find(Func<AssetItem, bool> predicate, Pager pager, string path = "", bool sanitize = false); Task Reset(); } @@ -254,7 +254,7 @@ public async Task<AssetItem> UploadFromWeb(Uri requestUri, string root, string p } } - public async Task<IEnumerable<AssetItem>> Find(Func<AssetItem, bool> predicate, Pager pager, string path = "") + public async Task<IEnumerable<AssetItem>> Find(Func<AssetItem, bool> predicate, Pager pager, string path = "", bool sanitize = false) { var skip = pager.CurrentPage * pager.ItemsPerPage - pager.ItemsPerPage; var files = GetAssets(path); @@ -267,6 +267,14 @@ public async Task<IEnumerable<AssetItem>> Find(Func<AssetItem, bool> predicate, var page = items.Skip(skip).Take(pager.ItemsPerPage).ToList(); + if (sanitize) + { + foreach (var p in page) + { + p.Path = ""; + } + } + return await Task.FromResult(page); } @@ -331,6 +339,8 @@ public async Task Reset() void VerifyPath(string path) { + path = path.SanitizePath(); + if (!string.IsNullOrEmpty(path)) { var dir = Path.Combine(Location, path); @@ -373,7 +383,7 @@ string GetFileName(string fileName) Random rnd = new Random(); fileName = fileName.Replace("mceclip0", rnd.Next(100000, 999999).ToString()); } - return fileName; + return fileName.SanitizeFileName(); } string GetUrl(string path, string root) @@ -444,7 +454,7 @@ string TitleFromUri(Uri uri) title = title.Replace(" ", "-"); - return title.Replace("/", ""); + return title.Replace("/", "").SanitizeFileName(); } List<AssetItem> MapFilesToAssets(IList<string> assets)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3- github.com/advisories/GHSA-qcx4-gfh8-w5p5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-12277ghsaADVISORY
- github.com/blogifierdotnet/Blogifier/commit/3e2ae11f6be8aab82128f223c2916fab5a408be5ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.