<?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: Cristhian Carlos MAMANI CORI</title>
    <description>The latest articles on DEV Community by Cristhian Carlos MAMANI CORI (@cristhiancarlosmamanic).</description>
    <link>https://dev.to/cristhiancarlosmamanic</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4015736%2F4fed62b8-7219-4295-b148-e2064dd8fe3d.jpg</url>
      <title>DEV Community: Cristhian Carlos MAMANI CORI</title>
      <link>https://dev.to/cristhiancarlosmamanic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cristhiancarlosmamanic"/>
    <language>en</language>
    <item>
      <title>Automating Security in Python: A Hands-On Guide to SAST with Bandit and GitHub Actions</title>
      <dc:creator>Cristhian Carlos MAMANI CORI</dc:creator>
      <pubDate>Sun, 05 Jul 2026 04:05:26 +0000</pubDate>
      <link>https://dev.to/cristhiancarlosmamanic/automating-security-in-python-a-hands-on-guide-to-sast-with-bandit-and-github-actions-3pn6</link>
      <guid>https://dev.to/cristhiancarlosmamanic/automating-security-in-python-a-hands-on-guide-to-sast-with-bandit-and-github-actions-3pn6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's fast-paced development cycles, security can no longer be an afterthought. Static Application Security Testing (SAST) tools help developers catch vulnerabilities early by analyzing source code before it is compiled or deployed to production.&lt;/p&gt;

&lt;p&gt;In this article, we will explore how to apply a SAST tool to a Python application. While tools like SonarQube or Snyk are popular, we will focus on &lt;strong&gt;Bandit&lt;/strong&gt;, a powerful and lightweight tool designed specifically to find common security issues in Python code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Bandit?
&lt;/h2&gt;

&lt;p&gt;Bandit is an open-source SAST tool maintained by the Python Packaging Authority (PyPA). It parses Python code, builds an Abstract Syntax Tree (AST), and runs appropriate plugins against the AST nodes to detect security flaws like hardcoded passwords, injection vulnerabilities, and unsafe library usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Demo Application
&lt;/h2&gt;

&lt;p&gt;Let's create a simple Python application that intentionally contains some security vulnerabilities for Bandit to find. We'll simulate a basic script that has hardcoded credentials and uses dangerous functions.&lt;/p&gt;

&lt;p&gt;Here is our &lt;code&gt;app.py&lt;/code&gt;:&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;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;

&lt;span class="c1"&gt;# VULNERABILITY 1: Hardcoded credentials
&lt;/span&gt;&lt;span class="n"&gt;DB_PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;super_secret_password_123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# VULNERABILITY 2: Command injection risk (shell=True)
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Executing command...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;parse_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yaml_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# VULNERABILITY 3: Unsafe YAML loading
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yaml_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;App started.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;run_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ls -la&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;h2&gt;
  
  
  Running Bandit Locally
&lt;/h2&gt;

&lt;p&gt;To test our code locally, we first install Bandit via pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bandit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can run it against our &lt;code&gt;app.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bandit &lt;span class="nt"&gt;-r&lt;/span&gt; app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bandit will immediately flag the issues we planted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;B105: hardcoded_password_string&lt;/strong&gt; - Flags the hardcoded &lt;code&gt;DB_PASSWORD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;B602: subprocess_popen_with_shell_equals_true&lt;/strong&gt; - Warns about the potential command injection in &lt;code&gt;subprocess.call&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;B506: yaml_load&lt;/strong&gt; - Warns about using the unsafe &lt;code&gt;yaml.load&lt;/code&gt; function instead of &lt;code&gt;yaml.safe_load&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Automating SAST with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Running tools locally is great, but enforcing them automatically on every push is the best practice. Let's set up a GitHub Action to automatically run Bandit whenever code is pushed to our repository.&lt;/p&gt;

&lt;p&gt;Create a file in your repository at &lt;code&gt;.github/workflows/bandit.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bandit SAST Scan&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;security-scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v5&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.10'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install bandit&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Bandit&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bandit -r . -f txt -o bandit-report.txt || &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload Bandit Report&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bandit-security-report&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bandit-report.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How this automation works:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Triggers&lt;/strong&gt;: The action runs on every push to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution&lt;/strong&gt;: It installs Bandit and runs it across the entire repository (&lt;code&gt;-r .&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifacts&lt;/strong&gt;: It generates a report and uploads it as an artifact, so developers can download and review the findings directly from the GitHub Actions tab. &lt;em&gt;(Note: We use &lt;code&gt;|| true&lt;/code&gt; to prevent the workflow from failing immediately so the report can be uploaded).&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Integrating a SAST tool like Bandit into your Python projects is a straightforward process that significantly enhances your code's security posture. By automating this process with GitHub Actions, you ensure that vulnerabilities are caught in the CI/CD pipeline before they ever reach production.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🔗 Check out the full demo code and automated GitHub Action in this repository:&lt;/strong&gt; &lt;br&gt;
&lt;a href="https://github.com/Cristhian465/Trabajo-en-equipo-de-investigaci-n-N-01-Herramientas-Sast-para-aplicaciones" rel="noopener noreferrer"&gt;https://github.com/Cristhian465/Trabajo-en-equipo-de-investigaci-n-N-01-Herramientas-Sast-para-aplicaciones&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>python</category>
      <category>devops</category>
      <category>github</category>
    </item>
  </channel>
</rss>
