AI Security Scanner for Python

Build a CLI tool that uses Gemini AI to scan Python code for security vulnerabilities.

Introduction

30 Second Summary

Security bugs in code can lead to stolen data, unauthorized access, and compromised systems. Professional security teams use automated scanners to catch these issues before they reach production.

In this project, you will build a Python command-line tool that uses Google's Gemini AI to scan code files for security vulnerabilities. You'll point it at any Python file and get back a structured report of what's wrong, why it matters, and how to fix it.

What You'll Build

Imagine running a single command, pointing it at a Python file, and instantly seeing a detailed breakdown of every security flaw hiding in the code.

By the end of this project, you'll have:

  • A working CLI security scanner powered by the Google Gemini API that reads any Python file and returns a vulnerability report.
  • A structured security prompt that produces consistent, actionable output including vulnerability type, explanation, impact, and a code fix.
  • A test suite of intentionally vulnerable code that triggers 4 distinct security findings: SQL injection, weak hashing, command injection, and hardcoded credentials.
  • Secret Mission: Color-coded severity ratings so you always know which vulnerability to fix first.

Are there any prerequisites?

None. This guide includes full setup instructions for Python, the Google AI API key, and every tool you need. No prior security or AI experience required.

Before We Start

Before we dive in, let's get clear on what you're about to build and why it matters. You'll create a Python command-line tool that uses Google's Gemini AI to scan code for real security vulnerabilities like SQL injection, hardcoded secrets, weak cryptography, and command injection.

Set Up Your Environment

You've committed to building an AI security scanner. Before writing any code, you need the tools that make it possible.

Your scanner needs three things: an API key to talk to Google Gemini, a Python environment isolated from your system, and the packages that let Python communicate with Gemini securely.

In this step, get ready to:
  • Get a Google AI API key from Google AI Studio.
  • Create a project folder with an isolated Python virtual environment.
  • Install the packages your scanner needs.
Get your Google AI API key

The Gemini API is what gives your scanner its AI brain. To use it, you need an API key that authenticates your requests to Google's servers.

  • Open your browser and go to https://aistudio.google.com/.
  • Sign in with your Google account.
  • Click Get API key in the left navigation.
  • Click Create API key.
  • If prompted to select a project, choose the default project that Google AI Studio created for you.
  • Copy the displayed key and paste it somewhere safe (a notes app or temporary text file). You will need this in the next step.

What is an API key?

An API key is a unique string that identifies your application to Google's servers. Think of it like a membership card that lets your scanner access Gemini's AI capabilities.

Gemini 2.5 Flash is free to use on Google's Free Tier, so this project costs nothing.

📣 Keep your API key private

Treat your API key like a password. Never share it publicly, paste it into code you commit to GitHub, or include it in screenshots. You will store it securely in a .env file later.

🙋‍♀️ Seeing a permission denied error?

If the Create API key button is greyed out or you see a permission error, try opening the page in an incognito window. Make sure you are signed in with a personal Google account (not a work or school account that may have restrictions).

help me fix a permission denied error when creating my Gemini API key in Google AI Studio

Create your project folder and set up Python

Now you need a dedicated folder for your scanner project and an isolated Python environment inside it. A virtual environment keeps your project's packages separate from your system Python, so nothing conflicts.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Cursor and press Enter to open it.

What is Cursor?

Cursor is a code editor built on VS Code with AI features. If you do not have Cursor installed, you can download it from cursor.com. Any code editor with an integrated terminal (like VS Code) works too.

  • Open Cursor's integrated terminal by clicking Terminal in the top menu bar, then New Terminal.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir security-scanner
cd security-scanner
  • Confirm the folder exists by running:
pwd

You should see a path ending in security-scanner (for example, /Users/yourname/Desktop/security-scanner).

  • Now open this folder as your project in Cursor. Click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the security-scanner folder, and click Open.
  • If prompted to trust the authors of the folder, click Yes, I trust the authors.
  • Open a fresh terminal by clicking Terminal in the top menu bar, then New Terminal. This terminal starts inside your security-scanner folder.

Next, confirm that Python is installed and meets the minimum version requirement. The packages your scanner uses require Python 3.10 or higher.

  • Check your Python version by running this command:

macOS

python3 --version

Windows

python --version

✔️ I see version 3.10 or higher

Your Python version is ready. Move on to creating the virtual environment below.

ⓧ I see an older version

