<?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: David Oprea</title>
    <description>The latest articles on DEV Community by David Oprea (@david_oprea).</description>
    <link>https://dev.to/david_oprea</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%2F4027816%2F16ecf7d6-9818-4ff6-bc2c-f234b3a0ad36.jpg</url>
      <title>DEV Community: David Oprea</title>
      <link>https://dev.to/david_oprea</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/david_oprea"/>
    <language>en</language>
    <item>
      <title>Why Your Unit Tests Aren't Enough (And How to Break Your Own API)</title>
      <dc:creator>David Oprea</dc:creator>
      <pubDate>Wed, 22 Jul 2026 23:08:10 +0000</pubDate>
      <link>https://dev.to/david_oprea/why-your-unit-tests-arent-enough-and-how-to-break-your-own-api-5ge</link>
      <guid>https://dev.to/david_oprea/why-your-unit-tests-arent-enough-and-how-to-break-your-own-api-5ge</guid>
      <description>&lt;p&gt;Stop testing the happy path. Learn how to use property-based testing and Schemathesis to automate chaos and break your API before your users do&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Manual Testing
&lt;/h2&gt;

&lt;p&gt;We’ve all been there. You finish building a new API endpoint, fire off a perfectly formatted JSON payload, and get a beautiful &lt;em&gt;200 OK&lt;/em&gt;. You write a few unit tests covering the expected inputs, watch the green checkmarks light up in your CI pipeline, and confidently merge the pull request.&lt;/p&gt;

&lt;p&gt;Then the code hits a live environment. A frontend glitch sends a massive integer instead of a string. A random scraper drops a 10MB payload into a query parameter. Someone decides to test your search bar with a null byte. Suddenly, your bulletproof endpoint is throwing unhandled 500 Internal Server Errors, triggering alerts, and potentially exposing backend stack traces!&lt;/p&gt;

&lt;p&gt;Unit tests are excellent for verifying that your application works perfectly when users play by the rules. But they are entirely blind to what happens when users don’t. To stop staging environments from crashing, we have to stop testing the happy path and start automating the chaos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Property-Based Testing (and Automating the Chaos)
&lt;/h2&gt;

&lt;p&gt;Since writing manual test cases for every possible bad input is exhausting, we need to introduce property-based testing.&lt;/p&gt;

&lt;p&gt;Instead of writing tests with hardcoded values (&lt;em&gt;test_user_age_is_25&lt;/em&gt;), property-based testing generates data based on rules. If you tell it an endpoint expects an integer, it will throw maximum integers, negative numbers, zeroes, and everything in between to see if the underlying properties of your application hold up.&lt;/p&gt;

&lt;p&gt;To do this, I built a lightweight CI/CD fuzzing pipeline using Schemathesis. Schemathesis is a brilliant tool that reads your OpenAPI (&lt;em&gt;openapi.json&lt;/em&gt;) specification, understands exactly what your API expects, and automatically generates thousands of malicious or edge-case payloads.&lt;/p&gt;

&lt;p&gt;The rule is simple: &lt;strong&gt;4xx errors are passes and 500 errors are failures&lt;/strong&gt;. If your API returns a &lt;em&gt;422 Unprocessable Entity&lt;/em&gt; because someone sent a null byte, great! Your validation logic did its job. If your API logic shatters and throws a &lt;em&gt;500 Internal Server Error&lt;/em&gt;, the test fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightning-Fast Fuzzing: Testing In-Memory
&lt;/h2&gt;

&lt;p&gt;One of the biggest hurdles to security testing is developer friction. If a test suite requires standing up a database, configuring Docker networks, and spinning up a live web server just to run, developers simply won't use it.&lt;/p&gt;

&lt;p&gt;To solve this, I designed the pipeline to test the application in-memory.&lt;/p&gt;

&lt;p&gt;If you are using FastAPI (or any ASGI/WSGI framework), Schemathesis can hook directly into your application object. You don't need to bind to a port or run Uvicorn. Here is exactly what the core of &lt;em&gt;test_fuzzer.py&lt;/em&gt; looks like:&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;schemathesis&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;  &lt;span class="c1"&gt;# Import your FastAPI app directly
&lt;/span&gt;
&lt;span class="c1"&gt;# Load the schema directly from the ASGI application
&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schemathesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;openapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_asgi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/openapi.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@schema.parametrize&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;test_api_fuzzer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Execute the generated edge-cases against the in-memory app
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call_asgi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Assert that the server handles the bad data gracefully
&lt;/span&gt;    &lt;span class="n"&gt;case&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Because it bypasses the network layer entirely, it can blast thousands of payloads at your API in seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  The CI/CD Magic: Breaking the Build
&lt;/h2&gt;

