diff --git a/offline/README.md b/offline/README.md index 78b2815..18c273e 100644 --- a/offline/README.md +++ b/offline/README.md @@ -19,6 +19,7 @@ Open replication of the code review benchmark used by companies like [Augment](h | [GitLab Duo](https://about.gitlab.com/gitlab-duo/) | AI code review | | [Graphite](https://graphite.dev/) | AI code review | | [Greptile](https://www.greptile.com/) | AI code review | +| [gx](https://gx.run) | AI code review | | [Propel](https://propelauth.com/) | AI code review | | [KG](https://kg.dev/) | AI code review | | [Kodus](https://kodus.io/) | AI code review | diff --git a/offline/analysis/benchmark_dashboard.html b/offline/analysis/benchmark_dashboard.html index 927d654..0aa4bff 100644 --- a/offline/analysis/benchmark_dashboard.html +++ b/offline/analysis/benchmark_dashboard.html @@ -198,15 +198,17 @@
Best for Complex Code
Best for Ui
Best for Critical Risk
+
Best for Bug Fixes
Small PRs + Performance Optimization (Precision)
Bug Fixes + Cross-File
Java + Authentication
+
Best for Scheduling
Best for Medium Python PRs
Best for Concurrency
-
Best for Bug Fixes
Ruby + Medium PRs
Highest Recall
Ruby + Features
+
Moderate Bugs + File Context
Best for Moderate Bugs
Ruby + Subtle Bugs
Best for Go
@@ -215,7 +217,6 @@
Best for Small PRs
Best for Caching
Best for Large PRs
-
Best for Bug Fixes
Best for Python
High Risk Auth
Best for File Context
@@ -224,7 +225,6 @@
Best for Authentication
Best for Medium Ruby PRs
Best for Medium Java PRs
-
Best for Scheduling
Best for Typescript
Best for Cross-File
Best for Medium PRs
@@ -428,10 +428,10 @@ ` and confirming it renders as text.", + "created_at": "2026-08-15T03:51:38Z" + }, + { + "path": "app/models/topic.rb", + "line": 719, + "body": "**Unsubscribe URL in emails is not authenticated — any recipient can unsubscribe another user**\n\nThe `unsubscribe_url` generated by `Topic#unsubscribe_url` is simply `{topic_url}/unsubscribe` with no token or HMAC. It relies solely on `current_user` (session authentication). However, the URL is placed in email bodies (`unsubscribe_link` locale). If the email is forwarded or the link shared, any logged-in user visiting it will have their own notification level changed (not necessarily the intended user's). More critically, the `List-Unsubscribe` header containing this URL may be processed by email clients that do not carry session cookies, potentially resulting in a redirect loop or error rather than the expected unsubscribe.\n\nEnsures that the unsubscribe mechanism works reliably from email clients and that authentication is handled appropriately for one-click unsubscribe flows.\n\nConsider adding a signed token (HMAC of user_id + topic_id + expiry) to the unsubscribe URL so it can work without an active session, similar to the existing `DigestUnsubscribeKey` pattern in `EmailController`. At minimum, document that the current implementation requires an active session and will not work from email clients that strip cookies. Verify by clicking the List-Unsubscribe link from an email client without an active Discourse session and confirming appropriate behavior.", + "created_at": "2026-08-15T03:51:38Z" + }, + { + "path": "app/assets/javascripts/discourse/templates/topic/unsubscribe.hbs", + "line": 3, + "body": "**XSS via triple-brace rendering of user-controlled topic title**\n\nThe Handlebars template `unsubscribe.hbs` uses `{{{stopNotificiationsText}}}` (triple braces = unescaped HTML). The computed property interpolates `model.fancyTitle` into the i18n string. `fancyTitle` may contain HTML entities from the Discourse `fancy_title` pipeline, but if a topic title contains injected HTML (admin-created or via a bug), it will be rendered unescaped in the browser.\n\nEliminates a stored XSS vector where a malicious topic title could execute JavaScript in the context of users visiting the unsubscribe page.\n\nIn `app/assets/javascripts/discourse/templates/topic/unsubscribe.hbs`, replace `{{{stopNotificiationsText}}}` with a safe approach: either use double-braces `{{stopNotificiationsText}}` and handle the bold formatting differently (e.g., separate the title into its own escaped binding), or sanitize the title before interpolation in the controller. Verify by creating a topic with a title containing `` and confirming the script does not execute on the unsubscribe page.", + "created_at": "2026-08-15T03:51:38Z" + }, + { + "path": "app/controllers/topics_controller.rb", + "line": 107, + "body": "**Handle missing TopicUser record in unsubscribe action to avoid 500s**\n\n`TopicUser.find_by(...)` can return nil (e.g., user never visited the topic or record not created yet). The code immediately dereferences `tu.notification_level`, which will raise and 500 the request. This is realistic on a link reached from email notifications (user may not have prior TopicUser row).\n\nPrevents a production 500 on a common user journey (email → unsubscribe link), improving reliability and supportability.\n\nIn `app/controllers/topics_controller.rb#unsubscribe`, replace `find_by` with a creation path when absent. For example: `tu = TopicUser.get(params[:topic_id], current_user) || TopicUser.create!(user_id: current_user.id, topic_id: params[:topic_id], notification_level: TopicUser.notification_levels[:regular])` (or use existing helper that ensures a row exists—there appears to be logic in TopicUser for ensuring consistency). Then apply the toggle and save. Verify with a controller/request spec: user with no topic_users row can hit `/t/:id/unsubscribe` and gets 200/redirect with notification_level updated/created.", + "created_at": "2026-08-15T04:15:13Z" + }, + { + "path": "app/assets/javascripts/discourse/templates/topic/unsubscribe.hbs", + "line": 4, + "body": "**Prevent HTML injection in topic unsubscribe page by removing triple-stash rendering**\n\nThe unsubscribe template renders `stopNotificiationsText` via triple-stash (`{{{...}}}`), which bypasses escaping. That text includes `{{title}}` interpolated from `model.fancyTitle`, which is derived from topic title and can be user-controlled. This is a reachable XSS path when a user clicks the unsubscribe link.\n\nEliminates a direct, user-triggerable XSS on a route that is explicitly linked from emails and thus likely to be visited from untrusted contexts.\n\nIn `app/assets/javascripts/discourse/templates/topic/unsubscribe.hbs`, change `{{{stopNotificiationsText}}}` to `{{stopNotificiationsText}}` and update `config/locales/client.en.yml` to avoid embedding raw `` tags in the translation. If bolding is required, use a safe pattern: split into separate keys and wrap the title in a `` in the template using escaped title, or use a framework-sanctioned i18n HTML helper that sanitizes interpolations. Verify by setting a topic title containing `