You have Python installed, but your version is below 3.10. The google-genai package requires Python 3.10 or higher.

  • Download and install the latest Python from python.org/downloads.
  • On macOS, the system python3 may still point to the old version after installing. Use the full path /usr/local/bin/python3 or install a version manager like pyenv to switch versions.
  • After installing, close and reopen your terminal, then run the version check again to confirm you see 3.10 or higher.

ⓧ Command not found

Python is not installed on your system yet.

  • Download and install the latest Python from python.org/downloads.
  • On Windows, make sure to check the Add Python to PATH checkbox during installation.
  • After installing, close and reopen your terminal, then run the version check again to confirm you see a version number.

Now create and activate your virtual environment.

  • Create and activate a virtual environment by running these commands:

macOS

python3 -m venv venv
source venv/bin/activate

Windows

python -m venv venv
venv\Scripts\activate

You should see (venv) appear at the start of your terminal prompt. This confirms the virtual environment is active.

What is a virtual environment?

A virtual environment is an isolated Python workspace. Packages you install inside it stay separate from your system Python. This prevents version conflicts between different projects on your machine.

🙋‍♀️ Don't see (venv) in your prompt?

Make sure you ran both commands (create then activate). On macOS, check that you used source venv/bin/activate and not just venv/bin/activate. On Windows, if you see a script execution policy error, run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned first, then try the activate command again.

help me activate my Python virtual environment

Install your scanner's packages

With your virtual environment active, you can now install the two packages your scanner needs. One talks to Gemini, and the other reads secret values from a file.

  • Install the Google Gemini client library by running:
pip install google-genai

You should see download and installation progress ending with a success message.

  • Install the dotenv library (for loading your API key from a file) by running:
pip install python-dotenv

What do these packages do?

google-genai is the official Python client for Google's Gemini AI models. It handles all the network communication between your script and Gemini's servers.

python-dotenv loads environment variables from a .env file into your script. This keeps your API key out of your source code.

Before you verify, what do you expect to see when you list the installed packages?

  • Confirm both packages installed successfully by running:
pip list

You should see google-genai and python-dotenv in the list of installed packages (along with their dependencies).

Packages not showing up?

Make sure (venv) still appears in your terminal prompt. If it disappeared, run the activate command again before retrying pip install. If you see a network error, check your internet connection and try the command again.

help me install google-genai and python-dotenv in my virtual environment

Your environment is fully set up. You have an API key, a project folder, an active virtual environment, and both packages installed. Next up, you will write the code that connects to Gemini and proves the API key works.

Connect to Gemini

Your virtual environment is ready and your packages are installed. Now it's time to write actual code that talks to Gemini.

In this step, you'll create your scanner script and prove the connection works by sending a test question to the AI. If Gemini answers back, your foundation is solid and you're ready to build on top of it.

In this step, get ready to:
  • Create scanner.py with the Gemini client setup.
  • Store your API key securely in a .env file.
  • Confirm Gemini responds to a test prompt.
Create the scanner script

Your scanner needs to do three things: load your API key from the environment, initialize a connection to Gemini, and send a prompt. You'll wrap all of this in a single Python script.

  • In Cursor, create a new file called scanner.py in the root of your security-scanner folder.
  • Add the following code to scanner.py:
import os
from dotenv import load_dotenv
import google.genai as genai

# Load environment variables from .env file
load_dotenv()
api_key = os.getenv("GOOGLE_API_KEY")

# Initialize the Gemini client with your API key
client = genai.Client(api_key=api_key)

# Send a test prompt to Gemini
try:
    response = client.models.generate_content(
        model='gemini-2.5-flash', contents='Why is the sky blue?'
    )
    print(response)
except Exception as e:
    print(f"\u274c Connection failed: {e}")

What does this code do?

  • load_dotenv() reads key-value pairs from a .env file and loads them into the environment so your code can access them.
  • os.getenv("GOOGLE_API_KEY") retrieves the value of GOOGLE_API_KEY from the environment.
  • genai.Client(api_key=api_key) creates a client that handles all communication with the Google Gemini API.
  • client.models.generate_content() sends a prompt to the gemini-2.5-flash model and returns a response.
  • The try/except block catches any connection errors and prints a helpful message instead of crashing.
  • Save scanner.py.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here's the complete scanner.py at this point:

import os
from dotenv import load_dotenv
import google.genai as genai

