Fix parameters bug + installation issues

This commit is contained in:
Tanguy Duhamel
2025-09-30 12:10:47 +02:00
parent 6de122ba2a
commit 724064dfaa
14 changed files with 3060 additions and 101 deletions

291
.gitignore vendored Normal file
View File

@@ -0,0 +1,291 @@
# ========================================
# FuzzForge Platform .gitignore
# ========================================
# -------------------- Python --------------------
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.python-version
# UV package manager
uv.lock
# But allow uv.lock in CLI and SDK for reproducible builds
!cli/uv.lock
!sdk/uv.lock
!backend/uv.lock
# MyPy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# -------------------- IDE / Editor --------------------
# VSCode
.vscode/
*.code-workspace
# PyCharm
.idea/
# Vim
*.swp
*.swo
*~
# Emacs
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Sublime Text
*.sublime-project
*.sublime-workspace
# -------------------- Operating System --------------------
# macOS
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
*.stackdump
[Dd]esktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msix
*.msm
*.msp
*.lnk
# Linux
*~
.fuse_hidden*
.directory
.Trash-*
.nfs*
# -------------------- Docker --------------------
# Docker volumes and data
docker-volumes/
.dockerignore.bak
# Docker Compose override files
docker-compose.override.yml
docker-compose.override.yaml
# -------------------- Database --------------------
# SQLite
*.sqlite
*.sqlite3
*.db
*.db-journal
*.db-shm
*.db-wal
# PostgreSQL
*.sql.backup
# -------------------- Logs --------------------
# General logs
*.log
logs/
*.log.*
# -------------------- FuzzForge Specific --------------------
# FuzzForge project directories (user projects should manage their own .gitignore)
.fuzzforge/
# Test project databases and configurations
test_projects/*/.fuzzforge/
test_projects/*/findings.db*
test_projects/*/config.yaml
test_projects/*/.gitignore
# Local development configurations
local_config.yaml
dev_config.yaml
.env.local
.env.development
# Generated reports and outputs
reports/
output/
findings/
*.sarif.json
*.html.report
security_report.*
# Temporary files
tmp/
temp/
*.tmp
*.temp
# Backup files
*.bak
*.backup
*~
# -------------------- Node.js (for any JS tooling) --------------------
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.npm
# -------------------- Security --------------------
# Never commit these files
*.pem
*.key
*.p12
*.pfx
secret*
secrets/
credentials*
api_keys*
.env.production
.env.staging
# AWS credentials
.aws/
# -------------------- Build Artifacts --------------------
# Python builds
build/
dist/
*.wheel
# Documentation builds
docs/_build/
site/
# -------------------- Miscellaneous --------------------
# Jupyter Notebook checkpoints
.ipynb_checkpoints
# IPython history
.ipython/
# Rope project settings
.ropeproject
# spyderproject
.spyderproject
.spyproject
# mkdocs documentation
/site
# Local Netlify folder
.netlify
# -------------------- Project Specific Overrides --------------------
# Allow specific test project files that should be tracked
!test_projects/*/src/
!test_projects/*/scripts/
!test_projects/*/config/
!test_projects/*/data/
!test_projects/*/README.md
!test_projects/*/*.py
!test_projects/*/*.js
!test_projects/*/*.php
!test_projects/*/*.java
# But exclude their sensitive content
test_projects/*/.env
test_projects/*/private_key.pem
test_projects/*/wallet.json
test_projects/*/.npmrc
test_projects/*/.git-credentials
test_projects/*/credentials.*
test_projects/*/api_keys.*

View File