&lt;p&gt;A fuzzer is only useful if it stops bad code from being merged. Thus, I wrapped this setup into a GitHub Actions workflow that runs on every push and pull request.&lt;/p&gt;

&lt;p&gt;The workflow spins up an ephemeral Ubuntu runner, installs the dependencies, and runs the fuzzer. Here is the exact YAML configuration:&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;Automated API Fuzzer&lt;/span&gt;

&lt;span class="c1"&gt;# This makes the action run every time you push code or open a Pull Request&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;pull_request&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;fuzz-api&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="m"&gt;3.10&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.10"&lt;/span&gt;
        &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pip"&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="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;python -m pip install --upgrade pip&lt;/span&gt;
        &lt;span class="s"&gt;pip install -r requirements.txt&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 Schemathesis Fuzzer&lt;/span&gt;
      &lt;span class="c1"&gt;# We pipe the output to a text file so we can read it in the next step&lt;/span&gt;
      &lt;span class="c1"&gt;# The "continue-on-error" ensures the pipeline doesn't crash immediately if the fuzzer finds a bug&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run_fuzzer&lt;/span&gt;
      &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;pytest test_fuzzer.py --tb=short &amp;gt; fuzzing_report.txt&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;Publish Security Report to GitHub Summary&lt;/span&gt;
      &lt;span class="c1"&gt;# It takes the terminal output and puts it directly on the GitHub UI.&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "## API Fuzzing Security Report" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;
        &lt;span class="s"&gt;echo "\`\`\`text" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;
        &lt;span class="s"&gt;cat fuzzing_report.txt &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;
        &lt;span class="s"&gt;echo "\`\`\`" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&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;Enforce Quality Gate&lt;/span&gt;
      &lt;span class="c1"&gt;# If the fuzzer found a 500 error, we explicitly fail the workflow at the very end&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;steps.run_fuzzer.outcome == 'failure'&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "Fuzzer detected server crashes (500 errors). Check the summary for details."&lt;/span&gt;
        &lt;span class="s"&gt;exit 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But nobody wants to dig through hundreds of lines of raw terminal logs to figure out which payload broke the server. To fix the developer experience, the workflow catches the output and pipes it directly into the GitHub UI using &lt;strong&gt;Step Summaries&lt;/strong&gt;. When a build fails, developers get an immediate visual markdown report right on their PR page detailing exactly which endpoint crashed and what payload caused it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try Breaking Your Own API
&lt;/h2&gt;

&lt;p&gt;Security testing shouldn't be reserved for massive enterprise teams with dedicated DevSecOps engineers. By combining the OpenAPI standard with GitHub Actions, you can automate your own red team.&lt;/p&gt;

&lt;p&gt;I’ve open-sourced this entire pipeline on my GitHub repository. It is designed to be completely framework-agnostic at the HTTP level, but if you are running a Python web application, integration is virtually zero-config.&lt;/p&gt;

&lt;p&gt;You can check out the repository here: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/DavidOprea" rel="noopener noreferrer"&gt;
        DavidOprea
      &lt;/a&gt; / &lt;a href="https://github.com/DavidOprea/Auto_API_Doc_And_Fuzzer" rel="noopener noreferrer"&gt;
        Auto_API_Doc_And_Fuzzer
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A CI/CD-integrated API fuzzing pipeline that automatically tests endpoints for vulnerabilities and edge-case crashes using OpenAPI schemas and Schemathesis.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Automated API Fuzzing &amp;amp; Documentation Pipeline&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A lightweight, CI/CD-integrated API fuzzing pipeline that uses property-based testing to automatically detect unhandled server exceptions (500 errors) before they reach production.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Developers often test the "happy path" of their APIs but neglect to test how their endpoints handle malformed or malicious data. This project solves that by automatically reading an application's OpenAPI specification and generating thousands of edge-case payloads (e.g., extremely large integers, null bytes, malformed strings) to attempt to crash the server.&lt;/p&gt;

&lt;p&gt;If the API successfully catches the bad data and returns a &lt;code&gt;4xx&lt;/code&gt; error (like &lt;code&gt;422 Unprocessable Entity&lt;/code&gt;), the test passes. If the API logic breaks and throws a &lt;code&gt;500 Internal Server Error&lt;/code&gt;, the pipeline catches it, fails the build, and generates a security report.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture &amp;amp; Tech Stack&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Target Backend:&lt;/strong&gt; FastAPI (Python)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing Engine:&lt;/strong&gt; Pytest &amp;amp; Schemathesis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Protocol:&lt;/strong&gt; OpenAPI 3.0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Automation:&lt;/strong&gt; GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Language-Agnostic Core:&lt;/strong&gt;…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/DavidOprea/Auto_API_Doc_And_Fuzzer" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;&lt;strong&gt;To test your own application:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Copy the &lt;em&gt;.github/workflows/fuzzing_pipeline.yml&lt;/em&gt; into your repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Drop &lt;em&gt;test_fuzzer.py&lt;/em&gt; into your test directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Update the import statement to point to your FastAPI/Flask app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; Push your code, open a PR, and see if your endpoints survive.&lt;/p&gt;