load_dotenv()
api_key = os.getenv("GOOGLE_API_KEY")

client = genai.Client(api_key=api_key)

try:
    response = client.models.generate_content(
        model='gemini-2.5-flash', contents='Why is the sky blue?'
    )
    print(response)
except Exception as e:
    print(f"\u274c Connection failed: {e}")
Run the script and test the connection

Before you run this, what do you think will happen? Will Gemini answer your question, or will something go wrong?

  • In your terminal, run the script:
python scanner.py

Your script fails with an error. This is expected and intentional.

Why did this fail?

The script called load_dotenv() to load your API key from a .env file. But that file doesn't exist yet.

Without it, os.getenv("GOOGLE_API_KEY") returns None, and the Gemini client has no valid key to authenticate with. This is why environment variables matter. They keep secrets out of your code while still making them available at runtime.

Time to fix this by creating the .env file your script is looking for.

  • In Cursor, create a new file called .env in the root of your security-scanner folder.
  • Add your API key to the file:
GOOGLE_API_KEY=your-api-key-here
  • Replace your-api-key-here with the real API key you copied from Google AI Studio in the previous step.
  • Save the .env file.

Why use a .env file instead of pasting the key in my code?

Hardcoding secrets directly in source code is a common security mistake. If you ever share or upload your code, anyone can see your key.

A .env file keeps the secret separate from your code. You can add .env to a .gitignore file to ensure it never gets committed to version control.

Now that the .env file exists with your key, what do you expect to see when you run the script again?

  • Run the script again:
python scanner.py

This time, you'll see Gemini's response to "Why is the sky blue?" printed in your terminal. The output is a response object containing the AI's answer.

Still seeing an error?

  • Check that your .env file is in the root of security-scanner (the same folder as scanner.py), not inside the venv folder.
  • Make sure the variable name is exactly GOOGLE_API_KEY with no spaces around the = sign.
  • Confirm your API key is valid by checking it in Google AI Studio. If the key was deleted or revoked, generate a new one.
  • Make sure your virtual environment is still active. You should see (venv) at the start of your terminal prompt.

Help me debug my Gemini connection error

Your connection to Gemini is live. Next up, you'll replace this test question with a structured security prompt that tells Gemini exactly how to analyze code for vulnerabilities.

Add Security Expertise

Your scanner can talk to Gemini, but right now it only asks trivial questions like "Why is the sky blue?"

In this step, you'll craft a structured prompt that transforms Gemini from a general chatbot into a focused security analyst. The prompt tells Gemini exactly what vulnerabilities to look for and how to format its findings.

In this step, get ready to:
  • Add a structured security analysis prompt to scanner.py.
  • Wire the prompt into Gemini and verify it responds as a security expert.
Add the security analysis prompt

The quality of an AI's output depends heavily on the quality of your prompt. A vague request gets a vague answer, but a structured prompt with clear instructions produces consistent, actionable results.

  • In scanner.py, find this line:
client = genai.Client(api_key=api_key)
  • Add the following security_prompt variable below that line, with a blank line separating them:
security_prompt = """
You are a security expert. Analyze this code for vulnerabilities.

For each issue, provide:
1. Vulnerability type
2. Why it is vulnerable (1 sentence)
3. Impact (1 sentence)
4. Secure code fix

Be concise.

Code:
{code}
"""

What does this prompt do?

This is prompt engineering in action. You're giving Gemini a specific role ("security expert") and a strict output format (vulnerability type, explanation, impact, fix).

The {code} placeholder at the bottom is where real code will be injected later. For now it stays as a literal placeholder string, which is fine for testing.

  • Save scanner.py.
Send the security prompt to Gemini

The prompt exists in your file now, but the try block still sends the old test question to Gemini. You need to swap that out.

  • In scanner.py, scroll down to the try: block and find this line:
        model='gemini-2.5-flash', contents='Why is the sky blue?'
  • Replace 'Why is the sky blue?' with security_prompt, so the line now looks like this:
        model='gemini-2.5-flash', contents=security_prompt
  • Save scanner.py.

Before you run this, what do you think Gemini will do when it receives a prompt containing {code} as literal text instead of actual code?

  • Run your scanner to test the new prompt:
python scanner.py

Gemini responds by stating it needs actual code to analyze. It recognizes its role as a security expert and asks for code to review. That's exactly what you want.