@@ -32,10 +32,10 @@
**FuzzForge** helps security researchers and engineers automate **application security** and **offensive security** workflows with the power of AI and fuzzing frameworks.
- Orchestrate static & dynamic analysis
- Automate vulnerability research
- Scale AppSec testing with AI agents
- Build, share & reuse workflows across teams
- Orchestrate static & dynamic analysis
- Automate vulnerability research
- Scale AppSec testing with AI agents
- Build, share & reuse workflows across teams
FuzzForge is **open source**, built to empower security teams, researchers, and the community.
@@ -55,12 +55,12 @@ If you find FuzzForge useful, please star the repo to support development 🚀
## ✨ Key Features
- 🤖 **AI Agents for Security** Specialized agents for AppSec, reversing, and fuzzing
- 🛠 **Workflow Automation** Define & execute AppSec workflows as code
- 📈 **Vulnerability Research at Scale** Rediscover 1-days & find 0-days with automation
- 🔗 **Fuzzer Integration** AFL, Honggfuzz, AFLnet, StateAFL & more
- 🌐 **Community Marketplace** Share workflows, corpora, PoCs, and modules
- 🔒 **Enterprise Ready** Team/Corp cloud tiers for scaling offensive security
- 🤖 **AI Agents for Security** Specialized agents for AppSec, reversing, and fuzzing
- 🛠 **Workflow Automation** Define & execute AppSec workflows as code
- 📈 **Vulnerability Research at Scale** Rediscover 1-days & find 0-days with automation
- 🔗 **Fuzzer Integration** AFL, Honggfuzz, AFLnet, StateAFL & more
- 🌐 **Community Marketplace** Share workflows, corpora, PoCs, and modules
- 🔒 **Enterprise Ready** Team/Corp cloud tiers for scaling offensive security
---
@@ -72,6 +72,7 @@ If you find FuzzForge useful, please star the repo to support development 🚀
Python 3.11 or higher is required.
**uv Package Manager**
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
@@ -122,25 +123,27 @@ ff workflow security_assessment . # Start a workflow (you can also use ff comman
```
### Manual Workflow Setup
![Manual Workflow Demo](docs/static/videos/manual_workflow.gif)
*Setting up and running security workflows through the interface*
_Setting up and running security workflows through the interface_
👉 More installation options in the [Documentation](https://fuzzforge.ai/docs).
---
## AI-Powered Workflow Execution
![LLM Workflow Demo](docs/static/videos/llm_workflow.gif)
*AI agents automatically analyzing code and providing security insights*
_AI agents automatically analyzing code and providing security insights_
## 📚 Resources
- 🌐 [Website](https://fuzzforge.ai)
- 📖 [Documentation](https://fuzzforge.ai/docs)
- 💬 [Community Discord](https://discord.com/invite/acqv9FVG)
- 🎓 [FuzzingLabs Academy](https://academy.fuzzinglabs.com/?coupon=GITHUB_FUZZFORGE)
- 🌐 [Website](https://fuzzforge.ai)
- 📖 [Documentation](https://fuzzforge.ai/docs)
- 💬 [Community Discord](https://discord.com/invite/acqv9FVG)
- 🎓 [FuzzingLabs Academy](https://academy.fuzzinglabs.com/?coupon=GITHUB_FUZZFORGE)
---
@@ -148,10 +151,11 @@ ff workflow security_assessment . # Start a workflow (you can also use ff comman
We welcome contributions from the community!
There are many ways to help:
- Report bugs by opening an [issue](../../issues)
- Suggest new features or improvements
- Submit pull requests with fixes or enhancements
- Share workflows, corpora, or modules with the community
- Report bugs by opening an [issue](../../issues)
- Suggest new features or improvements
- Submit pull requests with fixes or enhancements
- Share workflows, corpora, or modules with the community
See our [Contributing Guide](CONTRIBUTING.md) for details.
@@ -160,6 +164,7 @@ See our [Contributing Guide](CONTRIBUTING.md) for details.
## 🗺️ Roadmap
Planned features and improvements:
- 📦 Public workflow & module marketplace
- 🤖 New specialized AI agents (Rust, Go, Android, Automotive)
- 🔗 Expanded fuzzer integrations (LibFuzzer, Jazzer, more network fuzzers)

View File

@@ -65,12 +65,12 @@ def get_registry_url(context: str = "default") -> str:
return os.getenv("FUZZFORGE_REGISTRY_PULL_URL", os.getenv("FUZZFORGE_REGISTRY_PUSH_URL", "localhost:5001"))
def _compose_project_name(default: str = "fuzzforge_alpha") -> str:
def _compose_project_name(default: str = "fuzzforge") -> str:
"""Return the docker-compose project name used for network/volume naming.
Honors COMPOSE_PROJECT_NAME if present; falls back to a sensible default.
Always returns 'fuzzforge' regardless of environment variables.
"""
return os.getenv("COMPOSE_PROJECT_NAME", default)
return "fuzzforge"
class PrefectManager:
@@ -539,18 +539,18 @@ class PrefectManager:
raise enhanced_error
# Determine the Docker Compose network name and volume names
# Docker Compose creates networks with pattern: {project_name}_default
# Hardcoded to 'fuzzforge' to avoid directory name dependencies
import os
compose_project = _compose_project_name('fuzzforge_alpha')
docker_network = f"{compose_project}_default"
compose_project = "fuzzforge"
docker_network = "fuzzforge_default"
# Build volume mounts
# Add toolbox volume mount for workflow code access
backend_toolbox_path = "/app/toolbox" # Path in backend container
# Use dynamic volume names based on Docker Compose project name
prefect_storage_volume = f"{compose_project}_prefect_storage"
toolbox_code_volume = f"{compose_project}_toolbox_code"
# Hardcoded volume names
prefect_storage_volume = "fuzzforge_prefect_storage"
toolbox_code_volume = "fuzzforge_toolbox_code"
volumes = [
f"{target_path}:/workspace:{volume_mode}",

View File

@@ -160,8 +160,8 @@ async def setup_docker_pool():
"type": "array",
"title": "Volume Mounts",
"default": [
f"{get_actual_compose_project_name()}_prefect_storage:/prefect-storage",
f"{get_actual_compose_project_name()}_toolbox_code:/opt/prefect/toolbox:ro"
"fuzzforge_prefect_storage:/prefect-storage",
"fuzzforge_toolbox_code:/opt/prefect/toolbox:ro"
],
"description": "Volume mounts in format 'host:container:mode'",
"items": {
@@ -171,7 +171,7 @@ async def setup_docker_pool():
"networks": {
"type": "array",
"title": "Docker Networks",
"default": [f"{get_actual_compose_project_name()}_default"],
"default": ["fuzzforge_default"],
"description": "Docker networks to connect container to",
"items": {
"type": "string"
@@ -211,10 +211,10 @@ def get_actual_compose_project_name():
"""
Return the hardcoded compose project name for FuzzForge.
Always returns 'fuzzforge_alpha' as per system requirements.
Always returns 'fuzzforge' as per system requirements.
"""
logger.info("Using hardcoded compose project name: fuzzforge_alpha")
return "fuzzforge_alpha"
logger.info("Using hardcoded compose project name: fuzzforge")
return "fuzzforge"
async def setup_result_storage():
@@ -388,10 +388,10 @@ async def validate_infrastructure():
# Validate registry connectivity for custom image building
await validate_registry_connectivity()
# Validate network (check for default network pattern)
# Validate network (hardcoded to avoid directory name dependencies)
import os
compose_project = os.getenv('COMPOSE_PROJECT_NAME', 'fuzzforge_alpha')
docker_network = f"{compose_project}_default"
compose_project = "fuzzforge"
docker_network = "fuzzforge_default"
try:
await validate_docker_network(docker_network)

2635
backend/uv.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@ from .commands import (
ai,
ingest,
)
from .constants import DEFAULT_VOLUME_MODE
from .fuzzy import enhanced_command_not_found_handler
# Install rich traceback handler
@@ -180,6 +181,31 @@ workflow_app.command("params")(workflows.workflow_parameters)
def run_workflow(
workflow: str = typer.Argument(help="Workflow name"),
target: str = typer.Argument(help="Target path"),
params: List[str] = typer.Argument(default=None, help="Parameters as key=value pairs"),
param_file: Optional[str] = typer.Option(
None, "--param-file", "-f",
help="JSON file containing workflow parameters"
),
volume_mode: str = typer.Option(
DEFAULT_VOLUME_MODE, "--volume-mode", "-v",
help="Volume mount mode: ro (read-only) or rw (read-write)"
),
timeout: Optional[int] = typer.Option(
None, "--timeout", "-t",
help="Execution timeout in seconds"
),
interactive: bool = typer.Option(
True, "--interactive/--no-interactive", "-i/-n",
help="Interactive parameter input for missing required parameters"
),
wait: bool = typer.Option(
False, "--wait", "-w",
help="Wait for execution to complete"
),
live: bool = typer.Option(
False, "--live", "-l",
help="Start live monitoring after execution (useful for fuzzing workflows)"
)
):
"""
🚀 Execute a security testing workflow
@@ -189,13 +215,13 @@ def run_workflow(
execute_workflow(
workflow=workflow,
target_path=target,
params=[],
param_file=None,
volume_mode='ro',
timeout=None,
interactive=True,
wait=False,
live=False
params=params,
param_file=param_file,
volume_mode=volume_mode,
timeout=timeout,
interactive=interactive,
wait=wait,
live=live
)
@workflow_app.callback()
@@ -406,37 +432,6 @@ def main():
if len(sys.argv) > 1:
args = sys.argv[1:]
# Handle workflow command with pattern recognition
if len(args) >= 3 and args[0] == 'workflow':
workflow_subcommands = ['run', 'status', 'history', 'retry', 'info', 'params']
# Skip custom dispatching if help flags are present
if not any(arg in ['--help', '-h', '--version', '-v'] for arg in args):
if args[1] not in workflow_subcommands:
# Direct workflow execution: ff workflow <name> <target>
from .commands.workflow_exec import execute_workflow
workflow_name = args[1]
target_path = args[2]
remaining_params = args[3:] if len(args) > 3 else []
console.print(f"🚀 Executing workflow: {workflow_name} on {target_path}")
try:
execute_workflow(
workflow=workflow_name,
target_path=target_path,
params=remaining_params,
param_file=None,
volume_mode='ro',
timeout=None,
interactive=True,
wait=False,
live=False
)
return
except Exception as e:
console.print(f"❌ Failed to execute workflow: {e}", style="red")
sys.exit(1)
# Handle finding command with pattern recognition
if len(args) >= 2 and args[0] == 'finding':

View File

@@ -217,11 +217,16 @@ services:
volumes:
postgres_data:
name: fuzzforge_postgres_data
redis_data:
name: fuzzforge_redis_data
prefect_storage:
name: fuzzforge_prefect_storage
toolbox_code:
name: fuzzforge_toolbox_code
registry_data:
name: fuzzforge_registry_data
networks:
default:
name: fuzzforge_alpha_default
name: fuzzforge_default

View File

@@ -189,7 +189,7 @@ services:
Example configuration:
```bash
COMPOSE_PROJECT_NAME=fuzzforge_alpha
COMPOSE_PROJECT_NAME=fuzzforge
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/fuzzforge
PREFECT_API_URL=http://prefect-server:4200/api
DOCKER_REGISTRY=localhost:5001

