AI Security Scanner for Python

Build a CLI tool that uses Gemini AI to scan Python code for security vulnerabilities with color-coded severity ratings.

Introduction

⚡️ 30 second Summary

Security teams at companies like Google DeepMind, OpenAI, and Snyk use AI to detect code vulnerabilities before they reach production. Imagine running a scanner that instantly spots SQL injection, hardcoded secrets, and weak cryptography - just like enterprise security tools, but built by you.

Most developers don't catch these issues until code review or worse, in production. You could manually audit every line, read security reports, hope for the best... or you could automate it.

Professional teams use AI-powered scanners - tools that analyze code instantly. Write code, run the scanner, see vulnerabilities with severity ratings. All automated, all catching issues before they become breaches.

What you'll build

In this project, you'll use Gemini API to build a security scanner that detects vulnerabilities in Python code with color-coded severity ratings.

Is the Gemini API free?

Yes! The Gemini API has a generous free tier that's more than enough for this project. You won't need a credit card to get started.

💡 Why Gemini for security?

Gemini is trained on millions of code examples and security patterns. It can spot vulnerabilities that simple pattern matching misses - like context-dependent SQL injection or subtle cryptographic weaknesses. Professional security tools use similar AI models to augment static analysis.

💡 New to security scanning?

You don't need any prior security or AI experience. This project teaches you how to connect to Gemini and craft prompts that detect real vulnerabilities.

Not sure if this project is right for you? Check if it matches your goals

How you'll build it:

First, you'll connect to Gemini API and test basic code analysis. Then, you'll build a scanner that detects vulnerabilities with severity ratings and colored output.

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

  • A working CLI tool that uses AI to find security issues.
  • A deeper understanding of SQL injection, hardcoded secrets, and weak cryptography.
  • 💎 Secret Mission: File scanning capability for real Python files.

Before you begin, try this quick quiz to get familiar with the concepts:

Connect to Gemini API

Time to connect to Google's Gemini API so you can start analyzing code for vulnerabilities. You'll get your API key, set up Python, and send your first request to Gemini.

In this step, get ready to:

  • Create a new project folder and set up your Python environment
  • Get your Google AI API key
  • Setup a .env file with your API key
  • Test your connection to Gemini

Create Your Project Folder

Let's start by setting up your project folder and opening it in your text editor.

  • Open Cursor.

Don't have Cursor?

You can use any text editor like VS Code, PyCharm, or even a simple text editor. The instructions will work the same way!

  • Create a new folder on your Desktop called security-scanner.
  • Select security-scanner.
  • Click Open Folder.

Set Up Your Python Environment

Before installing packages, let's create a virtual environment to keep your project dependencies isolated. First, you need to open a terminal window in Cursor to run commands.

  • In Cursor, click Terminal → New Terminal from the top menu (or press Ctrl+\on Windows /Cmd+`` on macOS).

First, let's check if Python is installed on your machine.

  • Type this command in the terminal and press Enter.
python --version

✅ I see a version number

You have Python installed. You should see something like Python 3.11.4 or similar.

❌ Command not found

You don't have Python installed yet.

  • Download the latest Python 3 installer.
  • Run the installer.
  • Important: Check the box that says "Add python.exe to PATH".
  • Click Install Now and complete the installation.
  • Close the installer.
  • Restart your terminal (close and reopen it).
  • Verify the installation:
python --version

You should now see the Python version number!

Still seeing "command not found"?

Make sure you restarted your terminal after installation. If it still doesn't work, try restarting Cursor completely.

Now let's create a virtual environment.

  • In your terminal, type this command and press Enter.
python -m venv venv

What is a virtual environment?

A virtual environment is like a separate workspace for your Python project. It keeps all your project's packages isolated from other projects, so they don't interfere with each other. Think of it as a sandbox where you can install whatever you need without affecting your computer's main Python setup.

  • Activate the virtual environment.

🍎 macOS

source venv/bin/activate

🖼️ Windows

venv\Scripts\activate

You should see (venv) appear at the beginning of your terminal prompt. This tells us your virtual environment is active.

Install the Google Generative AI SDK

Now install the SDK that lets Python talk to Gemini.

  • In your terminal, type this command and press Enter.
