<?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://cve.radiocsirt.org</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 13:54:50 +0000</lastBuildDate>
    <item>
      <title>CVE-2026-35490 — changedetection.io has an Authentication Bypass via Decorator Ordering</title>
      <link>https://cve.radiocsirt.org/vuln/cve-2026-35490</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; dgtlmoon changedetection.io&lt;/p&gt;
&lt;p&gt;changedetection.io is a free open source web page change detection tool. Prior to 0.54.8, the @login_optionally_required decorator is placed before (outer to) @blueprint.route() instead of after it. In Flask, @route() must be the outermost decorator because it registers the function it receives. When the order is reversed, @route() registers the original undecorated function, and the auth wrapper is never in the call chain. This silently disables authentication on these routes. This vulnerability is fixed in 0.54.8.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; dgtlmoon changedetection.io&lt;/p&gt;
&lt;p&gt;changedetection.io is a free open source web page change detection tool. Prior to 0.54.8, the @login_optionally_required decorator is placed before (outer to) @blueprint.route() instead of after it. In Flask, @route() must be the outermost decorator because it registers the function it receives. When the order is reversed, @route() registers the original undecorated function, and the auth wrapper is never in the call chain. This silently disables authentication on these routes. This vulnerability is fixed in 0.54.8.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://cve.radiocsirt.org/vuln/cve-2026-35490</guid>
    </item>
    <item>
      <title>GHSA-jmrh-xmgh-x9j4 — changedetection.io Vulnerable to Authentication Bypass via Decorator Ordering</title>
      <link>https://cve.radiocsirt.org/vuln/ghsa-jmrh-xmgh-x9j4</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: changedetection.io&lt;/p&gt;
&lt;p&gt;### Summary&lt;/p&gt;
&lt;p&gt;On 13 routes across 5 blueprint files, the `@login_optionally_required` decorator is placed **before** (outer to) `@blueprint.route()` instead of after it. In Flask, `@route()` must be the outermost decorator because it registers the function it receives. When the order is reversed, `@route()` registers the **original undecorated function**, and the auth wrapper is never in the call chain. This silently disables authentication on these routes.&lt;/p&gt;
&lt;p&gt;The developer correctly uses the decorator on 30+ other routes with the proper order, making this a classic consistency gap.&lt;/p&gt;
&lt;p&gt;### Details&lt;/p&gt;
&lt;p&gt;**Correct order (used on 30+ routes):**
```python
@blueprint.route(&amp;#39;/settings&amp;#39;, methods=[&amp;#39;GET&amp;#39;])
@login_optionally_required
def settings():
    ...
```&lt;/p&gt;
&lt;p&gt;**Incorrect order (13 vulnerable routes):**
```python
@login_optionally_required          # ← Applied to return value of @route, NOT the view
@blueprint.route(&amp;#39;/backups/download/&amp;lt;filename&amp;gt;&amp;#39;)  # ← Registers raw function
def download_backup(filename):
    ...
```&lt;/p&gt;
&lt;p&gt;## POC
```
=== PHASE 1: Confirm Authentication is Required ===&lt;/p&gt;
&lt;p&gt;$ curl -s -o /dev/null -w &amp;#34;%{http_code}&amp;#34; http://127.0.0.1:5557/
Main page:     HTTP 302 -&amp;gt; http://127.0.0.1:5557/login?next=/
$ curl -s -o /dev/null -w &amp;#34;%{http_code}&amp;#34; http://127.0.0.1:5557/settings
Settings page: HTTP 302 (auth required, redirects to login)&lt;/p&gt;
&lt;p&gt;Password is set. Unauthenticated requests to / and /settings
are properly redirected to /login.&lt;/p&gt;
&lt;p&gt;=== PHASE 2: Authentication Bypass on Backup Routes ===
(All r…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; PyPI: changedetection.io&lt;/p&gt;
&lt;p&gt;### Summary&lt;/p&gt;
&lt;p&gt;On 13 routes across 5 blueprint files, the `@login_optionally_required` decorator is placed **before** (outer to) `@blueprint.route()` instead of after it. In Flask, `@route()` must be the outermost decorator because it registers the function it receives. When the order is reversed, `@route()` registers the **original undecorated function**, and the auth wrapper is never in the call chain. This silently disables authentication on these routes.&lt;/p&gt;
&lt;p&gt;The developer correctly uses the decorator on 30+ other routes with the proper order, making this a classic consistency gap.&lt;/p&gt;
&lt;p&gt;### Details&lt;/p&gt;
&lt;p&gt;**Correct order (used on 30+ routes):**
```python
@blueprint.route(&amp;#39;/settings&amp;#39;, methods=[&amp;#39;GET&amp;#39;])
@login_optionally_required
def settings():
    ...
```&lt;/p&gt;
&lt;p&gt;**Incorrect order (13 vulnerable routes):**
```python
@login_optionally_required          # ← Applied to return value of @route, NOT the view
@blueprint.route(&amp;#39;/backups/download/&amp;lt;filename&amp;gt;&amp;#39;)  # ← Registers raw function
def download_backup(filename):
    ...
```&lt;/p&gt;
&lt;p&gt;## POC
```
=== PHASE 1: Confirm Authentication is Required ===&lt;/p&gt;
&lt;p&gt;$ curl -s -o /dev/null -w &amp;#34;%{http_code}&amp;#34; http://127.0.0.1:5557/
Main page:     HTTP 302 -&amp;gt; http://127.0.0.1:5557/login?next=/
$ curl -s -o /dev/null -w &amp;#34;%{http_code}&amp;#34; http://127.0.0.1:5557/settings
Settings page: HTTP 302 (auth required, redirects to login)&lt;/p&gt;
&lt;p&gt;Password is set. Unauthenticated requests to / and /settings
are properly redirected to /login.&lt;/p&gt;
&lt;p&gt;=== PHASE 2: Authentication Bypass on Backup Routes ===
(All r…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://cve.radiocsirt.org/vuln/ghsa-jmrh-xmgh-x9j4</guid>
    </item>
  </channel>
</rss>
