API Reference

Complete REST API documentation for RAKṢĀ vulnerability scanner.

Base URL: https://raksha-449012790678.asia-southeast1.run.app
Local Development: http://localhost:8430

Authentication

Currently, RAKṢĀ operates without authentication for simplicity. For production deployments, implement API key authentication through a reverse proxy or custom middleware.

Endpoints

Health Check

GET /health

Check scanner status and available engines.

Response:

{
  "status": "ok",
  "scanners": ["raksha-patterns", "semgrep", "bandit"],
  "total_scans": 42
}

cURL Example:

curl https://raksha-449012790678.asia-southeast1.run.app/health

Upload Scan

POST /scan/upload

Upload and scan a code archive.

Request:

  • Content-Type: multipart/form-data
  • Body: File upload with key file

Supported Formats:

  • .zip (ZIP archives)
  • .tar (TAR archives)
  • .tar.gz, .tgz (Compressed TAR)

Size Limits:

  • Default: 50MB
  • Configurable via MAX_UPLOAD_MB environment variable

Response:

{
  "scan_id": "a1b2c3d4e5f6",
  "source": "myproject.zip",
  "source_type": "upload",
  "scan_time": "2024-05-11T13:30:45.123Z",
  "duration_seconds": 8.5,
  "total_files": 156,
  "scanned_files": 142,
  "skipped_files": 14,
  "total_findings": 12,
  "findings_by_severity": {
    "critical": 1,
    "high": 2,
    "medium": 5,
    "low": 4,
    "info": 0
  },
  "findings": [...] // See Finding Schema below
}

cURL Example:

# Upload a ZIP file
curl -X POST https://raksha-449012790678.asia-southeast1.run.app/scan/upload \
  -F "file=@myproject.zip"
 
# Upload with custom filename
curl -X POST https://raksha-449012790678.asia-southeast1.run.app/scan/upload \
  -F "file=@project.tar.gz;filename=custom-name.tar.gz"

Error Responses:

// File too large
{
  "detail": "File exceeds 50MB limit"
}
 
// Unsupported format
{
  "detail": "Unsupported file type: .rar. Use .zip, .tar, .tar.gz, or .tgz"
}
 
// Extraction failed
{
  "detail": "Failed to extract archive: corrupt or invalid format"
}

GitHub Scan

POST /scan/github

Clone and scan a public GitHub repository.

Request:

{
  "url": "https://github.com/owner/repository",
  "branch": "main"  // Optional, defaults to default branch
}

Response: Same format as upload scan response.

cURL Examples:

# Scan main branch
curl -X POST https://raksha-449012790678.asia-southeast1.run.app/scan/github \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com/django/django"
  }'
 
# Scan specific branch
curl -X POST https://raksha-449012790678.asia-southeast1.run.app/scan/github \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com/microsoft/TypeScript",
    "branch": "release-5.0"
  }'

Error Responses:

// Invalid URL
{
  "detail": "Only public GitHub HTTPS URLs are supported (https://github.com/owner/repo)"
}
 
// Clone timeout
{
  "detail": "Clone timed out (60s limit)"
}
 
// Repository not found
{
  "detail": "Failed to clone: repository not found or private"
}

Get Scan Result

GET /scan/{scan_id}

Retrieve a previously completed scan result.

Parameters:

  • scan_id (path): Unique scan identifier

Response: Same format as scan response (see Upload Scan above).

cURL Example:

curl https://raksha-449012790678.asia-southeast1.run.app/scan/a1b2c3d4e5f6

Error Response:

{
  "detail": "Scan not found"
}

Export Scan Result

GET /scan/{scan_id}/export

Download scan result as a JSON file.

Parameters:

  • scan_id (path): Unique scan identifier

Response:

  • Content-Type: application/json
  • Header: Content-Disposition: attachment; filename=raksha-{scan_id}.json
  • Body: Complete scan result JSON

cURL Example:

# Download to file
curl -O -J https://raksha-449012790678.asia-southeast1.run.app/scan/a1b2c3d4e5f6/export
 
# Specify output filename
curl -o my-scan-results.json \
  https://raksha-449012790678.asia-southeast1.run.app/scan/a1b2c3d4e5f6/export

Data Schemas

Finding Schema

{
  "id": "RAKSHA-001-a1b2",
  "title": "SQL Injection Vulnerability",
  "description": "Direct SQL query construction without parameterization",
  "severity": "critical",
  "file": "app/models/user.py", 
  "line": 45,
  "column": 12,
  "code_snippet": "query = f\"SELECT * FROM users WHERE id = {user_id}\"",
  "scanner": "raksha-patterns",
  "rule_id": "sql-injection-format-string",
  "cwe": "CWE-89",
  "remediation": "Use parameterized queries with prepared statements or ORM methods",
  "confidence": "high",
  "references": [
    "https://owasp.org/www-community/attacks/SQL_Injection"
  ]
}

Severity Levels

