Skip to content

Commit dc02a34

Browse files
committed
Migrate to client-side GitHub API with token auth, rename to SecurityLens
1 parent dfef710 commit dc02a34

File tree

7 files changed

+274
-196
lines changed

7 files changed

+274
-196
lines changed

README.md

Lines changed: 23 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,23 @@
1-
# Plugin Vulnerability Scanner
2-
3-
A vulnerability scanner for plugin architectures, focusing on memory, filesystem, and plugin system vulnerabilities.
4-
A comprehensive security vulnerability scanner for dependency management across multiple programming languages and package ecosystems. This tool helps identify security vulnerabilities in your project's dependencies, regardless of the programming language or package manager used.
5-
6-
https://dmontgomery40.github.io/plugin-vulnerability-scanner/
7-
8-
<p align="center">
9-
<a href="https://github.com/user-attachments/assets/c708b25e-ee33-45c8-baea-01e71a4061e8">
10-
<img src="https://private-user-images.githubusercontent.com/130489651/390199844-c708b25e-ee33-45c8-baea-01e71a4061e8.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzI2Njg5NDIsIm5iZiI6MTczMjY2ODY0MiwicGF0aCI6Ii8xMzA0ODk2NTEvMzkwMTk5ODQ0LWM3MDhiMjVlLWVlMzMtNDVjOC1iYWVhLTAxZTcxYTQwNjFlOC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTI3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTEyN1QwMDUwNDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT01NThlNzI2MTJhODFiYTk0ODQ1YmE1MGMyZmUwMDIyNjdhN2Q5NGU2NTBhZmYxNzk0ZjkzNTdjZTVlZmIwYzNlJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.vfCgiRbUTiLLhKYSaNco9YPuRR1ulskAxgMSvXm6Tjw" alt="Dashboard" width="45%"/>
11-
</a>
12-
</p>
13-
14-
15-
16-
17-
## Features
18-
19-
- Detects various types of security vulnerabilities:
20-
- Memory-related vulnerabilities (buffer overflows, memory leaks)
21-
- Filesystem vulnerabilities (path traversal, unsafe operations)
22-
- Plugin system vulnerabilities (unsafe loading, eval usage)
23-
- Event listener leaks
24-
- Unhandled file operations
25-
26-
### Multi-Language Support
27-
Analyzes dependencies and vulnerabilities across multiple package ecosystems:
28-
* JavaScript/Node.js (npm)
29-
* Python (pip, poetry)
30-
* Ruby (gem)
31-
* Java (Maven, Gradle)
32-
* PHP (Composer)
33-
* Go (go modules)
34-
* Rust (Cargo)
35-
### Vulnerability Detection
36-
* Dependency vulnerability scanning
37-
* Version compatibility checking
38-
* Known CVE detection
39-
* Outdated package identification
40-
* License compliance checking
41-
* Security advisory integration
42-
### Analysis Types
43-
* Deep dependency tree analysis
44-
* Transitive dependency checking
45-
* Supply chain vulnerability detection
46-
* Package integrity verification
47-
* Version constraint validation
48-
### Output Formats
49-
* JSON
50-
* Plain text
51-
* HTML reports
52-
* GitHub-flavored Markdown
53-
* CI/CD compatible formats
54-
55-
## Installation
56-
57-
```bash
58-
# Install globally via npm
59-
npm install -g plugin-vulnerability-scanner
60-
# Or run directly with npx
61-
npx plugin-vulnerability-scanner
62-
```
63-
64-
## Features in Development
65-
* Real-time vulnerability monitoring
66-
* Custom rule creation
67-
* Plugin ecosystem for custom checks
68-
* Integration with additional package managers
69-
* Enhanced CI/CD pipeline integration
70-
* Custom policy enforcement
71-
* Automated fix suggestions
72-
* Impact analysis reports
73-
74-
75-
### GitHub Actions
76-
77-
...
78-
```yaml
79-
- name: Security Scan
80-
uses: plugin-vulnerability-scanner/action@v1
81-
with:
82-
path: '.'
83-
fail-on: 'high'
84-
```
85-
### GitLab CI
86-
```yaml
87-
security_scan:
88-
image: plugin-vulnerability-scanner
89-
script:
90-
- plugin-vulnerability-scanner scan ./ --ci
91-
```
92-
Recommendations:
93-
bufferOverflow:
94-
Replace Buffer.allocUnsafe() with Buffer.alloc()
95-
96-
### Jenkins Pipeline
97-
...
98-
```groovy
99-
stage('Security Scan') {
100-
steps {
101-
sh 'plugin-vulnerability-scanner scan ./ --output json'
102-
}
103-
}
104-
```
105-
106-
## Contributing
107-
108-
Contributions are welcome! Please feel free to submit a Pull Request.
109-
Contributions are welcome! Please feel free to submit a Pull Request. Here's how you can contribute:
110-
1. Fork the repository
111-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
112-
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
113-
4. Push to the branch (`git push origin feature/amazing-feature`)
114-
5. Open a Pull Request
115-
116-
### Development Setup
117-
```bash
118-
git clone https://github.com/yourusername/plugin-vulnerability-scanner.git
119-
cd plugin-vulnerability-scanner
120-
npm install
121-
npm run dev
122-
```
123-
124-
## License
125-
126-
MIT
127-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
128-
## Support
129-
* Documentation: [https://plugin-vulnerability-scanner.dev](https://plugin-vulnerability-scanner.dev)
130-
* Issues: [GitHub Issues](https://github.com/DMontgomery40/plugin-vulnerability-scanner/issues)
131-
* Discussions: [GitHub Discussions](https://github.com/DMontgomery40/plugin-vulnerability-scanner/discussions)
1+
# SecurityLens (or your chosen name)
2+
An open-source security analysis platform for education and vulnerability discovery.
3+
4+
## Current Features
5+
- Static code analysis for common security vulnerabilities
6+
- Pattern-based vulnerability detection
7+
- Detailed explanations and recommendations
8+
9+
## Roadmap
10+
### Phase 1 (Current)
11+
- [x] Basic vulnerability scanning
12+
- [ ] CVE database integration
13+
- [ ] Dependency vulnerability checking
14+
15+
### Phase 2 (Future)
16+
- [ ] Binary analysis capabilities
17+
- [ ] Integration with reverse engineering tools
18+
- [ ] Interactive learning modules
19+
20+
### Phase 3 (Long-term)
21+
- [ ] Collaborative analysis features
22+
- [ ] Integration with additional security tools
23+
- [ ] Advanced binary analysis

netlify.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@
88
status = 200
99

1010
[functions]
11-
node_bundler = "esbuild"
11+
node_bundler = "esbuild"
12+
included_files = ["src/lib/**"]
13+
external_node_modules = ["@octokit/rest"]
14+
15+
[functions.scan-repository]
16+
timeout = 30 # Increase timeout to 30 seconds
17+
memory = 1024 # Increase memory to 1GB

src/components/ScannerUI.jsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { scanRepository } from '../lib/apiClient';
77
import { Alert, AlertDescription } from './ui/alert';
88
import VulnerabilityScanner from '../lib/scanner';
99
import ScanResults from './ScanResults';
10+
import { authManager } from '../lib/githubAuth';
11+
import { AlertDialog, AlertDialogContent, AlertDialogHeader } from './ui/alert-dialog';
1012

1113
const ScannerUI = () => {
1214
const [scanning, setScanning] = useState(false);
@@ -17,6 +19,8 @@ const ScannerUI = () => {
1719
const [progress, setProgress] = useState({ current: 0, total: 0 });
1820
const [scanResults, setScanResults] = useState(null);
1921
const [usedCache, setUsedCache] = useState(false);
22+
const [githubToken, setGithubToken] = useState(localStorage.getItem('gh_token') || '');
23+
const [showTokenDialog, setShowTokenDialog] = useState(false);
2024

2125
const handleFileUpload = async (event) => {
2226
const files = Array.from(event.target.files);
@@ -62,6 +66,11 @@ const ScannerUI = () => {
6266
const handleUrlScan = useCallback(async () => {
6367
if (!urlInput) return;
6468

69+
if (!authManager.hasToken()) {
70+
setShowTokenDialog(true);
71+
return;
72+
}
73+
6574
setScanning(true);
6675
setError(null);
6776
setScanResults(null);
@@ -101,6 +110,25 @@ const ScannerUI = () => {
101110
}
102111
}, [urlInput]);
103112

113+
const handleTokenSubmit = (token) => {
114+
if (!token) return;
115+
116+
if (!authManager.isValidTokenFormat(token)) {
117+
setError('Invalid token format. Please ensure you\'ve copied the entire token.');
118+
return;
119+
}
120+
121+
try {
122+
authManager.setToken(token);
123+
setShowTokenDialog(false);
124+
if (urlInput) {
125+
handleUrlScan();
126+
}
127+
} catch (error) {
128+
setError(error.message);
129+
}
130+
};
131+
104132
return (
105133
<div className="p-8 bg-gray-100 min-h-screen">
106134
{/* Main Input Section */}
@@ -219,7 +247,67 @@ const ScannerUI = () => {
219247
scanning={scanning}
220248
/>
221249
)}
250+
251+
{!githubToken && (
252+
<div className="bg-white p-6 rounded-lg shadow-sm mb-4">
253+
<h2 className="text-lg font-semibold text-gray-700 mb-4">GitHub Access Token</h2>
254+
<p className="text-sm text-gray-600 mb-4">
255+
To scan repositories, you'll need a GitHub personal access token.
256+
This stays in your browser and is never sent to any server.
257+
</p>
258+
<input
259+
type="password"
260+
placeholder="GitHub token"
261+
onChange={(e) => handleTokenSubmit(e.target.value)}
262+
className="w-full px-4 py-2 border rounded"
263+
/>
264+
<a
265+
href="https://github.com/settings/tokens/new"
266+
target="_blank"
267+
className="text-sm text-blue-600 hover:underline mt-2 inline-block"
268+
>
269+
Generate a token
270+
</a>
271+
</div>
272+
)}
222273
</div>
274+
275+
{/* Token Dialog */}
276+
<AlertDialog open={showTokenDialog} onClose={() => setShowTokenDialog(false)}>
277+
<AlertDialogContent>
278+
<AlertDialogHeader>
279+
<h2 className="text-lg font-semibold">GitHub Token Required</h2>
280+
</AlertDialogHeader>
281+
<div className="space-y-4">
282+
<div className="bg-blue-50 border border-blue-200 rounded p-3 text-sm">
283+
<strong>🔒 Security Note:</strong> Your token is stored only in your browser's local storage.
284+
It never leaves your device and is not sent to any external servers.
285+
</div>
286+
<p className="text-sm text-gray-600">
287+
To scan GitHub repositories, you'll need a Personal Access Token. Here's how to get one:
288+
</p>
289+
<ol className="list-decimal list-inside space-y-2 text-sm">
290+
<li>Go to <a
291+
href="https://github.com/settings/tokens/new"
292+
target="_blank"
293+
rel="noopener noreferrer"
294+
className="text-blue-600 hover:underline"
295+
>
296+
GitHub Token Settings
297+
</a></li>
298+
<li>Select either "Classic" or "Fine-grained" token</li>
299+
<li>Enable "repo" access permissions</li>
300+
<li>Generate and copy the token</li>
301+
</ol>
302+
<input
303+
type="password"
304+
placeholder="Paste your GitHub token here"
305+
className="w-full px-4 py-2 border rounded"
306+
onChange={(e) => handleTokenSubmit(e.target.value)}
307+
/>
308+
</div>
309+
</AlertDialogContent>
310+
</AlertDialog>
223311
</div>
224312
);
225313
};

src/lib/apiClient.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,28 @@ export async function scanRepository(url) {
1717
});
1818

1919
if (!response.ok) {
20-
const contentType = response.headers.get('content-type');
21-
if (contentType && contentType.includes('text/html')) {
20+
console.error('Scan failed with status:', response.status);
21+
const text = await response.text();
22+
console.error('Response body:', text);
23+
24+
try {
25+
const errorData = JSON.parse(text);
26+
throw new ApiError(errorData.error || 'Scan failed', response.status);
27+
} catch (e) {
2228
throw new ApiError(
23-
'Server error: The scanning service is not available. Please ensure Netlify functions are properly configured.',
24-
503
29+
`Server error (${response.status}): ${text.slice(0, 100)}...`,
30+
response.status
2531
);
2632
}
27-
28-
const data = await response.json();
29-
throw new ApiError(data.error || 'Scan failed', response.status);
3033
}
3134

3235
const data = await response.json();
3336
return data;
3437
} catch (error) {
38+
console.error('Scan error details:', error);
3539
if (error instanceof ApiError) {
3640
throw error;
3741
}
38-
if (error.name === 'SyntaxError') {
39-
throw new ApiError(
40-
'Server error: Invalid response from scanning service. Please check Netlify function logs.',
41-
500
42-
);
43-
}
4442
throw new ApiError('Scan failed: ' + error.message, 500);
4543
}
4644
}

src/lib/githubAuth.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
export class GitHubAuthManager {
2+
constructor() {
3+
this.tokenKey = 'security_lens_gh_token';
4+
this.token = this.loadToken();
5+
}
6+
7+
loadToken() {
8+
try {
9+
return localStorage.getItem(this.tokenKey);
10+
} catch (error) {
11+
console.warn('Unable to access localStorage:', error);
12+
return null;
13+
}
14+
}
15+
16+
setToken(token) {
17+
try {
18+
if (token) {
19+
localStorage.setItem(this.tokenKey, token);
20+
} else {
21+
localStorage.removeItem(this.tokenKey);
22+
}
23+
this.token = token;
24+
} catch (error) {
25+
console.error('Failed to save token:', error);
26+
throw new Error('Unable to save GitHub token. Please check your browser settings.');
27+
}
28+
}
29+
30+
hasToken() {
31+
return !!this.token;
32+
}
33+
34+
getToken() {
35+
return this.token;
36+
}
37+
38+
clearToken() {
39+
this.setToken(null);
40+
}
41+
42+
// Validate token format (basic check)
43+
isValidTokenFormat(token) {
44+
return /^(ghp_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$/.test(token);
45+
}
46+
}
47+
48+
export const authManager = new GitHubAuthManager();

0 commit comments

Comments
 (0)