pip install google-generativeai

What is pip?

pip is Python's package installer. It downloads and installs packages from the Python Package Index (PyPI), which is like an app store for Python libraries. When you run pip install google-generativeai, pip finds the package, downloads it along with any dependencies it needs, and installs everything in your virtual environment. This makes it easy to add functionality to your Python projects without writing everything from scratch.

💡 What is the Google Generative AI SDK?

The google-generativeai package is Google's official Python library for interacting with Gemini models. It handles all the complexity of connecting to Google's servers and verifying your identity with the API key. Instead of writing raw API calls, you can use simple Python methods like model.generate_content() to send prompts and get AI-generated responses.

✅ Successfully installed

You'll see messages showing each package being installed. It ends with Successfully installed google-generativeai and other packages.

❌ I got an error

If you see an error:

  • Make sure your virtual environment is activated (you should see (venv) in your terminal).
  • Try running pip install --upgrade pip first, then retry the install command.
  • If you're on macOS and see permission errors, make sure you're using the virtual environment and not the system Python.

Still stuck?

Ask Claude for help debugging your specific error. You can also ask the NextWork community!

❌ pip: command not found

If you see "pip: command not found":

  • Your Python installation might not include pip.
  • Try python -m pip install google-generativeai instead.
  • This uses Python's built-in module runner to call pip.

Still stuck?

Ask Claude for help with pip installation. You can also ask the NextWork community!

Install python-dotenv for Environment Variables

Before we write code, let's install a package to securely manage your API key. Instead of hardcoding your key directly in your code, you'll use environment variables - special values stored separately from your code that get loaded when your program runs.

  • In your terminal, type this command and press Enter.
pip install python-dotenv

Why use environment variables?

Hardcoding API keys directly in your code is dangerous - if you accidentally commit your code to GitHub or share a screenshot, your key is exposed. Environment variables let you store secrets in a separate .env file that you never commit to version control. This is a security best practice used by professional developers.

Create a .env File with Placeholder

Great! Your packages are installed. Now let's create your .env file with a placeholder. You'll add your actual API key to this file in just a moment.

  • In Cursor, create a new file called .env at the root of your security-scanner project folder (not inside the venv folder).

Hint: To create a new file in Cursor

Right-click in the file explorer at the project root and select New File, then type the filename.

  • Save the file.

Never commit your .env file!

The .env file contains your secret API key. If you use Git, create a .gitignore file and add .env to it. This ensures your secrets never get committed to version control.

Perfect! Your .env file is ready. Now let's get your actual API key from Google.

Get Your Google AI API Key

Now that your environment is set up, let's get your API key from Google AI Studio.

✅ I see the Google AI Studio dashboard

You're already signed in. You'll see the Google AI Studio homepage.

  • In the left sidebar, click Get API key

🚀 I see a Get started button

You're not signed in yet. You'll see a welcome page with a Get started button.

  • Click Get started.

✅ I have a Google account

  • Click on your existing Google account to sign in.

After signing in, you'll be on the Google AI Studio dashboard.

➕ I need a Google account

  • Click Use another account.
  • Click Create account.
✅ Account created successfully

After creating your account, you'll be on the Google AI Studio dashboard.

❓ I am struggling to create an account

If you're having trouble:

  • Make sure you're using a valid email address.
  • Check your email for a verification link if prompted.
  • Try using a different browser if the form isn't working.
Still having issues?

Get help with Google account creation

  • In the top right, click Create API key.

A dialog will appear to create your API key.

  • In the name field, enter My API Key (you can call it whatever you want).
  • Click on the Choose an imported project dropdown.
  • Select Create project.
  • In the project name field, enter My New Project (you can call it whatever you want).
  • Click Create project.
  • Click Create key.

Nice! API key set up and ready to go.

  • Click the Copy icon next to your key to copy it.

Add Your API Key to the .env File

Perfect! Now let's add your actual API key to the .env file you created earlier.

  • Paste your API key into:
GOOGLE_API_KEY=[[YOUR_API_KEY="your-api-key-will-go-here"]]
  • Go back to Cursor.
  • Open your .env file.
  • Paste in the GOOGLE_API_KEY code block.

