<?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: Avash Karn</title>
    <description>The latest articles on DEV Community by Avash Karn (@avash_karn).</description>
    <link>https://dev.to/avash_karn</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%2F3933233%2F56290230-cdb4-4f0e-9175-c3fe094af7d9.png</url>
      <title>DEV Community: Avash Karn</title>
      <link>https://dev.to/avash_karn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avash_karn"/>
    <language>en</language>
    <item>
      <title>SQL Injection Protection in Flask: A Practical Guide. Part 5 of e2ee chat series</title>
      <dc:creator>Avash Karn</dc:creator>
      <pubDate>Fri, 29 May 2026 03:01:29 +0000</pubDate>
      <link>https://dev.to/avash_karn/sql-injection-protection-in-flask-a-practical-guide-part-5-of-e2ee-chat-series-1gjk</link>
      <guid>https://dev.to/avash_karn/sql-injection-protection-in-flask-a-practical-guide-part-5-of-e2ee-chat-series-1gjk</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most developers think their database is safe. It's not. SQL injection attacks can destroy everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SQL Injection?
&lt;/h2&gt;

&lt;p&gt;If you write code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM users WHERE username = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An attacker types: &lt;code&gt;admin' OR '1'='1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your query becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;All users exposed.&lt;/strong&gt; Game over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Parameterized Queries
&lt;/h2&gt;

&lt;p&gt;Never use f-strings for queries. Use parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SQLAlchemy&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SQLAlchemy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLAlchemy automatically escapes dangerous characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Database treats input as DATA, not CODE&lt;/li&gt;
&lt;li&gt;Even if attacker types &lt;code&gt;admin' OR '1'='1'&lt;/code&gt;, it's treated as literal string&lt;/li&gt;
&lt;li&gt;Safe from injection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Using f-strings for queries ❌&lt;/li&gt;
&lt;li&gt;Not validating input ❌&lt;/li&gt;
&lt;li&gt;Trusting user data ❌&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Always use parameterized queries. Never build queries with string formatting.&lt;/p&gt;

</description>
      <category>database</category>
      <category>python</category>
      <category>security</category>
      <category>sql</category>
    </item>
    <item>
      <title>Building an E2EE Chat App in Flask - Part 4: Real-Time Messaging with SocketIO</title>
      <dc:creator>Avash Karn</dc:creator>
      <pubDate>Tue, 26 May 2026 10:04:11 +0000</pubDate>
      <link>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-4-real-time-messaging-with-socketio-2ll7</link>
      <guid>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-4-real-time-messaging-with-socketio-2ll7</guid>
      <description>&lt;h2&gt;
  
  
  Building an E2EE Chat App in Flask - Part 4: Real-Time Messaging with SocketIO
&lt;/h2&gt;

&lt;p&gt;Hey! So far we covered encryption, passwords, and file uploads. But how do messages show up instantly without refreshing?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Polling vs Real-Time
&lt;/h2&gt;

&lt;p&gt;Without real-time, your app is dead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User sends message&lt;/li&gt;
&lt;li&gt;Other user refreshes page&lt;/li&gt;
&lt;li&gt;Message appears or they don't refresh message won't appear&lt;/li&gt;
&lt;li&gt;Sucks, right?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: SocketIO
&lt;/h2&gt;

&lt;p&gt;WebSockets = open connection between client and server. Message goes instantly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_socketio&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;join_room&lt;/span&gt;

&lt;span class="n"&gt;socketio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SocketIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cors_allowed_origins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@socketio.on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;send_message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;channel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Save to database
&lt;/span&gt;    &lt;span class="n"&gt;new_post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Send to all users in channel
&lt;/span&gt;    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;receive_message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User sends message&lt;/li&gt;
&lt;li&gt;Server receives via flask-SocketIO&lt;/li&gt;
&lt;li&gt;Server saves to database&lt;/li&gt;
&lt;li&gt;Server broadcasts to all users in channel&lt;/li&gt;
&lt;li&gt;Everyone gets message INSTANTLY&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;No refresh needed. No delay. Real-time = better UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Part 5: Database design and security.&lt;/p&gt;

&lt;p&gt;Questions?&lt;/p&gt;

</description>
      <category>backend</category>
      <category>python</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an E2EE Chat App in Flask - Part 3: Keeping File Uploads Safe</title>
      <dc:creator>Avash Karn</dc:creator>
      <pubDate>Sat, 23 May 2026 02:43:26 +0000</pubDate>
      <link>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-3-keeping-file-uploads-safe-iid</link>
      <guid>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-3-keeping-file-uploads-safe-iid</guid>
      <description>&lt;p&gt;Okay hi, so imagine you have a mailbox at your house. Anyone can put things in it, am I right or am I right? What if someone puts a bomb in there? Or trash? You need to check what goes in before it causes problems.&lt;/p&gt;

&lt;p&gt;That's what file uploads are like. Users can upload anything. We need to stop the bad stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Bad Files
&lt;/h2&gt;

&lt;p&gt;When I first built my chat app, I didn't think about what users could upload. They could upload:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files with viruses hidden inside&lt;/li&gt;
&lt;li&gt;Really huge files that break the app&lt;/li&gt;
&lt;li&gt;Weird file types that cause problems&lt;/li&gt;
&lt;li&gt;Files with tricky names designed to hack the system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's like leaving your house door open and hoping bad people don't come in. Spoiler: they will.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Solution: Check Everything
&lt;/h2&gt;

&lt;p&gt;I learned to be a security guard for my app. Here's what I do:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Only Accept Certain File Types
&lt;/h3&gt;