View File

@@ -111,7 +111,7 @@ Example volume mount:
```yaml
volumes:
- "/host/path/to/code:/app/target:ro"
- "fuzzforge_alpha_prefect_storage:/app/prefect"
- "fuzzforge_prefect_storage:/app/prefect"
```
### Volume Security

View File

@@ -197,7 +197,7 @@ Docker cant access the path you provided.
- Check Docker network configuration:
```bash
docker network ls
docker network inspect fuzzforge_alpha_default
docker network inspect fuzzforge_default
```
- Recreate the network:
```bash

View File

@@ -24,7 +24,7 @@ cd fuzzforge
Create the required environment configuration:
```bash
echo "COMPOSE_PROJECT_NAME=fuzzforge_alpha" > .env
echo "COMPOSE_PROJECT_NAME=fuzzforge" > .env
```
## Step 2: Configure Docker (Critical Step)

28
pyproject.toml Normal file
View File

@@ -0,0 +1,28 @@
[project]
name = "fuzzforge"
version = "0.6.0"
description = "FuzzForge Platform - Complete fuzzing and security testing platform with AI capabilities"
readme = "README.md"
license = { text = "BSL-1.1" }
requires-python = ">=3.11"
dependencies = [
"fuzzforge-sdk",
"fuzzforge-ai",
"fuzzforge-cli",
]
[project.scripts]
fuzzforge = "fuzzforge_cli.main:main"
ff = "fuzzforge_cli.main:main"
[build-system]
requires = ["uv_build>=0.8.22,<0.9.0"]
build-backend = "uv_build"
[tool.setuptools]
packages = []
[tool.uv.sources]
fuzzforge-sdk = { path = "./sdk", editable = true }
fuzzforge-ai = { path = "./ai", editable = true }
fuzzforge-cli = { path = "./cli", editable = true }

View File

@@ -51,8 +51,8 @@ class FuzzForgeSetup:
"""Print welcome header"""
print(f"""{Colors.CYAN}{Colors.BOLD}
╔══════════════════════════════════════════╗
║ FuzzForge Setup Script ║
║ Automated Development Setup
║ FuzzForge Setup Script
Automated Development Setup ║
╚══════════════════════════════════════════╝
{Colors.END}""")
print(f"{Colors.WHITE}Welcome to FuzzForge! This script will set up your development environment.{Colors.END}\n")
@@ -115,16 +115,21 @@ class FuzzForgeSetup:
self.errors.append(f"Python version {python_version} is too old. Please install Python 3.11+")
all_good = False
# Check Docker
docker_success, docker_output = self.run_command("docker --version", "Checking Docker", critical=False)
# Check Docker daemon is running
docker_success, docker_output = self.run_command("docker ps", "Checking Docker", critical=False)
if not docker_success:
self.errors.append("Docker is not installed. Please install Docker Desktop")
self.errors.append("Docker daemon is not running. Please start Docker Desktop")
all_good = False
# Check Docker Compose
compose_success, _ = self.run_command("docker compose version", "Checking Docker Compose", critical=False)
if not compose_success:
self.errors.append("Docker Compose is not available. Please ensure Docker Desktop is installed properly")
# Check Docker Compose with actual compose file validation
if docker_success:
compose_success, _ = self.run_command("docker compose config --quiet", "Checking Docker Compose", critical=False)
if not compose_success:
self.errors.append("Docker Compose validation failed. Please ensure docker-compose.yaml is valid and Docker is running")
all_good = False
else:
print(f"{Colors.RED}❌ Checking Docker Compose failed: Docker daemon not running{Colors.END}")
self.errors.append("Docker Compose cannot be validated - Docker daemon not running")
all_good = False
# Check UV
@@ -215,19 +220,11 @@ class FuzzForgeSetup:
self.errors.append("CLI directory not found")
return False
os.chdir(cli_dir)
# Install CLI using UV
success, _ = self.run_command("uv tool install .", "Installing FuzzForge CLI")
if not success:
# Fallback to pip
print(f"{Colors.YELLOW}📦 Trying pip installation as fallback...{Colors.END}")
success, _ = self.run_command("pip install .", "Installing CLI with pip")
# Install from root, pointing to the 'cli' directory
success, _ = self.run_command("uv tool install --python python3.12 .", "Installing FuzzForge CLI with Python 3.12")
return success
def print_next_steps(self):
"""Print next steps for the user"""
print(f"\n{Colors.BOLD}{Colors.GREEN}🎉 Setup Complete!{Colors.END}")
@@ -312,4 +309,4 @@ def main():
if __name__ == "__main__":
main()
main()

View File

@@ -0,0 +1,3 @@
"""FuzzForge Platform - Complete security testing platform with AI capabilities."""
__version__ = "0.6.0"