SeverityDescriptionExit CodeExample
criticalImmediate security risk1SQL Injection, RCE
highSignificant vulnerability1Auth bypass, XSS
mediumModerate security concern0Info disclosure
lowMinor security issue0Weak crypto
infoBest practice violation0Code quality

Scan Result Schema

{
  "scan_id": "string",
  "source": "string",
  "source_type": "upload|github",
  "scan_time": "ISO 8601 timestamp",
  "duration_seconds": "number",
  "total_files": "number",
  "scanned_files": "number", 
  "skipped_files": "number",
  "total_findings": "number",
  "findings_by_severity": {
    "critical": "number",
    "high": "number", 
    "medium": "number",
    "low": "number",
    "info": "number"
  },
  "scanners_used": ["string"],
  "findings": ["Finding[]"]
}

Error Response Schema

{
  "detail": "string",
  "error_code": "string", // Optional
  "scan_id": "string"     // Optional, if scan was created
}

Usage Patterns

Bulk Scanning

# Scan multiple repositories in parallel
repos=(
  "https://github.com/owner/repo1"
  "https://github.com/owner/repo2" 
  "https://github.com/owner/repo3"
)
 
for repo in "${repos[@]}"; do
  {
    echo "Scanning: $repo"
    result=$(curl -s -X POST https://raksha-449012790678.asia-southeast1.run.app/scan/github \
      -H "Content-Type: application/json" \
      -d "{\"url\": \"$repo\"}")
    
    scan_id=$(echo "$result" | jq -r '.scan_id')
    echo "Scan ID for $repo: $scan_id"
  } &
done
 
wait
echo "All scans complete"

CI/CD Integration

# Example GitHub Actions step
- name: Security Scan
  run: |
    # Upload current repository
    zip -r source.zip . -x ".git/*"
    
    response=$(curl -s -X POST ${{ secrets.RAKSHA_URL }}/scan/upload \
      -F "file=@source.zip")
    
    scan_id=$(echo "$response" | jq -r '.scan_id')
    critical=$(echo "$response" | jq -r '.findings_by_severity.critical')
    high=$(echo "$response" | jq -r '.findings_by_severity.high')
    
    echo "Scan ID: $scan_id"
    echo "Critical issues: $critical"
    echo "High issues: $high"
    
    # Fail build if critical or high severity issues found
    if [[ $critical -gt 0 || $high -gt 0 ]]; then
      echo "Security vulnerabilities detected!"
      exit 1
    fi

SARIF Export (For Advanced Integrations)

While RAKṢĀ doesn’t natively support SARIF output yet, you can convert the JSON result:

# Install sarif-tools
pip install sarif-om
 
# Convert RAKṢĀ JSON to SARIF
python3 << 'EOF'
import json
import sys
from sarif_om import *
 
# Load RAKṢĀ result
with open('scan-result.json') as f:
    raksha_result = json.load(f)
 
# Convert to SARIF format
sarif_run = Run(
    tool=Tool(driver=ToolComponent(name="RAKṢĀ")),
    results=[
        Result(
            rule_id=finding['rule_id'],
            message=Message(text=finding['description']),
            locations=[
                Location(
                    physical_location=PhysicalLocation(
                        artifact_location=ArtifactLocation(uri=finding['file']),
                        region=Region(start_line=finding['line'])
                    )
                )
            ]
        )
        for finding in raksha_result['findings']
    ]
)
 
# Output SARIF
sarif_log = SarifLog(runs=[sarif_run])
print(sarif_log.serialize())
EOF

Rate Limits

Currently no rate limiting is implemented. For production deployments, consider implementing:

  • Per-IP limits: 100 requests/hour
  • Concurrent scans: Max 5 per client
  • File size limits: Configurable per deployment

SDK Examples

Python SDK Example

import requests
import json
from pathlib import Path
 
class RakshaClient:
    def __init__(self, base_url="https://raksha-449012790678.asia-southeast1.run.app"):
        self.base_url = base_url.rstrip('/')
    
    def health(self):
        """Check scanner health"""
        response = requests.get(f"{self.base_url}/health")
        return response.json()
    
    def scan_upload(self, file_path):
        """Upload and scan a file"""
        with open(file_path, 'rb') as f:
            files = {'file': (Path(file_path).name, f)}
            response = requests.post(f"{self.base_url}/scan/upload", files=files)
        return response.json()
    
    def scan_github(self, url, branch=None):
        """Scan a GitHub repository"""
        data = {'url': url}
        if branch:
            data['branch'] = branch
        
        response = requests.post(
            f"{self.base_url}/scan/github", 
            json=data
        )
        return response.json()
    
    def get_scan(self, scan_id):
        """Get scan results"""
        response = requests.get(f"{self.base_url}/scan/{scan_id}")
        return response.json()
 
# Usage
client = RakshaClient()
result = client.scan_github("https://github.com/django/django")
print(f"Found {result['total_findings']} issues")

Need help? Check the troubleshooting guide or review use cases for integration examples.