<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rohit Sriram</title>
    <description>The latest articles on DEV Community by Rohit Sriram (@rohit_sriram_970bf595b17b).</description>
    <link>https://dev.to/rohit_sriram_970bf595b17b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3939020%2F35ef4f8c-cb32-4790-a7ae-ca6eae92d39d.jpg</url>
      <title>DEV Community: Rohit Sriram</title>
      <link>https://dev.to/rohit_sriram_970bf595b17b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohit_sriram_970bf595b17b"/>
    <language>en</language>
    <item>
      <title>I scanned Plane (50k stars) for bugs. Found 32. Zero false positives.</title>
      <dc:creator>Rohit Sriram</dc:creator>
      <pubDate>Sun, 31 May 2026 13:28:16 +0000</pubDate>
      <link>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-plane-50k-stars-for-bugs-found-32-zero-false-positives-1png</link>
      <guid>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-plane-50k-stars-for-bugs-found-32-zero-false-positives-1png</guid>
      <description>&lt;p&gt;Plane is one of the most popular open source project management tools out there. Over 50,000 GitHub stars, actively maintained, used by real teams in production.&lt;/p&gt;

&lt;p&gt;I scanned it with Faultmark, a code scanner I built that uses a multi-model AI debate to verify findings before surfacing them. Every candidate bug gets challenged by multiple models before it makes the final list. The goal is zero false positives.&lt;/p&gt;

&lt;p&gt;The result: 32 confirmed bugs, 0 false positives.&lt;/p&gt;

&lt;p&gt;Some of them are bad. Here are the ones that stood out.&lt;/p&gt;

&lt;p&gt;GitHub and GitLab OAuth are both completely broken&lt;/p&gt;

&lt;p&gt;In the space app, a local variable named base_host shadows the imported base_host function on line 61 of github.py. From that point forward, every call to base_host(request=request, is_space=True) fails with TypeError: 'str' object is not callable. The same shadowing pattern exists in the GitLab callback file. Anyone trying to log in via GitHub or GitLab on the space app gets a 500 error and never gets authenticated.&lt;/p&gt;

&lt;p&gt;Existing users are treated as new signups, and new users are treated as returning logins&lt;/p&gt;

&lt;p&gt;In adapter/base.py line 299, is_signup = bool(user) has the logic completely inverted. If the user already exists in the database, bool(user) is True, so is_signup is True. If the user is new and doesn't exist yet, is_signup is False. The onboarding flow triggers for returning users and gets skipped for new registrations.&lt;/p&gt;

&lt;p&gt;Project invitations are fully broken in two separate ways&lt;/p&gt;

&lt;p&gt;Bug 1: In invite.py line 105, project_invitations gets reassigned to the list returned by bulk_create(), then .delay() is called on that list. Lists do not have a .delay() method. Every invitation crashes with AttributeError: 'list' object has no attribute 'delay'.&lt;/p&gt;

&lt;p&gt;Bug 2: In the same file at lines 60-64, .role is called directly on a QuerySet returned by .filter() instead of calling .first() first. AttributeError: 'QuerySet' object has no attribute 'role' on every invitation creation attempt.&lt;/p&gt;

&lt;p&gt;Any workspace member can modify another member's preferences&lt;/p&gt;

&lt;p&gt;In workspace/user_preference.py line 64, the query that fetches the preference to update does not filter by request.user. Any authenticated workspace member can send a PATCH request with another user's preference key and modify that user's pinned items and sort order. The fix is adding user=request.user to the filter.&lt;/p&gt;

&lt;p&gt;LLM output is passed to the frontend without HTML escaping&lt;/p&gt;

&lt;p&gt;In external/base.py, the response from the AI assistant goes through text.replace('\n', '&lt;br&gt;') without first escaping HTML entities. The resulting response_html field contains raw HTML. If rendered as innerHTML on the frontend, any LLM output containing script tags becomes stored XSS.&lt;/p&gt;

&lt;p&gt;Mention notifications go to the wrong user&lt;/p&gt;

&lt;p&gt;In notification_task.py line 576, EmailNotificationLog is created with receiver_id=subscriber instead of receiver_id=mention_id. The subscriber variable is the last value from an outer loop. The mentioned user never receives the email, and the log is recorded against the wrong person.&lt;/p&gt;

&lt;p&gt;Updating a saved view silently wipes all its filters&lt;/p&gt;

&lt;p&gt;In view.py, IssueViewSerializer.update() unconditionally overwrites the query field regardless of whether filters were included in the PATCH request. Renaming a view by sending {"name": "New Name"} resets all its saved filters to empty with no error and no warning.&lt;/p&gt;

&lt;p&gt;Deleting an estimate point bulk-updates all issues on the first loop iteration&lt;/p&gt;

&lt;p&gt;In estimate/base.py, issues.update(...) is called inside a for issue in issues: loop. issues.update() operates on the full queryset. On the first iteration, every issue gets updated. The loop then runs N-1 more times redundantly.&lt;/p&gt;

&lt;p&gt;Those are the highlights. The other 24 confirmed bugs cover nil dereferences across cycle archiving, issue relation deletion, intake issue handling, search filtering, page access, and asset deletion. The full list is in the GitHub issue filed on the Plane repo.&lt;/p&gt;