Your file now should look like this (Your API key will be differnet):

  • Save the file.

What is an API key?

An API key is a unique identifier that authenticates your requests to a service. Think of it like a password that tells Google "this request is coming from an authorized user." When you call the Gemini API, you include this key so Google knows who's making the request and can track usage.

Google's free tier gives you 1500 requests/day. If someone uses your key, their requests count against YOUR quota, potentially blocking your access or incurring charges.

⚠️ Keep your API key secure!

Don't share your API key publicly or commit it to version control. Anyone with your key can make requests that count against your quota.

To protect your key:

  • Never commit it to GitHub or version control
  • Don't share it in screenshots or documentation
  • Store it in environment variables or secure vaults

Create Your Scanner Script

Now create the main script file.

  • In Cursor, create a new file called scanner.py.
  • Add this code to test your Gemini connection.

What are imports in Python?

Imports load external code libraries into your script. When you write import google.generativeai, you're telling Python to load the Gemini SDK so you can use its functions. Without imports, you'd have to write all this functionality yourself. The as genai part creates a shorter alias - instead of typing google.generativeai.GenerativeModel(), you can write genai.GenerativeModel().

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

# Load environment variables from .env file
load_dotenv()

# Configure with your API key from environment variable
api_key = os.getenv("GOOGLE_API_KEY")
genai.configure(api_key=api_key)

# Initialize the model
model = genai.GenerativeModel("gemini-2.5-flash")

# ============================================================
# YOUR CODE GOES BELOW HERE
# ============================================================

# Test with a simple prompt
response = model.generate_content("Say 'Hello, security scanner!' if you can hear me.")

print(response.text)

# ============================================================
# YOUR CODE GOES ABOVE HERE
# ============================================================
  • Save the file.

What does this code do?

This code sets up a connection to Gemini and sends a test message to verify it's working. It loads your API key securely from the .env file, initializes the Gemini model, and prints the AI's response.

Let's break down each part:

  • import os and from dotenv import load_dotenv - Imports the tools we need to read environment variables
  • load_dotenv() - Loads variables from your .env file into the environment
  • os.getenv("GOOGLE_API_KEY") - Retrieves your API key from the environment (keeps it out of your code)
  • genai.configure(api_key=api_key) - Sets up authentication with your API key
  • genai.GenerativeModel("gemini-2.5-flash") - Creates a model object for Gemini 2.5 Flash, which is fast and efficient for text tasks
  • model.generate_content(...) - Sends a prompt to Gemini and returns the AI's response
  • response.text - Extracts the text content from Gemini's response

Using load_dotenv() and os.getenv() is the professional way to handle secrets - your API key stays in the .env file and never appears in your actual code.

Test Your Connection

Time to verify everything works.

  • In your terminal, type this command and press Enter.
python scanner.py

✅ I see a response

You should see Gemini respond with something like "Hello, security scanner!" or a similar greeting.

When you run python scanner.py, Python executes your code line by line - loading your API key from .env, connecting to Gemini's servers, sending your prompt, and printing the response. Your connection is working! 🎉

💬 I see a different response

Gemini might respond differently ("Hello!" or "I can hear you"). As long as you get a response, your connection is working.

❌ I got an error

Check these common issues:

  • API key error: Verify you replaced your-api-key-here with your actual API key in your .env file.
  • Module not found: Ensure your virtual environment is activated ((venv) should show in terminal).
  • Network error: Check your internet connection.

Still stuck?

Ask Claude for help debugging your specific error. You can also ask the NextWork community!

Test a Security Prompt

Excellent! Your connection works. Now test with a security-focused prompt to see how Gemini responds.

  • In your scanner.py, find the section between # YOUR CODE GOES BELOW HERE and # YOUR CODE GOES ABOVE HERE.
  • Replace everything in that section with this code:
# Test code with a security vulnerability
test_code = '''
password = "admin123"
'''

# Ask Gemini to analyze it
prompt = f"Analyze this code for security issues:\n{test_code}"

response = model.generate_content(prompt)
print(response.text)
  • Save the file.
  • In your terminal, type this command and press Enter.
