<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://vulnerability.circl.lu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Fri, 02 Oct 2026 15:42:59 +0000</lastBuildDate>
    <item>
      <title>fkie_cve-2026-73605</title>
      <link>https://vulnerability.circl.lu/vuln/fkie_cve-2026-73605</link>
      <description>&lt;p&gt;SiYuan versions before v3.7.4 contain a path traversal vulnerability in the getUniqueFilename endpoint that allows anonymous readers to probe filesystem existence without validation or confinement. Attackers can supply arbitrary absolute paths to determine whether files and directories exist on the host, enabling reconnaissance of the filesystem layout and installed software.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;SiYuan versions before v3.7.4 contain a path traversal vulnerability in the getUniqueFilename endpoint that allows anonymous readers to probe filesystem existence without validation or confinement. Attackers can supply arbitrary absolute paths to determine whether files and directories exist on the host, enabling reconnaissance of the filesystem layout and installed software.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/fkie_cve-2026-73605</guid>
    </item>
    <item>
      <title>GHSA-hf8h-97gm-4x2p — SiYuan: getUniqueFilename passes an unvalidated client-supplied path to the filesystem, giving anonymous readers an exi…</title>
      <link>https://vulnerability.circl.lu/vuln/ghsa-hf8h-97gm-4x2p</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; Go: github.com/siyuan-note/siyuan/kernel&lt;/p&gt;
&lt;p&gt;### Summary&lt;/p&gt;
&lt;p&gt;`/api/file/getUniqueFilename` takes a path from the request body and passes it to a filesystem existence check with no validation, confinement or authorization. The response distinguishes paths that exist from paths that do not, so an anonymous reader in publish mode can probe arbitrary locations on the host, one request per probe. Files and directories both work.&lt;/p&gt;
&lt;p&gt;Every neighbouring file route either requires an administrator or confines the path first.&lt;/p&gt;
&lt;p&gt;### Details&lt;/p&gt;
&lt;p&gt;**Route.** `kernel/api/router.go:289` on master, `:292` on the development branch, `CheckAuth` only.&lt;/p&gt;
&lt;p&gt;**Handler,** `kernel/api/file.go:84`, in full:&lt;/p&gt;
&lt;p&gt;```go
util.ParseJsonArgs(arg, ret, util.BindJsonArg(&amp;#34;path&amp;#34;, &amp;amp;filePath, true, true))
ret.Data = map[string]any{&amp;#34;path&amp;#34;: util.GetUniqueFilename(filePath)}
```&lt;/p&gt;
&lt;p&gt;**The argument binder does no path handling.** `util.BindJsonArg` (`kernel/util/net.go:365`) takes two booleans, `required` (the key must be present) and `rejectEmpty` (the value must be non-empty). That is its entire contract. There is no `filepath.Clean`, no workspace join, no traversal check. An absolute path outside the workspace reaches `gulu.File.IsExist` unmodified.&lt;/p&gt;
&lt;p&gt;**The oracle.** `util/file.go:67`:&lt;/p&gt;
&lt;p&gt;```go
if !gulu.File.IsExist(filePath) {
    return filePath
}
// otherwise loop, returning the first non-existent dir/base (i).ext
```&lt;/p&gt;
&lt;p&gt;Input echoed back means the path does not exist. A `(1)` suffix means it does.&lt;/p&gt;
&lt;p&gt;**The asymmetry.**&lt;/p&gt;
&lt;p&gt;| Route | Middleware |
|---|---|
| `putFile`, `copyFile`,…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; Go: github.com/siyuan-note/siyuan/kernel&lt;/p&gt;
&lt;p&gt;### Summary&lt;/p&gt;
&lt;p&gt;`/api/file/getUniqueFilename` takes a path from the request body and passes it to a filesystem existence check with no validation, confinement or authorization. The response distinguishes paths that exist from paths that do not, so an anonymous reader in publish mode can probe arbitrary locations on the host, one request per probe. Files and directories both work.&lt;/p&gt;
&lt;p&gt;Every neighbouring file route either requires an administrator or confines the path first.&lt;/p&gt;
&lt;p&gt;### Details&lt;/p&gt;
&lt;p&gt;**Route.** `kernel/api/router.go:289` on master, `:292` on the development branch, `CheckAuth` only.&lt;/p&gt;
&lt;p&gt;**Handler,** `kernel/api/file.go:84`, in full:&lt;/p&gt;
&lt;p&gt;```go
util.ParseJsonArgs(arg, ret, util.BindJsonArg(&amp;#34;path&amp;#34;, &amp;amp;filePath, true, true))
ret.Data = map[string]any{&amp;#34;path&amp;#34;: util.GetUniqueFilename(filePath)}
```&lt;/p&gt;
&lt;p&gt;**The argument binder does no path handling.** `util.BindJsonArg` (`kernel/util/net.go:365`) takes two booleans, `required` (the key must be present) and `rejectEmpty` (the value must be non-empty). That is its entire contract. There is no `filepath.Clean`, no workspace join, no traversal check. An absolute path outside the workspace reaches `gulu.File.IsExist` unmodified.&lt;/p&gt;
&lt;p&gt;**The oracle.** `util/file.go:67`:&lt;/p&gt;
&lt;p&gt;```go
if !gulu.File.IsExist(filePath) {
    return filePath
}
// otherwise loop, returning the first non-existent dir/base (i).ext
```&lt;/p&gt;
&lt;p&gt;Input echoed back means the path does not exist. A `(1)` suffix means it does.&lt;/p&gt;
&lt;p&gt;**The asymmetry.**&lt;/p&gt;
&lt;p&gt;| Route | Middleware |
|---|---|
| `putFile`, `copyFile`,…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/ghsa-hf8h-97gm-4x2p</guid>
    </item>
  </channel>
</rss>