&lt;p&gt;Every finding was verified against the actual source files before being reported. The scan took about 10 minutes.&lt;/p&gt;

&lt;p&gt;Faultmark is live at faultmark.com. Free tier includes 3 scans/month. If you want to see what it finds in your own codebase, try it.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>I scanned 5 open source repos for bugs. 50 real findings, 4 false positives.</title>
      <dc:creator>Rohit Sriram</dc:creator>
      <pubDate>Wed, 27 May 2026 05:28:14 +0000</pubDate>
      <link>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-5-open-source-repos-for-bugs-50-real-findings-4-false-positives-3h40</link>
      <guid>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-5-open-source-repos-for-bugs-50-real-findings-4-false-positives-3h40</guid>
      <description>&lt;p&gt;Last week I built Faultmark, an AI code scanner that uses a multi-model debate to verify bugs before surfacing them. One AI finds candidates, other AI models challenge each finding, and anything that can't survive the debate gets dropped. The goal is zero false positives.&lt;/p&gt;

&lt;p&gt;To test it before launch, I scanned 5 real open source repos: dub, documenso, cal.com, formbricks, and trigger.dev.&lt;/p&gt;

&lt;p&gt;Results across all 5: 54 total findings, 50 real bugs, 4 false positives. 7 of those bugs have already been fixed or are in the process of being merged by maintainers.&lt;/p&gt;

&lt;p&gt;Here's what I found in documenso alone, since it had the most findings.&lt;/p&gt;

&lt;p&gt;documenso: 24 bugs, 0 false positives&lt;/p&gt;

&lt;p&gt;The scan flagged issues across authentication flows, form handling, and error states. Most were real bugs that had been sitting in the codebase unnoticed. 7 of them were pushed by a maintainer within a few days of the issue being filed.&lt;/p&gt;

&lt;p&gt;The kind of bugs that come up are not obscure edge cases. They are missing null checks, stale state after form submissions, incorrect error handling, and race conditions that only show up under specific conditions. The kind of thing that passes code review because everything looks fine at a glance.&lt;/p&gt;

&lt;p&gt;Why the debate layer matters&lt;/p&gt;

&lt;p&gt;Running a single AI model against a codebase produces a lot of noise. You get flagged variables that look suspicious but are fine in context, missing checks that are actually handled upstream, and patterns that match known bugs but do not apply here.&lt;/p&gt;

&lt;p&gt;The debate layer cuts that noise. When two models disagree on a finding, it gets dropped or downgraded. Only the bugs that survive that cross-examination get reported. That is how we got to 4 false positives across 50 findings.&lt;/p&gt;

&lt;p&gt;What is next&lt;/p&gt;

&lt;p&gt;Faultmark is live at faultmark.com. Free tier gets 3 scans/month. Pro is up to unlimited scans with deeper coverage and the full debate layer.&lt;/p&gt;

&lt;p&gt;If you want to see what it finds on your codebase, try it. If you maintain an open source repo and want a free scan, reply here and I will run one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I scanned two popular open-source repos with an AI code scanner. Here's what I found.</title>
      <dc:creator>Rohit Sriram</dc:creator>
      <pubDate>Mon, 18 May 2026 22:47:30 +0000</pubDate>
      <link>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-two-popular-open-source-repos-with-an-ai-code-scanner-heres-what-i-found-1b9c</link>
      <guid>https://dev.to/rohit_sriram_970bf595b17b/i-scanned-two-popular-open-source-repos-with-an-ai-code-scanner-heres-what-i-found-1b9c</guid>
      <description>&lt;p&gt;I've been building Faultmark, an AI code scanner that uses a multi-model &lt;br&gt;
debate to verify bugs before showing them to you. One AI finds candidates, &lt;br&gt;
a second challenges each finding, a third breaks ties. Nothing gets surfaced &lt;br&gt;
unless it survives that process.&lt;/p&gt;

&lt;p&gt;I ran it on two real codebases as a test.&lt;/p&gt;

&lt;p&gt;dub.co (20k GitHub stars) — 6 confirmed bugs, 0 false positives&lt;/p&gt;

&lt;p&gt;The two most interesting findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Missing await on sendEmail calls in the CSV import flow. Both sends fire and forget, &lt;br&gt;
so errors are silently swallowed and users may never receive import confirmation emails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logic inversion in GET /api/customers. Any caller passing an explicit programId &lt;br&gt;
has it silently overwritten with the workspace default. Every filtered customer &lt;br&gt;
query is broken.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;documenso (8k GitHub stars) — 24 confirmed bugs, 0 false positives&lt;/p&gt;

&lt;p&gt;The most critical ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;handleInitialsFieldClick always returns null. The user types their initials, &lt;br&gt;
the dialog stores the input, but the return statement sends the original null &lt;br&gt;
value instead of what the user typed. Initials are never actually saved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;removeValue crashes when removing the last dropdown option. After splice(index, 1), &lt;br&gt;
the code reads newValues[index] which is now undefined. Runtime crash.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two progress bars divide by zero when a recipient has zero required fields, &lt;br&gt;
producing width: 'Infinity%' and breaking rendering.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All findings were filed as GitHub issues with the maintainers before this post.&lt;/p&gt;

&lt;p&gt;The tool is at faultmark.com if you want to run it on your own repo.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>security</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
