<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Pontakorn's Blog]]></title><description><![CDATA[Pontakorn's Blog]]></description><link>https://blog.pontakorn.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 12:03:34 GMT</lastBuildDate><atom:link href="https://blog.pontakorn.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[This is how I built Mugen Quiz, an April Fool's day project.]]></title><description><![CDATA[On the. day before April Fool's day, I got a silly idea for the April Fool's day project. It's similar to Akinator except it only determines your favorite language, has only Yes and No, and never ends. I tried to do it simple way. Let's take a look a...]]></description><link>https://blog.pontakorn.dev/this-is-how-i-built-mugen-quiz-an-april-fools-day-project</link><guid isPermaLink="true">https://blog.pontakorn.dev/this-is-how-i-built-mugen-quiz-an-april-fools-day-project</guid><category><![CDATA[React]]></category><category><![CDATA[Preact]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[personal]]></category><category><![CDATA[watercooler]]></category><dc:creator><![CDATA[Pontakorn Paesaeng]]></dc:creator><pubDate>Sat, 02 Apr 2022 14:59:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648909487125/t1Ty6hzCX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On the. day before April Fool's day, I got a silly idea for the April Fool's day project. It's similar to <a target="_blank" href="https://en.akinator.com/">Akinator</a> except it only determines your favorite language, has only Yes and No, and never ends. I tried to do it simple way. Let's take a look at my project. The code is on <a target="_blank" href="https://github.com/pontakornth/mugen-quiz">this repo.</a>.</p>
<h2 id="heading-project-structure">Project structure</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648909946028/zFi_5py_N.png" alt="Screen Shot 2565-04-02 at 21.32.09.png" /></p>
<p>The project is so simple to the point that I don't even create a folder for components. The <code>page</code> directory is for the home page and quiz page. The <code>app.tsx</code> file contains logic for this project. The <code>data</code> directory contains questions for the quiz. </p>
<p>I use CSS file for styling as there is no benefit using complicated system such as CSS Module or CSS-in-JS. Tailwind is a good alternative choice.</p>
<h2 id="heading-source-of-apptsx">Source of app.tsx</h2>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Logo } <span class="hljs-keyword">from</span> <span class="hljs-string">'./logo'</span>
<span class="hljs-keyword">import</span> Router, { route, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">'preact-router'</span>
<span class="hljs-keyword">import</span> { h } <span class="hljs-keyword">from</span> <span class="hljs-string">'preact'</span>
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'preact/hooks'</span>
<span class="hljs-keyword">import</span> { Index } <span class="hljs-keyword">from</span> <span class="hljs-string">'./pages/index'</span>
<span class="hljs-keyword">import</span> { Quiz, QuizProps } <span class="hljs-keyword">from</span> <span class="hljs-string">'./pages/quiz'</span>
<span class="hljs-keyword">import</span> { questions } <span class="hljs-keyword">from</span> <span class="hljs-string">'./data/questions'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getQuestion</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> questions[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * questions.length)]
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [questionNumber, setQuestionNumber] = useState(<span class="hljs-number">1</span>)
  <span class="hljs-keyword">const</span> [started, setStarted] = useState(<span class="hljs-literal">false</span>)
  <span class="hljs-keyword">const</span> [currentQuestion, setCurrentQuestion] = useState&lt;<span class="hljs-built_in">string</span>&gt;(getQuestion())

  <span class="hljs-keyword">const</span> handleNext = <span class="hljs-function">() =&gt;</span> {
    setStarted(<span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> <span class="hljs-literal">true</span>)
    setQuestionNumber(<span class="hljs-function"><span class="hljs-params">n</span> =&gt;</span> n + <span class="hljs-number">1</span>)
    setCurrentQuestion(<span class="hljs-function"><span class="hljs-params">oldQuestion</span> =&gt;</span> {
      <span class="hljs-keyword">let</span> newQuestion: <span class="hljs-built_in">string</span>
      <span class="hljs-keyword">do</span> {
        newQuestion = getQuestion()
      } <span class="hljs-keyword">while</span> (newQuestion == oldQuestion)
      <span class="hljs-keyword">return</span> newQuestion
    })
    route(<span class="hljs-string">`/questions/<span class="hljs-subst">${questionNumber}</span>`</span>)
  }
  <span class="hljs-keyword">return</span> (
    &lt;&gt;
      &lt;Router&gt;
        &lt;Route component={<span class="hljs-function">() =&gt;</span> &lt;Index onNext={handleNext} /&gt;} path=<span class="hljs-string">"/"</span> /&gt;
        &lt;Route component={<span class="hljs-function">(<span class="hljs-params">{ questionNumber }: Partial&lt;QuizProps&gt;</span>) =&gt;</span> &lt;Quiz onNext={handleNext} questionNumber={questionNumber} currentQuestion={currentQuestion} started={started} /&gt;} path=<span class="hljs-string">"/questions/:questionNumber"</span> /&gt;
      &lt;/Router&gt;
    &lt;/&gt;
  )
}
</code></pre>
<p>Note that I use <a target="_blank" href="https://github.com/preactjs/preact-router">preact-router</a>. It render components inside base on the <code>path</code> prop. It's not quite friendly for TypeScript because I would need to define the component to accept <code>path</code> props or have global definitions similar to how <code>css</code> props work. I don't know how to do it yet.  Preact router provides <code>Route</code> component so I can use the router in TypeScript friendly way.</p>
<p>There is nothing interesting in <code>Index</code> page component. Let's take a look at <code>Quiz</code> page.</p>
<h2 id="heading-source-code-of-quiztsx">Source code of quiz.tsx</h2>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { route } <span class="hljs-keyword">from</span> <span class="hljs-string">"preact-router"</span>
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"preact/hooks"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> QuizProps {
    onNext: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">void</span>,
    questionNumber: <span class="hljs-built_in">number</span> | <span class="hljs-literal">undefined</span>,
    currentQuestion: <span class="hljs-built_in">string</span>,
    started: <span class="hljs-built_in">boolean</span>,
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Quiz</span>(<span class="hljs-params">{ onNext, questionNumber, currentQuestion, started }: QuizProps</span>) </span>{
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (!started) {
            <span class="hljs-comment">// Go home. You haven't visit home yet.</span>
            route(<span class="hljs-string">"/"</span>, <span class="hljs-literal">true</span>)
        }
    }, [])
    <span class="hljs-keyword">return</span> (
        &lt;&gt;
            &lt;h1&gt;Question {questionNumber}&lt;/h1&gt;
            &lt;p&gt;{currentQuestion}&lt;/p&gt;
            &lt;button onClick={onNext}&gt;Yes&lt;/button&gt;
            &lt;button onClick={onNext}&gt;No&lt;/button&gt;
        &lt;/&gt;
    )
}
</code></pre>
<p>And that's the prank, no matter what you clicked, you only get another random question. Nothing is saved. Nothing is used to determine your favorite language.</p>
<p>This projected fooled my friends to think that the quiz will eventually end. I want this prank to be obvious so I put joke questions such as "What is your favorite TV show?" there.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This is a simple project created in a simple way. There is no need for CSS-in-JS, state management or advanced build tools configuration although I used Vite to simplify development setup. It can even be simplified more such as don't use any JavaScript framework.  </p>
<p>I hope this post can be a example for anyone who have no idea what to build yet.  I am looking forward to see your projects.</p>
]]></content:encoded></item><item><title><![CDATA[Why do we need unit test? And how to write it in Python?]]></title><description><![CDATA[A good program must be correct. Try to imagine getting negative salary because of a bug. To verify how the program work, you must test it. But testing by hand is slow and unreliable. By the time you are testing a program, your competitor might alread...]]></description><link>https://blog.pontakorn.dev/why-do-we-need-unit-test-and-how-to-write-it-in-python</link><guid isPermaLink="true">https://blog.pontakorn.dev/why-do-we-need-unit-test-and-how-to-write-it-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[Testing]]></category><category><![CDATA[unit testing]]></category><dc:creator><![CDATA[Pontakorn Paesaeng]]></dc:creator><pubDate>Tue, 04 Jan 2022 14:16:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/4hbJ-eymZ1o/upload/v1640850057786/jIyif-6v1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A good program must be correct. Try to imagine getting negative salary because of a bug. To verify how the program work, you must test it. But testing by hand is slow and unreliable. By the time you are testing a program, your competitor might already release the third version of their program! In this post, I will mention one of the tests called unit tests.</p>
<h2 id="heading-what-is-a-unit-test">What is a unit test?</h2>
<p>Unit test is a test for a small part of program. For example, testing <code>abs</code> function to always output absolute value is a unit test. Unit test is testing in smallest part of a program.</p>
<h2 id="heading-lets-write-a-unit-test">Let's write a unit test</h2>
<p>In this post, we will write a unit test for <code>same_line</code> function. <code>same_line</code> checks if the given three points are on the same line.</p>
<p>First, let's write a function. Normally in test-driven development, programmers usually write tests first. But doing that will make IDE or text editor screams in undefined function. Let's write a stub function in <code>sameline.py</code>.</p>
<pre><code class="lang-python"><span class="hljs-string">"""Check three points are on the same line or not"""</span>
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Tuple


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">same_line</span>(<span class="hljs-params">a: Tuple[int, int], b: Tuple[int, int], c: Tuple[int, int]</span>) -&gt; bool:</span>
    <span class="hljs-string">"""Return True if point a, b, and c are on the same line."""</span>
    <span class="hljs-comment"># It is a stub.</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>I use <code>typing</code> module to make type clear. You don't need to do that, but it is better to have type.</p>