&lt;p&gt;First, I made a python Set of file types I actually want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ALLOWED_EXTENSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mp4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mov&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I only allow images (png, jpg, gif) and videos (mp4, mov). That's it. No .exe files. No .zip files. Nothing unsafe.&lt;/p&gt;

&lt;p&gt;Then I check every file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;allowed_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_EXTENSIONS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that code just says: "Does the file have a dot? Is it one of our allowed types? If yes, cool. If no, reject it."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Clean Up Bad Filenames
&lt;/h3&gt;

&lt;p&gt;Here's something sneaky: attackers might upload a file named something like "../../../admin.php" to try to escape the upload folder and hack the system.&lt;/p&gt;

&lt;p&gt;So I use a function that removes all the dangerous stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;werkzeug.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;secure_filename&lt;/span&gt;

&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;secure_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If someone uploads "../../admin.php", this function turns it into "admin.php" (harmless).&lt;/p&gt;

&lt;p&gt;If someone uploads "file (1) [2023].jpg", it cleans it up too.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Organize Files by Type
&lt;/h3&gt;

&lt;p&gt;After the file is safe, I check what type it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_file_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mp4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mov&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;video&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if someone uploads a video, I store it in the videos folder. Images go in the images folder. Everything stays organized and safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Actually Works
&lt;/h2&gt;

&lt;p&gt;Think about it like airport security:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Whitelist&lt;/strong&gt; = Only let through what's allowed (like a passenger list)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean names&lt;/strong&gt; = Remove anything suspicious (like checking luggage)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organize&lt;/strong&gt; = Put things in the right place (like baggage claim)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don't do these checks, bad stuff gets through.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happened
&lt;/h2&gt;

&lt;p&gt;I built this without thinking about security. Then I realized: what if someone uploads a virus? What if they upload a 1GB file? What if they try to hack the system with a weird filename?&lt;/p&gt;

&lt;p&gt;So I added these checks. Now my app is safer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Lesson
&lt;/h2&gt;

&lt;p&gt;Never, ever trust what users do. Always assume someone is trying to break your app. Check everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Part 4 is about real-time messaging. How do messages update instantly without refreshing? WebSockets.&lt;/p&gt;

&lt;p&gt;Let me know what you think!&lt;/p&gt;

</description>
      <category>python</category>
      <category>security</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an E2EE Chat App in Flask - Part 2: Secure Password Storage</title>
      <dc:creator>Avash Karn</dc:creator>
      <pubDate>Fri, 22 May 2026 09:26:50 +0000</pubDate>
      <link>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-2-secure-password-storage-3god</link>
      <guid>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-2-secure-password-storage-3god</guid>
      <description>&lt;p&gt;Hey everyone! Part 1 explained encryption. Now let's secure passwords.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Plain Text Passwords
&lt;/h2&gt;

&lt;p&gt;In my first version, I stored passwords like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p_word&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# LOGIN
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is TERRIBLE because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If database leaks, everyone's passwords exposed&lt;/li&gt;
&lt;li&gt;No hashing = no protection&lt;/li&gt;
&lt;li&gt;One breach = account takeover&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: Werkzeug Password Hashing
&lt;/h2&gt;

&lt;p&gt;Use werkzeug.security to hash passwords:&lt;/p&gt;

&lt;h3&gt;
  
  
  Registration:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;werkzeug.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generate_password_hash&lt;/span&gt;

&lt;span class="n"&gt;hashed_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_password_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Login:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;werkzeug.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;check_password_hash&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;check_password_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;logged_in&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="c1"&gt;# USER LOGGED IN
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Passwords are hashed (one-way)&lt;/li&gt;
&lt;li&gt;Hash can't be reversed&lt;/li&gt;
&lt;li&gt;Even if leaked, passwords stay safe&lt;/li&gt;
&lt;li&gt;Industry standard&lt;/li&gt;
&lt;li&gt;Built into Flask ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Passwords must NEVER be stored in plain text. Ever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3 Coming
&lt;/h2&gt;

&lt;p&gt;File uploads and validation.&lt;/p&gt;

&lt;p&gt;Questions? Drop them below!&lt;/p&gt;

</description>
      <category>python</category>
      <category>security</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an E2EE Chat App in Flask - Part 1: Why Encryption Matters</title>
      <dc:creator>Avash Karn</dc:creator>
      <pubDate>Fri, 22 May 2026 07:33:47 +0000</pubDate>
      <link>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-1-why-encryption-matters-2lo4</link>
      <guid>https://dev.to/avash_karn/building-an-e2ee-chat-app-in-flask-part-1-why-encryption-matters-2lo4</guid>
      <description>&lt;p&gt;Hey everyone! I'm building an encrypted chat application in Flask and documenting the journey. Here's Part 1.&lt;br&gt;
Why E2EE Matters&lt;br&gt;
Most messaging apps claim to be secure, but they're not. Your messages sit on their servers where anyone with access can read them.&lt;/p&gt;

&lt;p&gt;End-to-End Encryption (E2EE) = only you and the recipient can read messages. The server can't see anything.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
WhatsApp uses E2EE. Facebook Messenger doesn't. Your choice matters.&lt;/p&gt;

&lt;p&gt;Why I Built This&lt;br&gt;
I wanted to understand encryption by building it, not just reading about it. This project taught me way more than any tutorial.&lt;/p&gt;

&lt;p&gt;What's Next&lt;br&gt;
Part 2: How to handle passwords safely without storing them in plain text.&lt;/p&gt;

&lt;p&gt;Questions? Drop them in comments!&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>python</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