Seeing a syntax error?

  • Make sure the triple quotes """ open on the same line as security_prompt = and close on their own line. A missing or misplaced triple quote breaks the string.
  • Check that contents=security_prompt has no quotes around security_prompt. It's a variable name, not a string.
  • help me fix a syntax error in my scanner.py security prompt

💡 Why does Gemini ask for code?

Your prompt says "Code: {code}" at the bottom. Since {code} hasn't been replaced with real code yet, Gemini receives the literal text and correctly identifies there's nothing to analyze. In the next step, you'll wire up file reading so {code} gets replaced with actual Python code.

✔️ Awesome, I've got everything!

Great. Double check you've saved scanner.py and move on to the next step.

ⓧ I'd like to double check the full code

Your scanner.py should now contain these sections in order:

  • Imports (os, dotenv, google.genai).
  • load_dotenv() and api_key from environment.
  • client = genai.Client(api_key=api_key).
  • The security_prompt variable with triple-quoted string, ending with {code} placeholder.
  • A try block calling generate_content with contents=security_prompt (not the old sky question).

Scroll up and confirm each chunk is present and in order. If anything looks off, compare against the code blocks above.

Your scanner now thinks like a security expert. Next up, you'll give it the ability to read real Python files so it has actual code to analyze.

Scan Real Files

Your scanner can talk to Gemini and knows how to analyze code for vulnerabilities. But right now it has nothing to analyze.

In this step, you will add file-reading capability so you can point the scanner at any Python file from the command line. The scanner will read that file's contents and send them through the security prompt to Gemini.

In this step, get ready to:
  • Add command-line argument handling so the scanner accepts a filename.
  • Read file contents and format them into the security prompt.
  • Update the Gemini call to send real code instead of the raw prompt template.
Add command-line file reading

A CLI tool needs to accept input from the user. Your scanner will use sys.argv to grab a filename typed after the script name in the terminal.

  • In scanner.py, find the line that says import os at the top of the file.
  • Add import sys on a new line directly below it, so your first two lines look like this:
import os
import sys
  • Next, find the closing """ of your security_prompt variable.
  • Add the following code below it (before the existing try: block) to handle command-line arguments and read the target file:
# File path from command line: python scanner.py <file_path>
if len(sys.argv) < 2:
    print("Usage: python scanner.py <file_path>")
    sys.exit(1)

code_path = sys.argv[1]
with open(code_path, "r") as f:
    code = f.read()

prompt = security_prompt.format(code=code)

What does this code do?

  • if len(sys.argv) < 2 checks whether the user typed a filename when running the script. If not, it prints a usage hint and exits.
  • sys.argv[1] grabs the first argument after the script name (the file path the user wants to scan).
  • open(code_path, "r") opens that file and reads its entire contents into the code variable.
  • security_prompt.format(code=code) slots the file contents into the {code} placeholder in your security prompt, creating a complete analysis request.
  • Save scanner.py.
  • Test the argument check by running the scanner with no filename:
python scanner.py

You should see the usage message printed in your terminal:

Usage: python scanner.py <file_path>

