About the project

What inspired you?

I was inspired by the persistent challenge of securing modern web applications. The traditional security workflow is often slow and manual: a developer writes code, a static (SAST) tool finds a potential flaw, a developer manually tries to fix it, and then (maybe) a dynamic (DAST) tool later verifies if the fix worked.

I wanted to automate and accelerate this entire "find, fix, verify" loop. My inspiration was to build a single, intelligent system that could act as an AI security partner—one that not only finds flaws but also suggests the code to fix them and then proves the fix works by trying to hack the patched application, all within a single, iterative workflow.

How I built my project

RiskGuard is a multi-agent "Human-in-the-Loop" (HITL) security platform built on the Google Cloud ecosystem.

Architecture:

  1. Frontend: A responsive UI built in React and Vite, served by a Cloud Run Service.
  2. Backend: The entire backend is orchestrated by the Google Agent Development Kit (ADK), running as a separate Cloud Run Service. This backend manages the agentic workflow and serves all API tools.
  3. AI Agents: I created a multi-agent system using Gemini (via langchain-google-genai) for intelligence:
    • SAST Agent: Reads the user's uploaded code and uses Gemini to perform a "code review" to find potential vulnerabilities.
    • Fixer Agent: Takes the SAST report and the vulnerable code, and prompts Gemini to generate a diff-formatted patch to fix the flaw.
    • Planning Agent: Takes the SAST report and the live sandbox URL, and uses Gemini to generate a JSON-based attack plan for the DAST scan.
  4. The "Find, Fix, Verify" Loop:
    • A user uploads their code.
    • The ADK backend (start_full_scan tool) stores the code in Cloud Storage, triggers Cloud Build to create a Docker image, and deploys the vulnerable app to a temporary Cloud Run Service (Sandbox).
    • The SAST and Fixer agents run. The UI pauses, showing the user the suggested fixes.
    • The user clicks "Apply Fix." The backend (apply_fix_and_update_state tool) patches the code locally.
    • The user clicks "Run DAST." The backend (continue_scan_with_dast tool) destroys the old sandbox and re-deploys the patched code to a new sandbox.
    • The Planning Agent creates an attack plan.
    • The ADK backend triggers a separate, secure Cloud Run Job (DAST Executor), which attacks the new, patched sandbox.
    • The UI receives the DAST report. If the attack failed (the fix worked!), the user can finish. If the attack succeeded (the fix failed!), the user can trigger a new "Regenerate Fixes" tool (regenerate_fixes), repeating the loop.

Challenges I faced

  • Flask to ADK Migration: My biggest challenge was migrating from a stateful Flask server (using a global scan_state) to the stateless, tool-based architecture of the ADK. This required re-architecting the frontend (App.tsx) to be the "source of truth" for the scan_state and passing it to/from each ADK tool.
  • The Iterative DAST Loop: I initially had a major logic flaw where the DAST scan would run and then immediately destroy the sandbox in a finally block. This meant if a fix failed, the user was stuck. I had to refactor this into three separate tools (continue_scan_with_dast, regenerate_fixes, and finish_and_destroy_sandbox) to create the iterative loop.
  • Secure DAST: I couldn't run the exploit code inside the main backend. I solved this by creating a separate, isolated Cloud Run Job for the DAST attack, which the ADK backend triggers. This aligns perfectly with Google Cloud's best practices.

What I learned

  • How to Build with ADK: I learned how to build a complex, streaming, multi-tool agent system using the Google Agent Development Kit.
  • State Management is Key: I learned how to manage stateless backends by using the frontend as the state holder, which is a powerful and scalable pattern.
  • Orchestrating Cloud Run: I learned how to use different Cloud Run resource types for their specific strengths: a Service for the 24/7 backend/frontend and a Job for a secure, run-to-completion task like the DAST exploit.
  • Power of Gemini: I was incredibly impressed by Gemini's ability to handle highly domain-specific tasks like generating accurate diff patches for code.

Built With

Share this project:

Updates