Afrog SDK Usage Guide
January 3, 2026 ยท View on GitHub
Overview
The Afrog SDK provides a clean, efficient Go programming interface specifically designed for integrating vulnerability scanning capabilities. The SDK features the following core characteristics:
๐ Core Features
- โ Structured Returns - Direct Go struct returns for easy program processing
- โ Real-time Result Streaming - Supports both synchronous callbacks and asynchronous streaming
- โ OOB Detection Support - Complete Out-of-Band detection configuration and management
- โ Detailed Statistics - Provides scan progress, performance, and result statistics
- โ Concurrency Safe - All APIs are thread-safe
Installation
go get -u github.com/zan8in/afrog/v3
Quick Start
Basic Scan Example
The simplest usage pattern, suitable for quick integration:
package main
import (
"fmt"
"log"
"path/filepath"
"github.com/zan8in/afrog/v3"
)
func main() {
// Create scan options
options := afrog.NewSDKOptions()
// Set scan targets
options.Targets = []string{"https://www.example.com"}
// Set POC path (required)
pocPath, _ := filepath.Abs("./pocs/afrog-pocs")
options.PocFile = pocPath
// Create scanner
scanner, err := afrog.NewSDKScanner(options)
if err != nil {
log.Fatal(err)
}
defer scanner.Close()
// Execute scan
scanner.Run()
// Get results
results := scanner.GetResults()
fmt.Printf("Found %d vulnerabilities\n", len(results))
}
SDK Configuration Options
SDKOptions Structure
type SDKOptions struct {
// ========== Target Configuration ==========
Targets []string // List of scan targets
TargetsFile string // Path to targets file
// ========== POC Configuration ==========
PocFile string // POC file or directory path (required)
Search string // POC search keywords
Severity string // Severity level filter
// ========== Performance Configuration ==========
RateLimit int // Request rate limit (default: 150)
Concurrency int // Concurrency level (default: 25)
Retries int // Retry attempts (default: 1)
Timeout int // Timeout in seconds (default: 10)
MaxHostError int // Max errors per host (default: 3)
// ========== PortScan Pre-scan Configuration ==========
PortScan bool // Enable port pre-scan (same as CLI -ps)
PSPorts string // Ports definition: top/full/all/80,443/1-1024 etc. (same as -p)
PSRateLimit int // Pre-scan rate limit (same as -prate)
PSTimeout int // Pre-scan timeout in milliseconds (same as -ptimeout)
PSRetries int // Pre-scan retries (same as -ptries)
PSSkipDiscovery bool // Skip host discovery (same as -Pn)
PSS4Chunk int // Chunk size when ports=full (same as --ps-s4-chunk)
// ========== Network Configuration ==========
Proxy string // HTTP/SOCKS5 proxy
// ========== OOB Configuration ==========
EnableOOB bool // Enable OOB detection
OOB string // OOB adapter type
OOBKey string // OOB API key
OOBDomain string // OOB domain
OOBApiUrl string // OOB API URL
OOBHttpUrl string // OOB HTTP URL
// ========== Output Configuration ==========
EnableStream bool // Enable streaming output
}
Configuration Options Explained
Target Configuration
Targets: Directly specify list of scan targetsTargetsFile: Read targets from file (one per line)
POC Configuration
PocFile: Required POC file or directory pathSearch: Filter POCs by keywords, e.g., "tomcat,phpinfo"Severity: Filter by severity levels, e.g., "high,critical"
Performance Tuning
Concurrency: Number of concurrent scan threads, adjust based on target countRateLimit: Requests per second limit to avoid triggering defensesTimeout: Individual request timeoutRetries: Number of retry attempts for failed requests
Core Feature Examples
1. Real-time Result Callbacks
Process vulnerabilities immediately upon discovery:
scanner.OnResult = func(r *result.Result) {
fmt.Printf("Vulnerability found: %s - %s [%s]\n",
r.Target,
r.PocInfo.Info.Name,
r.PocInfo.Info.Severity)
// Immediate processing logic
if r.PocInfo.Info.Severity == "critical" {
sendAlert(r)
}
}
scanner.Run()
2. Progress Monitoring
Monitor scan progress in real-time:
go func() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
progress := scanner.GetProgress()
stats := scanner.GetStats()
fmt.Printf("Progress: %.2f%% (%d/%d) Vulnerabilities: %d\n",
progress,
stats.CompletedScans,
stats.TotalScans,
stats.FoundVulns)
}
}()
scanner.Run()
3. Asynchronous Scanning with Streaming
Non-blocking scanning with real-time results:
options.EnableStream = true
scanner, _ := afrog.NewSDKScanner(options)
// Start async scan
scanner.RunAsync()
// Read real-time results from channel
for result := range scanner.ResultChan {
fmt.Printf("Live discovery: %s - %s\n",
result.Target,
result.PocInfo.Info.Name)
// Process each result in real-time
processResult(result)
}
4. OOB (Out-of-Band) Detection Configuration
CEYE.io Configuration (Recommended)
options.EnableOOB = true
options.OOB = "ceyeio"
options.OOBKey = "your-ceye-api-token"
options.OOBDomain = "your-subdomain.ceye.io"
DNSLog.cn Configuration (Free)
options.EnableOOB = true
options.OOB = "dnslogcn"
options.OOBDomain = "your.dnslog.cn"
Other OOB Services
// Alphalog
options.OOB = "alphalog"
options.OOBDomain = "your.alphalog.cn"
options.OOBApiUrl = "https://api.alphalog.cn"
// XRay
options.OOB = "xray"
options.OOBDomain = "your.xray.domain"
options.OOBApiUrl = "http://xray-api:8777"
options.OOBKey = "your-xray-token"
OOB Status Check
if oobEnabled, oobStatus := scanner.GetOOBStatus(); oobEnabled {
fmt.Printf("โ OOB Status: %s\n", oobStatus)
} else {
fmt.Printf("โ OOB Status: %s\n", oobStatus)
}
5. Port Pre-scan (PortScan)
The SDK can perform a port pre-scan before running PoCs. Discovered open ports will be appended to the internal Targets (as host:port), and subsequent PoC scans will run against the updated target set.
In SDK mode, open ports are not printed by default. Consume them via callback or by retrieving the collected results.
options := afrog.NewSDKOptions()
options.Targets = []string{"1.2.3.4"}
options.PocFile = pocPath
options.PortScan = true
options.PSPorts = "top" // or "full"/"all"/"80,443"/"1-1024"
options.PSSkipDiscovery = true
options.PSTimeout = 500
scanner, _ := afrog.NewSDKScanner(options)
scanner.OnPort = func(host string, port int) {
fmt.Printf("open: %s:%d\n", host, port)
}
scanner.Run()
open := scanner.GetOpenPorts()
_ = open
You can also consume port pre-scan results asynchronously via PortChan. It is initialized when PortScan is enabled and will be closed automatically after the scan finishes.
options := afrog.NewSDKOptions()
options.Targets = []string{"1.2.3.4"}
options.PocFile = pocPath
options.PortScan = true
scanner, _ := afrog.NewSDKScanner(options)
_ = scanner.RunAsync()
for r := range scanner.PortChan {
fmt.Printf("open: %s:%d\n", r.Host, r.Port)
}
You can also run the example: examples/sdk_portscan/.
API Method Reference
SDKScanner Core Methods
| Method | Description | Return Value |
|---|---|---|
NewSDKScanner(opts) | Create scanner instance | *SDKScanner, error |
Run() | Execute scan synchronously | error |
RunAsync() | Execute scan asynchronously | error |
GetResults() | Get all scan results | []*result.Result |
GetOpenPorts() | Get open ports discovered by pre-scan | map[string][]int |
GetStats() | Get scan statistics | ScanStats |
GetProgress() | Get scan progress (0-100) | float64 |
GetVulnerabilityCount() | Get vulnerability count | int |
HasVulnerabilities() | Check if vulnerabilities exist | bool |
Stop() | Stop scanning | - |
Close() | Close scanner and release resources | - |
Dynamic Configuration Methods
| Method | Description |
|---|---|
SetProxy(proxy) | Dynamically set proxy |
SetRateLimit(n) | Dynamically set rate limit |
SetConcurrency(n) | Dynamically set concurrency |
OOB Related Methods
| Method | Description | Return Value |
|---|---|---|
IsOOBEnabled() | Check if OOB is enabled | bool |
GetOOBStatus() | Get OOB status information | bool, string |
ScanStats Structure
type ScanStats struct {
StartTime time.Time // Scan start time
EndTime time.Time // Scan end time
TotalTargets int // Total target count
TotalPocs int // Total POC count
TotalScans int // Total scan tasks
CompletedScans int32 // Completed scan count
FoundVulns int32 // Found vulnerability count
}
Advanced Usage Examples
Batch Scanning with Result Analysis
options := afrog.NewSDKOptions()
options.TargetsFile = "targets.txt" // Read many targets from file
options.PocFile = "/path/to/pocs"
options.Severity = "high,critical" // Only scan high-risk vulnerabilities
options.Concurrency = 50 // Increase concurrency
scanner, _ := afrog.NewSDKScanner(options)
// Handle different severity levels differently
scanner.OnResult = func(r *result.Result) {
switch r.PocInfo.Info.Severity {
case "critical":
sendUrgentAlert(r)
case "high":
logHighRiskVuln(r)
default:
saveToDatabase(r)
}
}
scanner.Run()
results := scanner.GetResults()
generateReport(results)
Intelligent Scan Control
scanner.OnResult = func(r *result.Result) {
// Stop scanning when critical vulnerability found
if r.PocInfo.Info.Severity == "critical" {
fmt.Println("Critical vulnerability found, stopping scan")
scanner.Stop()
}
}
// Dynamically adjust scan parameters
go func() {
time.Sleep(30 * time.Second)
// Reduce rate after 30 seconds
scanner.SetRateLimit(50)
}()
Multi-target Parallel Scanning
targets := [][]string{
{"https://site1.com", "https://site2.com"},
{"https://site3.com", "https://site4.com"},
}
var wg sync.WaitGroup
results := make(chan []*result.Result, len(targets))
for _, targetGroup := range targets {
wg.Add(1)
go func(targets []string) {
defer wg.Done()
options := afrog.NewSDKOptions()
options.Targets = targets
options.PocFile = pocPath
scanner, _ := afrog.NewSDKScanner(options)
defer scanner.Close()
scanner.Run()
results <- scanner.GetResults()
}(targetGroup)
}
wg.Wait()
close(results)
// Aggregate all results
allResults := []*result.Result{}
for groupResults := range results {
allResults = append(allResults, groupResults...)
}
Performance Optimization Tips
1. Concurrency Optimization
targetCount := len(options.Targets)
// Dynamically adjust concurrency based on target count
switch {
case targetCount <= 10:
options.Concurrency = 5
case targetCount <= 100:
options.Concurrency = 25
case targetCount <= 1000:
options.Concurrency = 50
default:
options.Concurrency = 100
}
2. Memory Optimization
// For large-scale scans, use streaming to avoid memory accumulation
options.EnableStream = true
// Process results immediately, don't accumulate
scanner.OnResult = func(r *result.Result) {
processImmediately(r)
// Don't store in slices
}
3. Network Optimization
// Configuration for unstable networks
options.Retries = 3
options.Timeout = 30
options.RateLimit = 50 // Reduce request frequency
// Use proxy pools
proxies := []string{"proxy1:8080", "proxy2:8080"}
scanner.SetProxy(proxies[rand.Intn(len(proxies))])
Error Handling Best Practices
Complete Error Handling
scanner, err := afrog.NewSDKScanner(options)
if err != nil {
switch {
case strings.Contains(err.Error(), "POCๆไปถ"):
log.Fatal("POC configuration error:", err)
case strings.Contains(err.Error(), "็ฎๆ "):
log.Fatal("Target configuration error:", err)
default:
log.Fatal("Initialization failed:", err)
}
}
// Scan error handling
if err := scanner.Run(); err != nil {
log.Printf("Scan exception: %v", err)
// Even with errors, partial results can be obtained
results := scanner.GetResults()
if len(results) > 0 {
fmt.Printf("Partial results obtained: %d vulnerabilities\n", len(results))
}
}
Timeout and Cancellation Handling
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
go func() {
scanner.RunAsync()
}()
select {
case <-ctx.Done():
scanner.Stop()
fmt.Println("Scan timed out, stopped")
case <-scanner.ResultChan:
// Normal completion
}
Integration Examples
Web Service Integration
func scanHandler(w http.ResponseWriter, r *http.Request) {
target := r.URL.Query().Get("target")
options := afrog.NewSDKOptions()
options.Targets = []string{target}
options.PocFile = os.Getenv("POC_PATH")
scanner, err := afrog.NewSDKScanner(options)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer scanner.Close()
scanner.Run()
results := scanner.GetResults()
// Return JSON results
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"vulnerabilities": len(results),
"results": results,
})
}
CI/CD Integration
func main() {
options := afrog.NewSDKOptions()
options.TargetsFile = "staging-urls.txt"
options.PocFile = "/security/pocs"
options.Severity = "high,critical"
scanner, err := afrog.NewSDKScanner(options)
if err != nil {
os.Exit(1)
}
defer scanner.Close()
scanner.Run()
if scanner.HasVulnerabilities() {
fmt.Println("โ Security vulnerabilities found, blocking deployment")
results := scanner.GetResults()
for _, r := range results {
fmt.Printf("- %s: %s\n", r.Target, r.PocInfo.Info.Name)
}
os.Exit(1)
}
fmt.Println("โ
Security check passed")
}
Frequently Asked Questions
Q: How to handle scanning of large numbers of targets?
A: Use streaming output and appropriate concurrency control:
options.EnableStream = true
options.Concurrency = 50
scanner.OnResult = func(r *result.Result) {
// Process immediately, don't accumulate
processImmediately(r)
}
Q: How to ensure OOB detection works properly?
A: Check OOB status before scanning:
if enabled, status := scanner.GetOOBStatus(); !enabled {
log.Printf("OOB Warning: %s", status)
}
Q: How to optimize scan performance?
A: Adjust parameters based on network and target conditions:
// Internal network scanning
options.Concurrency = 100
options.RateLimit = 500
// External network scanning
options.Concurrency = 25
options.RateLimit = 150
options.Timeout = 15
Q: How to handle scan interruption?
A: Use context and signal handling:
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
<-c
scanner.Stop()
fmt.Println("Scan stopped")
}()
Important Notes
- POC Path Must Be Specified - SDK won't automatically download or find POCs
- Completely Silent Operation - No console output, suitable for program integration
- No File Generation - Won't create any report files
- Resource Management - Must call
Close()to release resources - Concurrency Safe - All methods are thread-safe
- OOB Configuration - Proper configuration required for out-of-band vulnerability detection
License
MIT License
For more examples and detailed documentation, please refer to the example code in the examples/ directory.