import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../components/AuthContext'; import toast from 'react-hot-toast'; export const NewScan = () => { const [targetUrl, setTargetUrl] = useState(''); const [scanType, setScanType] = useState('Quick'); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const [customHeaders, setCustomHeaders] = useState(''); const [crawlDepth, setCrawlDepth] = useState('3'); const [excludePaths, setExcludePaths] = useState(''); const [enableRedTeam, setEnableRedTeam] = useState(false); const [scanConfig, setScanConfig] = useState([]); const [showAdvanced, setShowAdvanced] = useState(false); const [showUpgradeModal, setShowUpgradeModal] = useState(false); const [showQuotaExceededModal, setShowQuotaExceededModal] = useState(false); const [attemptedScan, setAttemptedScan] = useState(''); const [quotas, setQuotas] = useState([]); const [isScheduled, setIsScheduled] = useState(false); const [scheduleFrequency, setScheduleFrequency] = useState('daily'); const [scheduleTime, setScheduleTime] = useState('02:00'); // Legal & Confirmation Modal States const [showConfirmModal, setShowConfirmModal] = useState(false); const [showPolicyModal, setShowPolicyModal] = useState(false); const [hasReadPolicy, setHasReadPolicy] = useState(false); const [policyCheck1, setPolicyCheck1] = useState(false); const [policyCheck2, setPolicyCheck2] = useState(false); const [isConfirmedChecked, setIsConfirmedChecked] = useState(false); const { token, user } = useAuth(); const navigate = useNavigate(); useEffect(() => { fetch('/api/scans/config') .then(res => res.json()) .then(data => { if (data.config) { setScanConfig(data.config); } }) .catch(err => console.error("Failed to fetch scan config", err)); }, []); useEffect(() => { if (user?.org_id && token) { fetch(`/api/auth/organizations/${user.org_id}/quotas`, { headers: { 'Authorization': `Bearer ${token}` } }) .then(res => res.json()) .then(data => { if (Array.isArray(data)) { setQuotas(data); } else if (data.quotas) { setQuotas(data.quotas); } }) .catch(console.error); } }, [user?.org_id, token]); useEffect(() => { if (scanType === 'Deep') { setEnableRedTeam(true); setCrawlDepth('20'); } else if (scanType === 'Advanced') { setEnableRedTeam(true); setCrawlDepth('10'); } else if (scanType === 'Quick') { setEnableRedTeam(false); setCrawlDepth('3'); } }, [scanType]); const hasQuota = (methodId) => { if (user?.role === 'admin' || user?.role === 'super_admin') return true; if (!quotas || quotas.length === 0) return true; const q = quotas.find(q => q.scan_type.toLowerCase() === methodId.toLowerCase()); if (!q) return true; if (q.allocated_count === -1) return true; return (q.allocated_count - q.used_count) > 0; }; const handleLaunch = (e) => { e.preventDefault(); setError(''); if (!hasQuota(scanType)) { setAttemptedScan(scanType); setShowQuotaExceededModal(true); return; } if (!targetUrl) { setError('Please provide a target host URL.'); return; } try { const urlObj = new URL(targetUrl); if (urlObj.protocol !== 'http:' && urlObj.protocol !== 'https:') { setError('Please enter a valid website URL (must start with http:// or https://)'); return; } if (!urlObj.hostname.includes('.')) { setError('Please enter a valid website URL (must have a valid domain structure)'); return; } } catch (_) { setError('Please enter a valid website URL (must start with http:// or https://)'); return; } // Open confirmation modal before actual launch setShowConfirmModal(true); }; const executeScan = async () => { setShowConfirmModal(false); setLoading(true); try { let parsedAuthHeaders = {}; if (customHeaders) { const lines = customHeaders.split('\n'); lines.forEach(line => { const parts = line.split(':'); if (parts.length >= 2) { const key = parts[0].trim(); const value = parts.slice(1).join(':').trim(); if (key && value) parsedAuthHeaders[key] = value; } }); } if (isScheduled) { const res = await fetch('/api/scans/schedule', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ target_url: targetUrl, scan_type: scanType, frequency: scheduleFrequency, schedule_time: scheduleTime }) }); const data = await res.json(); if (res.ok) { toast.success('Scan scheduled successfully!'); navigate('/dashboard'); } else { if (res.status === 403 || res.status === 402 || data.message?.toLowerCase().includes('quota')) { setAttemptedScan(scanType); setShowQuotaExceededModal(true); } else { toast.error(data.message || 'Failed to schedule scan.'); } } } else { const res = await fetch('/api/scans/new', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ target_url: targetUrl, scan_type: scanType, auth_headers: parsedAuthHeaders, custom_headers: customHeaders, crawl_depth: crawlDepth, exclude_paths: excludePaths, enable_red_team: enableRedTeam }) }); const data = await res.json(); if (res.ok) { if (data.scan) { const existingActive = localStorage.getItem('wss_active_scan'); if (!existingActive) { localStorage.setItem('wss_active_scan', JSON.stringify(data.scan)); } } toast.success('Scan pipeline initiated successfully!'); navigate('/dashboard'); } else { if (res.status === 403 || res.status === 402 || data.message?.toLowerCase().includes('quota')) { setAttemptedScan(scanType); setShowQuotaExceededModal(true); } else { setError(data.message || 'Failed to initialize vulnerability scanning thread.'); } } } } catch (err) { setError('Connection timeout. Scanner microservice unavailable.'); console.error(err); } finally { setLoading(false); } }; const scanMethodologies = [ { id: 'Quick', title: 'Quick Scan', icon: 'bolt', desc: 'Rapid recon: HTTP headers audit, Nmap top-100 ports, SSLyze TLS check, technology fingerprinting & DNS lookup.', tools: ['Nmap', 'SSLyze', 'Headers', 'WHOIS'], duration: '~2-5 mins', price: '$4.99', colorClass: 'text-primary', requiredTier: 'free' }, { id: 'Advanced', title: 'Advanced Scan', icon: 'security', desc: 'Comprehensive deep crawl: All security modules, XSS/SQLi fuzzing, path traversal, Nuclei templates & OWASP ZAP passive analysis.', tools: ['Nuclei', 'ZAP Passive', 'Fuzzer', 'Dir Scan', 'Subfinder', 'Amass'], duration: '~20-40 mins', price: '$44.99', colorClass: 'text-primary', requiredTier: 'pro' }, { id: 'Deep', title: 'Deep Scan', icon: 'radar', desc: 'Exhaustive audit: All-port Nmap with vuln scripts, full TLS audit, OWASP ZAP active spider + active attack simulation.', tools: ['Nmap Full', 'ZAP Active', 'NSE Scripts', 'All Modules'], duration: '~1 hour+', price: '$99.99', colorClass: 'text-primary', requiredTier: 'enterprise' } ]; const getTierLevel = (tier) => { if (tier === 'enterprise') return 3; if (tier === 'pro') return 2; return 1; }; const userTierLevel = (user?.role === 'admin' || user?.role === 'super_admin') ? 3 : getTierLevel(user?.subscription_tier || 'free'); return (
Configure target parameters and execution methodology for a new vulnerability assessment.
You cannot use the {attemptedScan} methodology on your current plan.
If you need to use this feature, please upgrade your subscription plan to unlock advanced vulnerability scanning capabilities.
Your organization has used all allocated scan credits for {attemptedScan || scanType} Scans. To execute additional vulnerability scans, please upgrade your plan or purchase scan credits.
{/* Action Buttons */}Review target parameters before starting the scan pipeline
By initiating any scan, probe, or assessment through Larshield, you explicitly certify, represent, and warrant that you possess full, documented, and legally verifiable authorization from the owner of the target system to conduct active security assessments, penetration testing, or vulnerability scanning against it.
You acknowledge that scanning any computer, network, or application without proper authorization is illegal under applicable law — including, without limitation, the Computer Fraud and Abuse Act (US), the Computer Misuse Act (UK), the Information Technology Act (India), and equivalent statutes in other jurisdictions. Larshield is intended strictly for authorized security testing, such as systems you own, systems within a scope you have been contractually engaged to test, or environments explicitly designated for security research (e.g., CTF ranges, bug bounty programs with defined scope).
You acknowledge that vulnerability scanning and penetration testing are inherently intrusive activities. Depending on configuration, they may involve port scanning, service fingerprinting, exploitation simulation, or payload delivery, any of which could cause service degradation, data loss, or downtime on the target system.
By using Larshield, you accept full responsibility for any operational impact resulting from your use of the tool, and you agree to take reasonable precautions (e.g., scheduling scans during maintenance windows, using rate-limited or passive modes where appropriate) when testing production systems.
You agree to indemnify, defend, and hold harmless the Larshield project, its developer(s), contributors, and affiliates from any claims, damages, liabilities, costs, or losses (including reasonable legal fees) arising from your use of the Service — including any unauthorized or improper use.
Larshield is provided on an "AS IS" and "AS AVAILABLE" basis, without warranties of any kind, express or implied, including but not limited to fitness for a particular purpose or non-infringement. Larshield and its creators shall not be liable for any direct, indirect, incidental, or consequential damages resulting from use or misuse of the Service.
Larshield logs scan activity, including origin IP address, timestamp, scan configuration, and target parameters, for security, abuse-prevention, and accountability purposes.
In the event of an investigation into unauthorized access, abuse, or a legal inquiry, Larshield reserves the right to share relevant audit logs with law enforcement, hosting providers, or the affected system owner, as required or permitted by law.
You agree not to use Larshield to:
Scan results are stored per-user and are not shared with third parties except as required under Section 4.
Larshield may update this policy from time to time. Continued use of the Service after changes are posted constitutes acceptance of the revised policy.
By clicking "I Accept" below, you confirm that you have read, understood, and agree to be bound by this Security Policy & EULA.
{/* Checkbox Section inside Modal */}