Skip to content

Commit e43177b

Browse files
committed
R5EAGT4WS
1 parent 913d2dd commit e43177b

File tree

2 files changed

+38
-188
lines changed

2 files changed

+38
-188
lines changed

src/components/ScanResults.jsx

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,16 @@
11
import React, { useState, useEffect } from 'react';
22
import { patterns, patternCategories, recommendations } from '../lib/patterns';
3-
3+
import VulnerabilityScanner from '../lib/scanner';
44

55
// Severity sort order
66
const severityOrder = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
77

8-
const ScanResults = ({ files, onRefreshRequest, scanning }) => {
9-
const [results, setResults] = useState(null);
8+
const ScanResults = ({ scanResults, onRefreshRequest, scanning }) => {
109
const [error, setError] = useState(null);
1110

12-
const runScan = async () => {
13-
try {
14-
const scanResults = await scan(files);
15-
setResults(scanResults);
16-
setError(null);
17-
} catch (err) {
18-
setError(err.message);
19-
setResults(null);
20-
}
21-
};
22-
23-
useEffect(() => {
24-
if (files && Object.keys(files).length > 0) {
25-
runScan();
26-
}
27-
}, [files]);
28-
29-
if (!results) return null;
11+
if (!scanResults) return null;
3012

31-
const { findings = {}, summary = {} } = results;
13+
const { findings = {}, summary = {} } = scanResults;
3214

3315
// Convert findings object to array for processing
3416
const vulnerabilities = Object.entries(findings).map(([type, data]) => {

src/components/ScannerUI.jsx

Lines changed: 34 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -248,193 +248,61 @@ const ScannerUI = () => {
248248

249249
return (
250250
<div className="p-8 bg-white min-h-screen">
251-
{/* Main Input Section */}
252-
<div className="max-w-3xl mx-auto mb-8">
253-
<h1 className="text-3xl font-bold text-gray-900 mb-4 flex items-center">
254-
<Shield className="h-8 w-8 mr-2" />
255-
SecurityLens
256-
</h1>
257-
<p className="text-gray-600 mb-6 max-w-2xl">
258-
Scans code for security vulnerabilities including code injection, authentication bypass,
259-
SQL injection, XSS, buffer issues, sensitive data exposure, and more. Supports JavaScript,
260-
TypeScript, Python, and other languages.
261-
</p>
262-
263-
{/* URL Input Section */}
264-
<div className="bg-gray-50 p-6 rounded-lg shadow-sm mb-4">
265-
<h2 className="text-lg font-semibold text-gray-700 mb-4">Scan Repository</h2>
266-
<div className="flex gap-4">
267-
<input
268-
type="text"
269-
value={urlInput}
270-
onChange={(e) => setUrlInput(e.target.value)}
271-
placeholder="Enter GitHub repository URL"
272-
className="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
273-
/>
274-
<button
275-
onClick={handleUrlScan}
276-
disabled={scanning || !urlInput}
277-
className={`px-6 py-2 rounded-md text-white font-medium ${
278-
scanning || !urlInput
279-
? 'bg-gray-400 cursor-not-allowed'
280-
: 'bg-blue-600 hover:bg-blue-700'
281-
}`}
282-
>
283-
{scanning ? 'Scanning...' : 'Scan Repository'}
284-
</button>
285-
</div>
286-
</div>
287-
288-
{/* File Upload Section */}
289-
<div className="bg-gray-50 p-6 rounded-lg shadow-sm">
290-
<h2 className="text-lg font-semibold text-gray-700 mb-4">Scan Local Files</h2>
291-
<div className="flex justify-center">
251+
<div className="flex flex-col gap-8 p-8">
252+
<div className="flex flex-col gap-4">
253+
{/* File Upload Section */}
254+
<div className="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
292255
<input
293256
type="file"
294-
id="fileInput"
295257
multiple
296258
onChange={handleFileUpload}
297259
className="hidden"
260+
id="file-upload"
298261
/>
299262
<label
300-
htmlFor="fileInput"
301-
className="inline-flex flex-col items-center justify-center px-4 py-6 bg-gray-50 rounded-lg border-2 border-dashed border-gray-300 cursor-pointer hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
263+
htmlFor="file-upload"
264+
className="cursor-pointer text-gray-600"
302265
>
303-
<div className="mb-2">
304-
<svg className="w-12 h-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
305-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
306-
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
307-
/>
308-
</svg>
266+
Drag and drop files here, or click to select files
267+
<div className="text-sm text-gray-500 mt-2">
268+
Supported files: js, jsx, ts, tsx, py, java, and more
309269
</div>
310-
<p className="text-gray-600">
311-
Drag and drop files here, or click to select files
312-
</p>
313-
<p className="text-sm text-gray-500 mt-1">
314-
Supported files: .js, .jsx, .ts, .tsx, .py, and more
315-
</p>
316270
</label>
317271
</div>
318-
</div>
319272

320-
{/* Progress Bar */}
321-
{scanning && progress.total > 0 && (
322-
<div className="mb-6">
323-
<div className="w-full bg-gray-300 rounded-full h-3">
324-
<div
325-
className="bg-blue-600 h-3 rounded-full transition-all duration-300"
326-
style={{ width: `${(progress.current / progress.total) * 100}%` }}
327-
></div>
328-
</div>
329-
<div className="text-sm text-gray-700 mt-2 text-center">
330-
{progress.current === progress.total
331-
? 'Processing results...'
332-
: `Scanning file ${progress.current} of ${progress.total}`
333-
}
273+
{/* Progress and Status */}
274+
{scanning && (
275+
<div className="text-center">
276+
<div className="animate-pulse text-blue-600">
277+
Scanning... {progress.current} of {progress.total} files
278+
</div>
334279
</div>
335-
</div>
336-
)}
280+
)}
337281

338-
{/* Success Message */}
339-
{successMessage && (
340-
<Alert className="mb-4" variant="default">
341-
<AlertDescription>{successMessage}</AlertDescription>
342-
</Alert>
343-
)}
344-
345-
{/* Error Message */}
346-
{error && (
347-
<Alert className="mb-4" variant="error">
348-
<AlertDescription>
349-
<AlertTriangle className="h-4 w-4 inline-block mr-2" />
282+
{error && (
283+
<div className="text-red-600 text-center">
350284
{error}
351-
</AlertDescription>
352-
</Alert>
353-
)}
285+
</div>
286+
)}
354287

355-
{/* Rate Limit Info */}
356-
{rateLimitInfo && rateLimitInfo.remaining < 10 && (
357-
<Alert className="mb-4" variant="warning">
358-
<AlertDescription>
359-
Rate limit: {rateLimitInfo.remaining} requests remaining.
360-
Resets at {new Date(rateLimitInfo.reset * 1000).toLocaleTimeString()}
361-
</AlertDescription>
362-
</Alert>
363-
)}
288+
{successMessage && (
289+
<div className="text-green-600 text-center">
290+
{successMessage}
291+
</div>
292+
)}
293+
</div>
364294

365295
{/* Scan Results */}
366-
{scanResults && (
367-
<ScanResults
368-
data={scanResults}
369-
usedCache={usedCache}
370-
onRefreshRequest={handleUrlScan}
371-
scanning={scanning}
296+
{scanResults && !scanning && (
297+
<ScanResults
298+
scanResults={scanResults}
299+
onRefreshRequest={() => {
300+
setScanResults(null);
301+
setSuccessMessage('');
302+
}}
372303
/>
373304
)}
374-
375-
{/* If user has no token, show a quick form to set one */}
376-
{!githubToken && (
377-
<div className="bg-gray-50 p-6 rounded-lg shadow-sm mb-4">
378-
<h2 className="text-lg font-semibold text-gray-700 mb-4">GitHub Access Token</h2>
379-
<p className="text-sm text-gray-600 mb-4">
380-
To scan repositories, you'll need a GitHub personal access token.
381-
This stays in your browser and is never sent to any server.
382-
</p>
383-
<input
384-
type="password"
385-
placeholder="GitHub token"
386-
onChange={(e) => handleTokenSubmit(e.target.value)}
387-
className="w-full px-4 py-2 border rounded"
388-
/>
389-
<a
390-
href="https://github.com/settings/tokens/new"
391-
target="_blank"
392-
className="text-sm text-blue-600 hover:underline mt-2 inline-block"
393-
>
394-
Generate a token
395-
</a>
396-
</div>
397-
)}
398305
</div>
399-
400-
{/* Token Dialog */}
401-
<AlertDialog open={showTokenDialog} onClose={() => setShowTokenDialog(false)}>
402-
<AlertDialogContent>
403-
<AlertDialogHeader>
404-
<h2 className="text-lg font-semibold">GitHub Token Required</h2>
405-
</AlertDialogHeader>
406-
<div className="space-y-4">
407-
<div className="bg-blue-50 border border-blue-200 rounded p-3 text-sm">
408-
<strong>🔒 Security Note:</strong> Your token is stored only in your browser's local storage.
409-
It never leaves your device and is not sent to any external servers.
410-
</div>
411-
<p className="text-sm text-gray-600">
412-
To scan GitHub repositories, you'll need a Personal Access Token. Here's how to get one:
413-
</p>
414-
<ol className="list-decimal list-inside space-y-2 text-sm">
415-
<li>
416-
Go to <a
417-
href="https://github.com/settings/tokens/new"
418-
target="_blank"
419-
rel="noopener noreferrer"
420-
className="text-blue-600 hover:underline"
421-
>
422-
GitHub Token Settings
423-
</a>
424-
</li>
425-
<li>Select either "Classic" or "Fine-grained" token</li>
426-
<li>Enable "repo" access permissions</li>
427-
<li>Generate and copy the token</li>
428-
</ol>
429-
<input
430-
type="password"
431-
placeholder="Paste your GitHub token here"
432-
className="w-full px-4 py-2 border rounded"
433-
onChange={(e) => handleTokenSubmit(e.target.value)}
434-
/>
435-
</div>
436-
</AlertDialogContent>
437-
</AlertDialog>
438306
</div>
439307
);
440308
};

0 commit comments

Comments
 (0)