<p>Then we write test cases. In Python, we can use <code>unittest</code> module to write unit test in <code>sameline_test.py</code>.</p>
<pre><code class="lang-python"><span class="hljs-string">"""Tests for same line function"""</span>
<span class="hljs-keyword">import</span> unittest

<span class="hljs-keyword">from</span> sameline <span class="hljs-keyword">import</span> same_line


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SameLineTest</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-string">"""Tests for same line function"""</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_same_x</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""If x does not change, they are on the same line."""</span>
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">3</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">4</span>)))
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">-2</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">-3</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">-4</span>)))
        self.assertTrue(same_line((<span class="hljs-number">10</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">10</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">10</span>, <span class="hljs-number">-999</span>)))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_same_y</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""If y does not change, they are on the same line."""</span>
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">3</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">4</span>, <span class="hljs-number">2</span>)))
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">4</span>), (<span class="hljs-number">3</span>, <span class="hljs-number">4</span>), (<span class="hljs-number">4</span>, <span class="hljs-number">4</span>)))
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">-1</span>), (<span class="hljs-number">3</span>, <span class="hljs-number">-1</span>), (<span class="hljs-number">4</span>, <span class="hljs-number">-1</span>)))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_slope</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""If they share same slope, they are on the same line."""</span>
        self.assertTrue(same_line((<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">2</span>, <span class="hljs-number">3</span>), (<span class="hljs-number">3</span>, <span class="hljs-number">4</span>)))
        self.assertTrue(same_line((<span class="hljs-number">2</span>, <span class="hljs-number">3</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>)))
</code></pre>
<p>You can use <code>python -m unittest sameline_test.py</code> to run the unit test. Let's see the result.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640849532406/Z_Rxq3-ql.png" alt="Screen Shot 2564-12-30 at 14.31.53.png" /></p>
<p>Wait a minute. We haven't written anything yet. This happened because the function always returns <code>True</code> and we didn't test a case where the function should return <code>False</code>. Let's add a test.</p>
<pre><code class="lang-python">    <span class="hljs-comment"># Put this after the previous code.</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_triangle</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-string">"""If they can form a triangle, they are not on the same line."""</span>
        self.assertFalse(same_line((<span class="hljs-number">0</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)))
        self.assertFalse(same_line((<span class="hljs-number">12</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">3</span>, <span class="hljs-number">3</span>), (<span class="hljs-number">-1</span>, <span class="hljs-number">-99</span>)))
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640849687573/DKhJaXEJCL.png" alt="Screen Shot 2564-12-30 at 14.34.36.png" /></p>
<p>It's much better now. Now we know that this function does not work. If the function works, it should pass all tests now.</p>
<p><strong>Note: The program may still contain some bugs even all test cases passed. You can use code coverage to find some uncovered tests. </strong></p>
<p>I have a challenge for you. Try to write <code>same_line</code> function to check if point a, b, and c are in the same line. Optional challenge is to support 3D coordinate or cover more points. I hope this post will be useful to Python developers.</p>
]]></content:encoded></item><item><title><![CDATA[4 things you can do to make your Python code better]]></title><description><![CDATA[Imagine that you were working on a project yesterday and you cannot understand your code today. Or, someone wrote a long line of code and you need to fix it. But you cannot because you do not understand the code at all. If these things happen, that c...]]></description><link>https://blog.pontakorn.dev/4-things-you-can-do-to-make-your-python-code-better</link><guid isPermaLink="true">https://blog.pontakorn.dev/4-things-you-can-do-to-make-your-python-code-better</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[code review]]></category><category><![CDATA[code]]></category><category><![CDATA[documentation]]></category><dc:creator><![CDATA[Pontakorn Paesaeng]]></dc:creator><pubDate>Sat, 25 Dec 2021 07:43:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/S5YCDN46Wc8/upload/v1640351023548/P7b0DvnbC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine that you were working on a project yesterday and you cannot understand your code today. Or, someone wrote a long line of code and you need to fix it. But you cannot because you do not understand the code at all. If these things happen, that could mean the code is bad.</p>
<p>There are many definitions of good code. In this post, good code is understandable, simple, and standard. These qualities will be explained in 4 tips to make your Python code better. These tips can be applied to other languages as well with different tools and convention.</p>
<h2 id="heading-1-follow-pep-8-convention">1. Follow PEP 8 convention.</h2>
<p>PEP 8 is official guideline for writing Python code. It primarily focuses on readability and consistency such as how to name a variable. Using PEP8 will make code easier to read and understand. Let's take a look at this example.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getinformationfromshop</span>(<span class="hljs-params">shopname</span>):</span>
    <span class="hljs-comment"># Insert logic here</span>
   <span class="hljs-keyword">return</span> information
</code></pre>
<p>You can see it's difficult to read. Better names are <code>getInformationFromShop</code>, <code>GetInformationFromShop</code>, or <code>get_information_from_shop</code>. In PEP8, words should be separated by underscore. The first name is for Java and the second name is for C#. Also, in the second case, it might be mistaken for class instead. The better code looks like this.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_information_from_shop</span>(<span class="hljs-params">shop_name</span>):</span>
    <span class="hljs-comment"># Insert logic here</span>
   <span class="hljs-keyword">return</span> information
</code></pre>
<p>You can see that it looks better now. Many built-in functions in Python also follow the same convention. There are exceptions for legacy code such as <code>logging</code> module, which is ported from log4j. PEP8 should not be followed if it breaks compatibility.</p>
<h2 id="heading-2-use-formatter-and-linter">2. Use formatter and linter.</h2>
<p>In PyCharm, there is a built-in formatter. It can fix many issues such as inconsistent spacing or unnecessary parenthesis. Not everything can be fixed with PyCharm auto formatter.</p>
<p>If you are not using PyCharm, you can use other formatters such as <code>black</code> or <code>autopep8</code> as well.</p>
<p>Other things are covered by linters. Linter is a program that check quality of your code. It can detect some bad things such as unused variables or methods that could be standalone functions.</p>
<p><code>pylint</code> and <code>flake8</code> are popular linters for Python. </p>
<h2 id="heading-3-include-documentation-with-docstring-and-type-hints">3. Include documentation with docstring and type hints.</h2>
<p>Good code often explains itself. But sometimes it is not enough. That's why we have documentation and docstring. Take a look at this code.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_all_links</span>(<span class="hljs-params">src</span>):</span>
    <span class="hljs-comment"># Insert logic here.</span>
    <span class="hljs-keyword">return</span> all_links
</code></pre>
<p>It is ambiguous. What is <code>src</code>? What is returned? Now, I add docstring.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_all_links</span>(<span class="hljs-params">src: str</span>) -&gt; List[str]:</span>
    <span class="hljs-string">"""Return all hyperlink in the webpage.

    This function will perform HTTP request and fetch all hyperlinks if the page is HTML.

    Args:
        src: URL of the page ex. https://blog.pontakorn.dev
    Returns:
        All hyperlinks in the given page    
    Raises:
        ValueError: If the given page is not HTML
    """</span>
    <span class="hljs-comment"># Insert logic here</span>
    <span class="hljs-keyword">return</span> all_links
</code></pre>
<p>Now, we know that we need to input URL, the function will make a HTTP request, and all hyperlinks are returned. We also know required type.</p>
<p><code>mypy</code> is a progam for static type checking for Python. You can try it.</p>
<h2 id="heading-4-review-your-code">4. Review your code.</h2>
<p>Try to guess what does this code do.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> x - <span class="hljs-number">6</span> &gt; <span class="hljs-number">0</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> x - <span class="hljs-number">6</span> &lt;= <span class="hljs-number">0</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>3...2...1...0 The code is comparing if <code>x</code> is greater than 6 or not. You can see that the code is unnecessary complex.  It can be just</p>
<pre><code class="lang-python"><span class="hljs-keyword">return</span> x &gt; <span class="hljs-number">6</span>
</code></pre>
<p>It sounds ridiculous but it can happen to you time to time especially when you forgot to sleep or don't have enough coffee. Take a break and come back to your code to review.</p>
<p>I hope these 4 tips will help you improve your Python code.</p>
]]></content:encoded></item><item><title><![CDATA[What is XSS and why so many libraries mention it?]]></title><description><![CDATA[Before I write this, I exploited two of my classmates' projects with XSS. I didn't expect it to work but it worked anyway. In many libraries and frameworks, there are usually documentations about XSS. Most of them usually say something similar to

Do...]]></description><link>https://blog.pontakorn.dev/what-is-xss-and-why-so-many-libraries-mention-it</link><guid isPermaLink="true">https://blog.pontakorn.dev/what-is-xss-and-why-so-many-libraries-mention-it</guid><category><![CDATA[Security]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Pontakorn Paesaeng]]></dc:creator><pubDate>Fri, 10 Dec 2021 10:42:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/flha0KwRrRc/upload/v1639130646064/pm10q6bnr.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before I write this, I exploited two of my classmates' projects with XSS. I didn't expect it to work but it worked anyway. In many libraries and frameworks, there are usually documentations about XSS. Most of them usually say something similar to</p>
<blockquote>
<p>Don't use X to display untrusted content to prevent XSS attack.</p>
</blockquote>
<p>It usually appears when it is possible to display raw HTML from string or any input. Let's get into it.</p>
<h2 id="heading-what-is-xss-anyway">What is XSS anyway?</h2>
<p>XSS is about inserting script into someone's else website and browser just executes it. The code is executed the same way as code provided by the site. That means it can access sensitive information and use it. XSS can also use to perform unwanted actions such as making a request, changing HTML content and more.</p>
<h3 id="heading-example">Example</h3>
<p>There is website called superforum.com. Superforum has code like this. I will use Django to explain this but it applies to other frameworks as well.</p>
<p>Request</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_comment</span>(<span class="hljs-params">request, thread_id</span>):</span>
    <span class="hljs-comment"># The comment editor allows inserting HTML tag</span>
    comment_body = request.POST[<span class="hljs-string">'comment_body'</span>]
    <span class="hljs-comment"># Insert comment saving logic here</span>
    <span class="hljs-keyword">return</span> redirect(reverse(<span class="hljs-string">'forum:view'</span>, args=[thread_id]))
</code></pre>
<p>Template</p>
<pre><code class="lang-html"> <span class="hljs-comment">&lt;!-- Insert other things here --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"comment-body"</span>&gt;</span>
   {{ comment.comment_body|safe }}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In Django, <code>safe</code> filter allows string to display as raw HTML. If the user comment this</p>
<pre><code class="lang-html">I like this. <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-built_in">window</span>.open(<span class="hljs-string">"https://www.youtube.com/watch?v=dQw4w9WgXcQ"</span>, <span class="hljs-string">'_blank'</span>).focus()</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>it would be executed right away when someone view the page with this comment. The script above is harmless rickroll. Real attackers would steal your identity, transfer your money, mine Bitcoin, and more.</p>
<h2 id="heading-how-can-i-avoid-it-in-my-website">How can I avoid it in my website?</h2>
<p>Don't trust user input. Sanitize the input and escape it help. Common libraries usually have a way to deal with this. For example, Django escapes template by default (unless you use <code>safe</code>).</p>
<p>But, don't do it yourself. <a target="_blank" href="https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html">There is a terrifying long list of evasions. I don't even know if it is comprehensive or not.</a> If there is a verified library, use it.</p>
<h2 id="heading-more-information-and-references">More information and references</h2>
<ul>
<li><a target="_blank" href="https://owasp.org/www-community/attacks/xss/">More detailed information from OWASP</a></li>
<li><a target="_blank" href="https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html">That terrifying long list of evasions</a></li>
<li><a target="_blank" href="https://docs.djangoproject.com/en/3.2/topics/security/">Security in Django</a> It is the framework I used as an example.</li>
</ul>
<p>Also, I informed my classmates about vulnerabilities. Both projects already fixed this.</p>
]]></content:encoded></item><item><title><![CDATA[Moving to Hashnode]]></title><description><![CDATA[Hello, if you know me, you might know that I have a website at pontakorn.dev. It is my personal website that I write to. But, I move to Hashnode for now.
Why
I have tried so many stacks to setup my personal website. I tried Gatsby, Gridsome, Hugo, He...]]></description><link>https://blog.pontakorn.dev/moving-to-hashnode</link><guid isPermaLink="true">https://blog.pontakorn.dev/moving-to-hashnode</guid><category><![CDATA[personal]]></category><category><![CDATA[website]]></category><dc:creator><![CDATA[Pontakorn Paesaeng]]></dc:creator><pubDate>Fri, 10 Dec 2021 07:08:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/npxXWgQ33ZQ/upload/v1639120026087/8mfoGTT1fi.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, if you know me, you might know that I have a website at <a target="_blank" href="https://pontakorn.dev">pontakorn.dev</a>. It is my personal website that I write to. But, I move to Hashnode for now.</p>
<h2 id="heading-why">Why</h2>
<p>I have tried so many stacks to setup my personal website. I tried Gatsby, Gridsome, Hugo, Hexo, and 11ty. Each tool has its advantages and disadvantages. The latest one is Gatsby. I used  <a target="_blank" href="https://www.gatsbyjs.com/starters/contentful/starter-gatsby-blog">Gatsby Contentful Template</a>  for <a target="_blank" href="https://pontakorn.dev">pontakorn.dev</a>. The one I used is outdated so you might get to a different template.</p>
<p> I found that I take so much time customizing website and rarely publish any content at all. It's never good to me. I need to tweak it many times. It's time-consuming. So, my solution is basically..</p>
<blockquote>
<p>I am not doing it.</p>
</blockquote>
<p>Yes, I just don't make my website a blog and use Hashnode for blogging platform. I choose Hashnode because I see Hashnode sites many times from <a target="_blank" href="https://daily.dev">daily.dev</a>. My friend also suggest me this so I confirmed my hesitation and move here.</p>
<h2 id="heading-what-will-happen-next">What will happen next?</h2>
<p>Well, it will be there but not a blog anymore. I think I will change it into personal portfolio and portal website. It would give me more freedom over technologies because I can put fancy things without affecting readability of my content.</p>
<p>After moving here, I plan to publish in both English and Thai to attract both Thai and international audience. I don't have schedule or any concrete plan yet. I think it should be ready after final exam season.</p>
<p>For everyone who read this, have a nice day!</p>
]]></content:encoded></item></channel></rss>