&lt;p&gt;Stop testing the happy path. Start failing your builds before your users fail your servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Visual Alternative: The Black-Box API Fuzzer Web App
&lt;/h2&gt;

&lt;p&gt;Not every team wants to integrate an in-memory testing script into their repositories. Sometimes you just want to point a tool at a live local server, feed it an OpenAPI spec, and watch what happens.&lt;/p&gt;

&lt;p&gt;To solve this, I also built a standalone Black-Box API Fuzzer web application version of the project.&lt;/p&gt;

&lt;p&gt;Instead of running in CI/CD, this version runs as a containerized web application. It features a Next.js frontend where you can paste your OpenAPI specification URL (or upload the JSON), add the API key if necessary, and initiate a fuzzing campaign.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table width="100%"&gt;
  &lt;tbody&gt;
&lt;tr&gt;
    &lt;td width="33%"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flcpm6amlbe4o4y5itlby.jpeg" alt="Fuzzer result 1" width="768" height="874"&gt;
    &lt;/td&gt;
    &lt;td width="33%"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqewbpdllk0uyyhgs1mhi.jpeg" alt="Fuzzer result 2" width="768" height="1067"&gt;
    &lt;/td&gt;
    &lt;td width="33%"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmh7zashastw8ng5zy47o.jpeg" alt="Fuzzer result 3" width="768" height="857"&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Under the hood, it is powered by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI &amp;amp; Celery:&lt;/strong&gt; To handle the heavy lifting of running Schemathesis tasks asynchronously without blocking the main thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis:&lt;/strong&gt; Acting as the message broker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose:&lt;/strong&gt; Tying the entire microservice architecture together.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because it runs in Docker, it utilizes &lt;em&gt;host.docker.internal&lt;/em&gt; to seamlessly route the generated payloads out of the container and attack your target API running locally on your machine. The Next.js frontend uses async polling to fetch live metrics—like the number of API operations tested and the specific crash logs—so you can watch your endpoints fail in real-time through a clean visual dashboard.&lt;/p&gt;

&lt;p&gt;If you want to check this out and run it on your machine you can go to the following GitHub repository here: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/DavidOprea" rel="noopener noreferrer"&gt;
        DavidOprea
      &lt;/a&gt; / &lt;a href="https://github.com/DavidOprea/Black-Box-API-Fuzzer" rel="noopener noreferrer"&gt;
        Black-Box-API-Fuzzer
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An automated, schema-aware testing service that detects stability issues and 5xx errors in REST APIs. Feed it an OpenAPI URL, and it generates malformed payloads to find edge cases, logic flaws, and crashes. Get real-time progress, instant crash reports, and ready-to-run cURL commands to reproduce issues instantly. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Black-Box API Fuzzer&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A containerized DevSecOps testing utility designed to stress-test APIs and uncover edge-case 5xx server errors before public deployment. This fuzzer consumes OpenAPI specifications and leverages property-based testing to automatically generate and execute thousands of mutated HTTP requests against target endpoints.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This project is built with a decoupled, asynchronous microservices architecture to ensure the UI remains responsive during long-running fuzzing campaigns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Next.js (React)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; FastAPI (Python)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Queue:&lt;/strong&gt; Celery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Broker &amp;amp; Cache:&lt;/strong&gt; Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fuzzing Engine:&lt;/strong&gt; Schemathesis&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Docker &amp;amp; Docker Compose&lt;/li&gt;
&lt;li&gt;(Optional) Python 3.10+ and Node.js if running manually&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Installation via Docker Compose (Recommended)&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;The easiest way to spin up the entire stack is using Docker Compose. This ensures Redis, the FastAPI backend, the Celery worker, and the Next.js frontend are correctly networked.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Clone the repository&lt;/span&gt;
git clone https://github.com/DavidOprea/Black-Box-API-Fuzzer
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; Black-Box-API-Fuzzer
 
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Build and spin up the containers&lt;/span&gt;
docker-compose up --build&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/DavidOprea/Black-Box-API-Fuzzer" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>security</category>
      <category>api</category>
      <category>python</category>
    </item>
  </channel>
</rss>