Seeing a syntax error instead?

  • Make sure import sys is on its own line directly below import os.
  • Check that the new code block sits between the closing """ of security_prompt and the try: line. If it is inside the triple-quoted string or after the try:, the script will fail.
  • Confirm you saved the file before running the command.

help me debug a syntax error in my scanner.py after adding sys.argv argument handling

Wire the file contents into Gemini

The argument handling reads a file and stores a formatted prompt in the prompt variable. Now you need to tell Gemini to use that variable instead of the raw template.

  • In scanner.py, scroll down to the try: block and find these lines:
try:
    response = client.models.generate_content(
        model='gemini-2.5-flash', contents=security_prompt
    )
    print(response)
except Exception as e:
    print(f"❌ Connection failed: {e}")
  • Replace contents=security_prompt with contents=prompt so Gemini receives the file contents.
  • Replace print(response) with print(response.text) to print clean text instead of the raw response object.
  • Your updated try: block should now look like this:
try:
    response = client.models.generate_content(
        model='gemini-2.5-flash', contents=prompt
    )
    print(response.text)
except Exception as e:
    print(f"❌ Connection failed: {e}")

Why response.text?

The generate_content() method returns a response object containing metadata, safety ratings, and the actual text. Accessing .text gives you just the readable content Gemini generated.

Verify your scanner accepts file arguments
  • Save scanner.py.

Before you run the script, predict what you will see when you execute it with no arguments. Will it crash, show the usage message, or call Gemini?

  • Confirm the scanner still handles missing arguments correctly by running:
python scanner.py

You should see the same usage message as before:

Usage: python scanner.py <file_path>

This confirms your edits did not introduce any syntax errors and the argument check still works.

Getting a NameError or different output?

  • A NameError: name 'prompt' is not defined means the argument handling block (which creates prompt) is placed after the try: block instead of before it.
  • If you see Gemini responding instead of the usage message, the if len(sys.argv) < 2: check may be missing or indented incorrectly.

help me fix my scanner.py - I'm not seeing the expected usage message when I run it without arguments

✔️ Awesome, I've got everything!

Great. Make sure you have saved scanner.py before moving on.

ⓧ I'd like to double check the full code

Your scanner.py should contain these sections in order. Scroll up and confirm each one is present:

  • Imports: os, sys, dotenv, google.genai.
  • Environment setup: load_dotenv(), api_key, client.
  • The security_prompt multi-line string with the {code} placeholder at the bottom.
  • Argument handling: sys.argv check, file read, and prompt = security_prompt.format(code=code).
  • The try: block passing contents=prompt and printing response.text.

Your scanner now accepts any Python file as a command-line argument and feeds it to Gemini. Next up, you will create a test file full of intentional vulnerabilities and watch the scanner catch them.

Test Your Scanner

Your scanner can read any Python file and send it to Gemini for a security analysis. But you have not tested it against real vulnerable code yet.

In this step, you will create a Python file packed with intentional security vulnerabilities and point your scanner at it. This proves the tool can detect real-world issues that matter to developers.

In this step, get ready to:
  • Create a test file with hardcoded credentials and run your first scan.
  • Add SQL injection, weak hashing, and command injection vulnerabilities to the test file.
  • Analyze Gemini's findings to understand each vulnerability's real-world impact.
Create your first vulnerable test file

One of the most common security mistakes developers make is hardcoding passwords and API keys directly in source code. You will start with this simple vulnerability to confirm your scanner catches it.

  • Create a new file called vulnerable.py in your security-scanner folder by pasting the following code:
DB_PASSWORD = "password123"
API_SECRET = "sk-live-abcd1234"

def connect_to_database():
    return f"Connecting with password: {DB_PASSWORD}"

What does this code do?

This code stores a database password and an API secret directly in the source file. Anyone who can read the code (teammates, version control history, leaked repos) can see these credentials and use them to access your systems.

  • Save vulnerable.py.
  • Run your scanner against this file by running:
python scanner.py vulnerable.py
  • You should see Gemini flag the hardcoded credentials in its output. It will mention that DB_PASSWORD and API_SECRET should not be stored directly in code.

Not seeing any output?

Make sure your virtual environment is still activated (you should see (venv) in your terminal prompt). If not, run source venv/bin/activate again.

Also check that vulnerable.py is saved in the same folder as scanner.py. If it is in a different location, the scanner will not find it.

Help me debug why my scanner isn't producing output.

Add more vulnerabilities to your test file

Hardcoded credentials are just one category of vulnerability. Real-world code often contains more dangerous flaws that let attackers steal data or run arbitrary commands on your server.

  • In vulnerable.py, add the following code at the very top of the file (above your existing DB_PASSWORD line):
import hashlib
import sqlite3

def authenticate(username, password):
    query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    cursor.execute(query)
    return cursor.fetchone()

def hash_password(password):
    return hashlib.md5(password.encode()).hexdigest()

def process_input(user_input):
    import os
    os.system(f"echo {user_input}")

What does this code do?

Each function contains a different category of vulnerability:

  • authenticate() builds a SQL query using f-strings. An attacker can type a specially crafted username to bypass the login entirely.
  • hash_password() uses MD5, a hashing algorithm that was broken years ago. Attackers can reverse MD5 hashes in seconds.
  • process_input() passes user input directly to os.system(). An attacker could inject any shell command after the echo.
  • Save vulnerable.py.

Before you run the scanner, think about how many vulnerabilities you expect Gemini to find. Will it catch all four categories, or miss some?

  • Run the scanner against the updated file:
python scanner.py vulnerable.py

You should see Gemini identify at least 4 vulnerabilities: SQL injection, weak MD5 hashing, command injection, and hardcoded credentials. Each finding includes the vulnerability type, why it is dangerous, the impact, and a secure fix.

Seeing fewer than 4 vulnerabilities?

AI responses vary slightly each run. If Gemini missed one, run the command again. The model sometimes groups related issues together or uses different category names.

If you see a connection error instead of results, check that your .env file still contains your valid API key.

Help me understand why Gemini is not finding all 4 vulnerabilities.

✔️ Awesome, I've got everything!

Great. Double check you have saved vulnerable.py with all four vulnerability categories in place.

ⓧ I'd like to double check the full code

Here is the complete vulnerable.py file. Make sure yours matches:

import hashlib
import sqlite3

def authenticate(username, password):
    query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    cursor.execute(query)
    return cursor.fetchone()

def hash_password(password):
    return hashlib.md5(password.encode()).hexdigest()

def process_input(user_input):
    import os
    os.system(f"echo {user_input}")

DB_PASSWORD = "password123"
API_SECRET = "sk-live-abcd1234"

def connect_to_database():
    return f"Connecting with password: {DB_PASSWORD}"
Scavenger hunt through your results

Reading a security report is a skill in itself. Look back through Gemini's output and find the answers to these questions.

  • Which function lets an attacker bypass the login without knowing the password? (Hint: look for the SQL injection finding.)
  • Which hashing algorithm did Gemini flag, and why is it considered broken?
  • What makes process_input() dangerous? What could an attacker type as input to delete files?
  • Where does Gemini recommend storing credentials instead of in the source code?

Why is SQL injection so dangerous?

The authenticate() function builds a SQL query by pasting user input directly into the string. An attacker could type ' OR '1'='1 as the username to make the query always return true, bypassing the login entirely.

The fix is to use parameterized queries (placeholders like ?) instead of f-strings. This tells the database to treat the input as data, never as executable SQL.

Your scanner just detected 4 real security vulnerabilities in under a second. Next up, you will take this further in the Secret Mission by adding color-coded severity ratings so you always know which bug to fix first.

Secret mission

Prioritize Like a Pro

Your scanner currently reports every vulnerability with equal weight. A weak hash and a command injection that could wipe a server look the same. Real security professionals triage by severity. Can you add color-coded priority ratings so you always know what to fix first?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally with a free-tier API key, so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • security-scanner project folder on your Desktop (contains scanner.py, vulnerable.py, .env, and your virtual environment).
  • Google AI API key (free tier, no ongoing charges).

Keep everything running

No action needed. Your API key is securely stored in .env and sits on the free tier. Keep building and experimenting with new scan targets.

  • Your virtual environment stays ready. Reactivate it anytime with source venv/bin/activate from inside the security-scanner folder.
  • Your API key remains active on the free tier with no billing.

Pause - I'll come back to this later

Shut down the running virtual environment to free up your terminal. Your files and API key stay intact for next time.

  • Deactivate your virtual environment by running this command in the terminal:
  • When you come back, navigate into security-scanner and reactivate with source venv/bin/activate.
deactivate

Delete - I don't want to use this again

Remove all project resources and revoke your API key. This cannot be undone.

  • Deactivate your virtual environment first (if still active):
deactivate
  • Delete the entire project folder from your Desktop by running:
cd ~/Desktop
rm -rf security-scanner
  • Confirm the folder is gone:
ls

You should no longer see security-scanner in the output.

  • Revoke your Google AI API key:
  • Go to Google AI Studio and sign in.
  • Open the API Keys page from the left panel.
  • Find the key you created for this project and delete it.

Why revoke the key?

Even though the free tier has no charges, deleting unused API keys is a good security habit. A leaked key could let someone else make requests on your behalf.

Nice Work!

Nice Work!

You just built a fully functional AI-powered security scanner from scratch. Point it at any Python file, and it instantly identifies real vulnerabilities with actionable fixes.

Here's what you accomplished:

  • Built a Python CLI security scanner that connects to Google's Gemini AI with a securely stored API key in a .env file.
  • Crafted a structured security prompt that produces consistent vulnerability reports with vulnerability type, explanation, impact, and fix.
  • Detected 4 real vulnerabilities in test code: SQL injection, weak MD5 hashing, command injection, and hardcoded credentials.
  • Secret Mission: Added color-coded severity ratings (CRITICAL/HIGH/MEDIUM/LOW) with colorama for professional triage output.

Ready to quiz yourself?