python scanner.py

✅ I see security analysis

Gemini should identify the hardcoded password as a security issue, explaining why storing passwords directly in code is dangerous.

Your security scanner foundation is ready! ✅

⚠️ Gemini didn't flag it

If Gemini doesn't identify it as a security issue:

  • Try running the script again - AI responses can vary.
  • Make sure your prompt asks specifically to "analyze for security issues".
  • The model should catch hardcoded passwords, but responses may differ.

Still not working?

Ask Claude about improving your security prompt. You can also ask the NextWork community!

❌ I got an error

If the script fails:

  • Make sure you saved the file after making changes.
  • Check that your API key is correct in your .env file.
  • Ensure your virtual environment is still activated.

Still stuck?

Ask Claude for help with your error. You can also ask the NextWork community!

Detect Security Vulnerabilities

Your Gemini connection is working. Now let's build a real security scanner that detects SQL injection, hardcoded secrets, and weak cryptography - the same vulnerabilities that professional tools look for.

In this step, get ready to:

  • Add vulnerable code examples to test against
  • Create a detailed security prompt for Gemini
  • Test detection of SQL injection, hardcoded secrets, and weak passwords

Add Vulnerable Code Examples

Create some intentionally vulnerable code to test your scanner. This will help verify Gemini can identify real security issues like hardcoded secrets.

  • In your scanner.py, add these vulnerable code examples after the model initialization (right before the # YOUR CODE GOES BELOW HERE section):
# Vulnerable code example 1: SQL Injection
vulnerable_code_1 = '''
def get_user(username):
    query = "SELECT * FROM users WHERE username = '" + username + "'"
    cursor.execute(query)
    return cursor.fetchone()
'''

# Vulnerable code example 2: Hardcoded credentials
vulnerable_code_2 = '''
DATABASE_PASSWORD = "supersecret123"
API_KEY = "sk-1234567890abcdef"

def connect_db():
    return psycopg2.connect(
        host="localhost",
        password=DATABASE_PASSWORD
    )
'''

# Vulnerable code example 3: Weak cryptography
vulnerable_code_3 = '''
import hashlib

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

What are these vulnerabilities?

These three examples represent some of the most common and dangerous security flaws in software:

  • SQL Injection - SQL is a language databases use to find, sort, and filter data. When user input is directly concatenated into SQL queries (like "SELECT * FROM users WHERE username = '" + username + "'"), attackers can inject malicious SQL code through forms or search bars. Your app runs their code, letting them steal data, delete records, or bypass authentication.
  • Hardcoded Credentials - Storing passwords and API keys directly in source code means anyone who sees your code (through a data breach, public repository, or insider access) gets your secrets.
  • Weak Cryptography - Cryptography is the practice of scrambling data so only authorized people can read it (like turning "password123" into unreadable gibberish). MD5 is an old method that's too weak for modern security - attackers can easily reverse it to reveal the original password. Modern applications should use stronger methods like bcrypt or Argon2 for password protection.

Create a Security Analysis Prompt

Now create a detailed prompt that tells Gemini exactly how to analyze code for security vulnerabilities.

  • In your scanner.py, add this security prompt above the YOUR CODE section (after the model initialization):
security_prompt = """
You are a security expert. Analyze this code for vulnerabilities.

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

Be concise.

Code:
{code}
"""

Why is prompt engineering important?

The quality of Gemini's response depends on how you structure your prompt. By specifying exactly what you want (vulnerability type, explanation, impact, and fix), you get consistent, actionable output instead of vague responses. The {code} placeholder is a Python format string that will be replaced with actual code when you call security_prompt.format(code=vulnerable_code_1).

Test the Scanner

Perfect! Now test the scanner against your vulnerable code examples.

  • In your scanner.py, update the YOUR CODE section with this testing code:
# Test with SQL injection example
print("=" * 50)
print("Analyzing SQL Injection Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_1))
print(response.text)

# Test with hardcoded credentials
print("\n" + "=" * 50)
print("Analyzing Hardcoded Credentials Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_2))
print(response.text)

# Test with weak cryptography
print("\n" + "=" * 50)
print("Analyzing Weak Cryptography Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_3))
print(response.text)
  • Save the file.
  • In your terminal, type this command and press Enter.
python scanner.py

✅ I see vulnerability analysis

You should see Gemini identify the vulnerabilities in each code example:

  • SQL injection in the first example
  • Hardcoded credentials in the second example
  • Weak MD5 hashing in the third example

Your scanner is successfully detecting security issues! 🔍

❌ I got an error

If you see an error:

  • Make sure you saved the file after making changes.
  • Check that the indentation is correct (Python is sensitive to spacing).
  • Ensure your API key is in your .env file.
  • Verify your virtual environment is still activated.

Still stuck?

Ask Claude for help with your specific error. You can also ask the NextWork community!

Add Severity Ratings and Color

Your scanner detects vulnerabilities. Now let's add professional severity ratings (CRITICAL, HIGH, MEDIUM, LOW) with color-coded output - just like enterprise security tools.

In this step, get ready to:

  • Install the colorama library for colored terminal output
  • Update the prompt to include severity ratings
  • Add a function to colorize severity levels in the output
  • Test the scanner with colored severity ratings

Install Colorama for Colored Output

Add colors to make the output more readable.

  • In your terminal, type this command and press Enter.
pip install colorama

What is colorama?

Colorama is a Python library that makes it easy to add colored text to terminal output. It works across Windows, macOS, and Linux, handling platform differences automatically.

✅ Successfully installed

You should see "Successfully installed colorama-..." in your terminal. The package is ready to use! ✅

❌ I got an error

If you see an error:

  • Make sure your virtual environment is still activated (you should see (venv) in your terminal).
  • Try pip install --upgrade pip first, then retry.

Still stuck?

Ask Claude for help installing colorama. You can also ask the NextWork community!

❌ pip: command not found

If you see "pip: command not found":

  • Try python -m pip install colorama instead.
  • This uses Python's module runner to call pip directly.

Still stuck?

Ask Claude for help with pip. You can also ask the NextWork community!

Update the Security Prompt for Severity Ratings

Perfect! Your scanner detects vulnerabilities. Now modify the prompt to ask Gemini to rate the severity of each vulnerability.

  • Update your security prompt.
security_prompt = """
Analyze this code for security vulnerabilities. Be concise.

For each issue use this exact format:

- --
SEVERITY: [CRITICAL/HIGH/MEDIUM/LOW]
TYPE: [Vulnerability Name]
DESCRIPTION: [One sentence explaining the issue]
IMPACT: [One sentence on potential damage]
FIX: [Code snippet only]
---

Code:
{code}
"""
  • Save the file.

What do the severity levels mean?

Security professionals use standardized severity ratings to prioritize fixes:

  • CRITICAL - Immediate exploitation possible, could lead to full system compromise. Fix immediately.
  • HIGH - Serious vulnerability that could be exploited with moderate effort. Fix within days.
  • MEDIUM - Vulnerability exists but requires specific conditions to exploit. Schedule a fix soon.
  • LOW - Minor issue with limited impact. Fix when convenient.

This classification helps development teams focus their limited time on the most dangerous issues first.

Add Colored Output

Add colors to make severity levels stand out.

  • At the top of your scanner.py, add the colorama import:
from colorama import init, Fore, Style

# Initialize colorama
init(autoreset=True)
  • Just above the YOUR CODE section, add this function:

What are functions in Python?

Functions are reusable blocks of code that perform a specific task. When you define a function with def function_name():, you're creating a tool you can use multiple times without rewriting the code. Functions take inputs (parameters), do something with them, and return outputs. The add_colors_to_output function takes text as input, adds color codes to severity levels, and returns the colorized text. This keeps your code organized and makes it easier to test and maintain.

def add_colors_to_output(text):
    """Add colors to severity levels in the output."""
    text = text.replace("SEVERITY: CRITICAL", f"SEVERITY: {Fore.RED}{Style.BRIGHT}CRITICAL{Style.RESET_ALL}")
    text = text.replace("SEVERITY: HIGH", f"SEVERITY: {Fore.YELLOW}{Style.BRIGHT}HIGH{Style.RESET_ALL}")
    text = text.replace("SEVERITY: MEDIUM", f"SEVERITY: {Fore.BLUE}MEDIUM{Style.RESET_ALL}")
    text = text.replace("SEVERITY: LOW", f"SEVERITY: {Fore.GREEN}LOW{Style.RESET_ALL}")
    return text
  • Now update your YOUR CODE section to use colors:
# Test with SQL injection example
print("=" * 50)
print("Analyzing SQL Injection Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_1))
output = add_colors_to_output(response.text)
print(output)

# Test with hardcoded credentials
print("\n" + "=" * 50)
print("Analyzing Hardcoded Credentials Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_2))
output = add_colors_to_output(response.text)
print(output)

# Test with weak cryptography
print("\n" + "=" * 50)
print("Analyzing Weak Cryptography Example...")
print("=" * 50)

response = model.generate_content(security_prompt.format(code=vulnerable_code_3))
output = add_colors_to_output(response.text)
print(output)
  • Save the file.
  • In your terminal, type this command and press Enter.
python scanner.py

✅ I see colored output

You should now see a professionally formatted security report with colored severity levels - red for CRITICAL, yellow for HIGH, blue for MEDIUM, and green for LOW. 🎨

❌ I got an error

If you see an error:

  • Make sure you imported colorama correctly at the top of the file.
  • Check that you installed colorama with pip install colorama.
  • Verify all the code was copied correctly.

Still stuck?

Ask Claude for help with your error. You can also ask the NextWork community!

⚠️ Colors aren't showing

If you see the text but no colors:

  • Make sure you included init(autoreset=True) after importing colorama.
  • Some terminals don't support colors. Try running in VS Code's integrated terminal or a different terminal app.
  • On Windows, the init() call should enable color support automatically.

Still no colors?

Ask Claude for help with terminal color support. You can also ask the NextWork community!

Secret mission

Ready to level up? This section is for those who want to take their skills further.

What does this diagram show?

This diagram shows how your scanner will work with file scanning. You'll run python scanner.py vulnerable.py in the terminal, your script reads the file, sends the code to Gemini for analysis, and prints the colored security report back to your terminal.

Your scanner detects vulnerabilities in hardcoded examples. Now let's make it work with real Python files so you can scan actual code.

Scan Real Python Files

Clean Up Your Resources

Clean Up Your Resources

Nice work completing this project! Let's clean up the resources we created.

Resources to clean up:

  • Deactivate your Python virtual environment
  • Revoke your Google AI API key (optional)
  • Delete the project folder (optional)

Deactivate Virtual Environment

First, deactivate your virtual environment:

deactivate

You should see the (venv) prefix disappear from your terminal prompt.

What About Your API Key?

You have options for your Google AI API key:

💾 Keep the API key

If you plan to build more AI projects, keep your API key active.

Your scanner is already using best practices with .env - your key is secure!

Optional: Add .gitignore

If you use Git, create a .gitignore file to protect your secrets:

.env
venv/
__pycache__/
*.pyc

🗑️ Revoke the API key

If you're completely done with Gemini API:

  • Go to Google AI Studio.
  • Click Get API key in the left sidebar.
  • Find your key and click the trash icon to delete it.

Your API key is now revoked and can't be used.

Delete Project Files (Optional)

If you want to completely remove the project:

  • Delete the entire security-scanner folder from your Desktop.

All resources have been cleaned up!

That's a wrap!

That's a wrap!

You did it! 🎊 You've built an AI-powered security scanner that detects vulnerabilities in Python code.

What you learned:

  • 🔐 How to use Gemini API to analyze code for security vulnerabilities
  • 🎯 Crafting structured prompts for consistent AI responses
  • 🎨 Adding colored terminal output with colorama for severity ratings
  • ⚠️ Common security vulnerabilities: SQL injection, hardcoded secrets, and weak cryptography
  • 🐍 Python environment management with virtual environments

Ready to quiz yourself? 💪

p.s. Does it say "Still tasks to complete!" at the bottom of the screen?

This means you still have screenshots left to upload, or questions left to answer!

  1. Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
  2. Search for the text Return to later.
  3. Jump straight to your incomplete tasks!
  4. 🙋‍♀️ Still stuck? Ask the community!