This document defines the requirements for the Vulhub CLI tool. The tool aims to simplify the usage of the Vulhub security lab platform, allowing users to start specific vulnerability environments without learning Docker Compose commands or downloading the complete Vulhub project.
- Go (1.21+)
If the following functionalities are required, the listed third-party libraries SHOULD be preferred to implement them:
| Category | Library | Purpose |
|---|---|---|
| CLI Framework | github.com/urfave/cli/v3 |
Command-line interface implementation |
| Dependency Injection | github.com/uber-go/fx |
Dependency management and lifecycle |
| TOML Parsing | github.com/BurntSushi/toml |
Parsing environments.toml and config.toml |
| HTTP Client | resty.dev/v3 |
Enhanced HTTP operations |
| GitHub Client | github.com/google/go-github |
GitHub API integration |
| Utility Functions | github.com/samber/lo |
Functional programming helpers |
The following Go standard library packages SHALL be used:
| Category | Packages |
|---|---|
| File Operations | os, path/filepath, io |
| Concurrency | context, sync |
| Logging | log/slog |
| Testing | testing |
- When implementing any feature, MUST first check if the required functionality can be achieved using the libraries listed above
- If a library is not listed but is required, preference SHALL be given to well-maintained, widely-adopted libraries
- Standard library packages SHALL be preferred over third-party alternatives when functionality is equivalent
User Story: As a user, I want to initialize the Vulhub CLI tool and sync the environment list, so that I can have the latest vulnerability environments available locally.
vulhub init- Initialize the CLI tool configurationvulhub syncup- Sync/update the environment list from remote
- WHEN user executes
vulhub initTHEN system SHALL create initialization configuration files in user's home directory (e.g.,~/.vulhub/config.toml) - WHEN user executes
vulhub initTHEN system SHALL download the official environment list from https://github.com/vulhub/vulhub/blob/master/environments.toml - WHEN configuration files already exist THEN system SHALL prompt user whether to overwrite existing configuration
- WHEN user executes
vulhub syncupTHEN system SHALL fetch the latest environment list from remote and update local cache - WHEN initialization completes successfully THEN system SHALL display success message with basic usage instructions
The following files SHALL be created in ~/.vulhub/ directory:
config.toml- Main configuration fileenvironments.toml- Cached environment list from vulhub repositoryenvironments/- Directory for caching downloaded environment files
User Story: As a user, I want to use simple command-line commands to manage vulnerability environments.
| Command | Description |
|---|---|
vulhub start [keyword] |
Start a vulnerability environment |
vulhub stop [keyword] |
Stop a running vulnerability environment |
vulhub down [keyword] |
Completely remove an environment (containers, volumes, and local files) |
vulhub restart [keyword] |
Restart a vulnerability environment |
vulhub clean [keyword] |
Clean up environment files and Docker resources |
vulhub list |
List all downloaded vulnerability environments |
vulhub list-available |
List all available vulnerability environments |
vulhub status |
Display status of all environments |
vulhub search [keyword] |
Search for vulnerability environments |
vulhub info [keyword] |
Display detailed information about a vulnerability environment |
vulhub github-auth |
Authenticate with GitHub using OAuth Device Flow |
vulhub doctor |
Check system environment and diagnose potential issues |
- WHEN user executes any command THEN system SHALL parse command-line arguments correctly
- WHEN user provides
--helpor-hflag THEN system SHALL display help information for the command - WHEN user provides invalid arguments THEN system SHALL display error message with correct usage
- WHEN command requires a keyword but none is provided THEN system SHALL prompt user or display error message
- This requirement SHALL only implement command-line parsing logic; backend execution logic is NOT in scope
--help, -h- Display help information--version, -v- Display version information--verbose- Enable verbose output--config <path>- Specify custom configuration file path--proxy <url>- Proxy server URL (HTTP or SOCKS5) for CLI network requests
User Story: As a user, I want to specify environments using flexible keywords (CVE number, path, or application name), and the system should help me find the correct environment.
- Exact CVE Number - e.g.,
CVE-2021-44228 - Exact Path - e.g.,
log4j/CVE-2021-44228 - Fuzzy Keyword - e.g.,
log4j,apache,tomcat
- WHEN user provides an exact CVE number (format:
CVE-YYYY-XXXXX) THEN system SHALL search environments.toml for matching CVE - WHEN user provides an exact path that exists in environments.toml THEN system SHALL directly use that environment
- WHEN exact CVE or path is found THEN system SHALL directly execute the corresponding operation (start/stop/etc.)
- WHEN user provides a fuzzy keyword (application name, partial match) THEN system SHALL list all matching environments
- WHEN multiple environments match the keyword THEN system SHALL display an interactive selection menu
- WHEN no environment matches the keyword THEN system SHALL display error message and suggest using
vulhub searchcommand - Interactive selection SHALL support keyboard navigation (arrow keys) and number input
- Exact CVE match (highest priority)
- Exact path match
- Application name match (case-insensitive)
- Partial name/description match (lowest priority)
User Story: As a developer, I want a standalone package that provides a bridge to Docker Compose commands, so that the main CLI can use Docker Compose functionality without tight coupling.
dockercompose (internal package)
package dockercompose
type ComposeClient interface {
// Start starts the Docker Compose environment in the specified directory
Start(ctx context.Context, workDir string, options StartOptions) error
// Stop stops the Docker Compose environment
Stop(ctx context.Context, workDir string, options StopOptions) error
// Restart restarts the Docker Compose environment
Restart(ctx context.Context, workDir string, options RestartOptions) error
// Status returns the status of containers in the environment
Status(ctx context.Context, workDir string) ([]ContainerStatus, error)
// Logs retrieves logs from containers
Logs(ctx context.Context, workDir string, options LogsOptions) (io.ReadCloser, error)
// Down stops and removes containers, networks, and volumes
Down(ctx context.Context, workDir string, options DownOptions) error
// Pull pulls images for the environment
Pull(ctx context.Context, workDir string) error
}- Package SHALL provide a clean interface for executing Docker Compose commands
- Package SHALL wrap
docker composeCLI commands (not docker-compose v1) - Package SHALL handle command output (stdout/stderr) appropriately
- Package SHALL return structured errors with meaningful messages
- Package SHALL support context cancellation for long-running operations
- Package SHALL check if Docker daemon is running before executing commands
- Package SHALL be independently testable with mock implementations
User Story: As a developer, I want a standalone package that provides a bridge to GitHub API, so that the main CLI can download files and access repository information.
github (internal package)
package github
type GitHubClient interface {
// DownloadFile downloads a single file from a repository
DownloadFile(ctx context.Context, owner, repo, path, ref string) ([]byte, error)
// DownloadDirectory downloads all files in a directory from a repository
DownloadDirectory(ctx context.Context, owner, repo, path, ref, destDir string) error
// GetFileContent gets the content of a file (for small files)
GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
// GetLatestRelease gets the latest release information
GetLatestRelease(ctx context.Context, owner, repo string) (*Release, error)
// ListDirectoryContents lists contents of a directory in the repository
ListDirectoryContents(ctx context.Context, owner, repo, path, ref string) ([]ContentEntry, error)
}- Package SHALL provide a clean interface for GitHub API operations
- Package SHALL use GitHub REST API for file downloads and repository access
- Package SHALL support downloading raw file content from repositories
- Package SHALL handle rate limiting gracefully with appropriate retry logic
- Package SHALL support optional GitHub token authentication for higher rate limits
- Package SHALL cache downloaded files to reduce API calls
- Package SHALL return structured errors with meaningful messages
- Package SHALL be independently testable with mock implementations
- GitHub API base URL:
https://api.github.com - Raw content URL:
https://raw.githubusercontent.com - Optional authentication via
GITHUB_TOKENenvironment variable
User Story: As a user, I want all CLI subcommands to work correctly, utilizing the Docker Compose and GitHub packages for their operations.
- Check if configuration directory exists (
~/.vulhub/) - Create configuration directory and default config file if not exists
- Call GitHub package to download
environments.tomlfrom vulhub repository - Save environment list to local cache
- Display success message
- Call GitHub package to fetch latest
environments.toml - Compare with local cached version
- Update local cache if remote version is newer
- Display update summary (new/updated/removed environments)
- Resolve keyword using Requirement 3 logic
- If multiple matches, display interactive selection
- Call GitHub package to download environment files (docker-compose.yml, etc.)
- Call Docker Compose package to start the environment
- Display access information (URLs, ports)
- Resolve keyword using Requirement 3 logic
- Call Docker Compose package to stop the environment
- Display confirmation message
- Resolve keyword using Requirement 3 logic
- Call Docker Compose package to restart the environment
- Display confirmation message
- Resolve keyword using Requirement 3 logic
- If multiple matches, display interactive selection
- Call Docker Compose package to stop and remove containers, networks, and volumes (
docker compose down -v) - Remove local environment files (docker-compose.yml, etc.)
- Display confirmation message
- Scan local cache directory for downloaded environments
- Call Docker Compose package to get status of each environment
- Display list of environments with their status (running/stopped)
- Call Docker Compose package to get status of all running containers
- Display detailed status information (container names, ports, uptime)
- Load environment list from local cache
- Search by CVE, application name, tags, and description
- Display matching environments in formatted table
- Resolve keyword to specific environment
- Display detailed information:
- Environment name
- CVE number(s)
- Application name
- Tags
- Path in vulhub repository
- README content (if available)
- If
--statusflag is provided, display current authentication status - If
--removeflag is provided, prompt for confirmation and remove saved token - Otherwise, initiate OAuth Device Flow authentication: a. Request device code from GitHub OAuth endpoint b. Display user code and verification URL c. Automatically open browser to verification URL d. Poll for access token while user completes authorization e. Save access token to configuration file
- Display success message with rate limit information
- Check Docker environment:
- Verify Docker is installed and in PATH
- Verify Docker daemon is running (
docker info) - Verify Docker Compose is available (
docker compose version)
- Check configuration:
- Verify config directory exists (
~/.vulhub/) - Validate
config.tomlsyntax - Validate
environments.tomlsyntax - Check environments directory status
- Verify config directory exists (
- Check network connectivity:
- Test DNS resolution and HTTP connectivity to GitHub API (
api.github.com) - Test connectivity to GitHub Raw Content (
raw.githubusercontent.com) - Test connectivity to Docker Hub (
hub.docker.com) - Test connectivity to Docker Registry (
registry-1.docker.io) - Test connectivity to Docker Auth (
auth.docker.io) - Test connectivity to Docker CDN (
production.cloudflare.docker.com)
- Test DNS resolution and HTTP connectivity to GitHub API (
- Check Docker registry:
- Display configured registry mirrors
- Perform actual image pull test using
hello-world:latest
- Display summary with pass/warning/error counts
- If
--verboseflag is provided, display detailed timing and path information
- All subcommands SHALL use the Docker Compose package (Requirement 4) for Docker operations
- All subcommands SHALL use the GitHub package (Requirement 5) for repository access
- All subcommands SHALL handle errors gracefully and display user-friendly messages
- All subcommands SHALL respect the
--verboseflag for detailed output - All subcommands SHALL support
--helpflag for command-specific help - Long-running operations SHALL display progress indicators
- Interactive selections SHALL be skippable with
--yesor-yflag for automation
User Story: As a user, I want to authenticate with GitHub easily without manually creating tokens, so that I can avoid API rate limits with minimal effort.
- OAuth App Name: Vulhub CLI
- Client ID:
Ov23liDeiHCLOTtZxFY4 - Authorization Flow: Device Flow (RFC 8628)
- Required Scope:
public_repo
vulhub github-auth- Authenticate with GitHub using OAuth Device Flow
| Flag | Description |
|---|---|
--status |
Display current authentication status |
--remove |
Remove saved GitHub authentication |
- WHEN user executes
vulhub github-authTHEN system SHALL initiate OAuth Device Flow - WHEN device code is received THEN system SHALL display user code and verification URL
- WHEN verification URL is displayed THEN system SHALL attempt to open default browser automatically
- WHEN waiting for authorization THEN system SHALL poll GitHub at the specified interval
- WHEN user completes authorization THEN system SHALL save the access token to config file
- WHEN user denies authorization THEN system SHALL display appropriate message
- WHEN device code expires THEN system SHALL inform user and suggest retrying
- WHEN user executes
vulhub github-auth --statusTHEN system SHALL display authentication status with masked token - WHEN user executes
vulhub github-auth --removeTHEN system SHALL prompt for confirmation before removing token - WHEN any command encounters GitHub API rate limit AND user is not authenticated THEN system SHALL prompt to start OAuth flow
-
Request Device Code
- POST to
https://github.com/login/device/code - Parameters:
client_id,scope=public_repo - Response:
device_code,user_code,verification_uri,expires_in,interval
- POST to
-
User Authorization
- Display
user_codeto user - Direct user to
verification_uri(https://github.com/login/device) - Open browser automatically if possible
- Display
-
Poll for Access Token
- POST to
https://github.com/login/oauth/access_token - Parameters:
client_id,device_code,grant_type=urn:ietf:params:oauth:grant-type:device_code - Poll at
intervalseconds until success or expiration - Handle
authorization_pending,slow_down,expired_token,access_deniedresponses
- POST to
-
Store Token
- Save access token to
~/.vulhub/config.tomlunder[github]section - Token format: OAuth access token (starts with
gho_)
- Save access token to
- OAuth implementation is in
internal/github/oauth.go - Device flow callbacks allow UI customization
- Browser opening is platform-specific (darwin:
open, windows:cmd /c start, linux:xdg-open) - Environment variable
GITHUB_TOKENtakes precedence over saved OAuth token