Skip to content

Commit 00a53da

Browse files
committed
Initial commit with core functionality and documentation
1 parent 025c4c1 commit 00a53da

16 files changed

+328
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Security Scan
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
scan:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- name: Install Dependencies
11+
run: |
12+
pip install -r requirements.txt
13+
- name: Run Secure Code Scanner
14+
run: |
15+
python scanner.py --repo "${{ github.repository }}"

config.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# config.yaml
2+
3+
rules:
4+
- name: "disallow_eval"
5+
pattern: "eval"
6+
severity: "critical"
7+
8+
- name: "disallow_exec"
9+
pattern: "exec"
10+
severity: "critical"
11+
12+
whitelisted_functions:
13+
- "safe_eval"
14+
15+
blacklisted_functions:
16+
- "exec"
17+
- "eval"
18+
19+
dependency_policies:
20+
check_outdated: true
21+
minimum_security_level: "high"
22+
allow_pre_releases: false
23+
disallowed_packages:
24+
- "pycrypto"
25+
26+
reporting:
27+
output_format: "json"
28+
verbosity: "high"
29+
include_timestamp: true
30+
critical_only: false
31+
save_path: "./reports"

core/clone_repo.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import git
2+
import tempfile
3+
import os
4+
import shutil
5+
6+
def clone_repository(repo_url):
7+
temp_dir = tempfile.mkdtemp()
8+
try:
9+
git.Repo.clone_from(repo_url, temp_dir)
10+
print(f"Repository cloned to {temp_dir}")
11+
return temp_dir
12+
except Exception as e:
13+
print(f"Error cloning repository: {e}")
14+
return None
15+
16+
def cleanup_repository(directory):
17+
if directory and os.path.exists(directory):
18+
shutil.rmtree(directory)
19+
print(f"Cleaned up directory: {directory}")

core/dependency_check.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import requests
2+
import os
3+
4+
def check_dependencies(repo_dir, config):
5+
results = []
6+
with open(os.path.join(repo_dir, "requirements.txt"), 'r') as file:
7+
for line in file:
8+
package_name, version = line.strip().split("==")
9+
vulnerabilities = check_vulnerabilities(package_name, version)
10+
if vulnerabilities:
11+
results.append(vulnerabilities)
12+
return results
13+
14+
def check_vulnerabilities(package_name, version):
15+
url = f"https://api.github.com/advisories/{package_name}/{version}"
16+
response = requests.get(url)
17+
if response.status_code == 200:
18+
return response.json()
19+
return []

core/detect_malicious.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import ast
2+
import re
3+
4+
def detect_malicious_patterns(file_path, config):
5+
results = []
6+
with open(file_path, 'r') as file:
7+
try:
8+
tree = ast.parse(file.read(), filename=file_path)
9+
for node in ast.walk(tree):
10+
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
11+
if node.func.id in config['blacklisted_functions']:
12+
results.append(f"Suspicious function `{node.func.id}` in {file_path}")
13+
except SyntaxError:
14+
print(f"Syntax error in {file_path}")
15+
return results

core/policy_config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import yaml
2+
3+
def load_policy(file_path='config.yaml'):
4+
try:
5+
with open(file_path, 'r') as file:
6+
config = yaml.safe_load(file)
7+
return config
8+
except FileNotFoundError:
9+
print("Configuration file not found. Using default settings.")
10+
return {}
11+
except yaml.YAMLError as e:
12+
print(f"Error reading configuration file: {e}")
13+
return {}

core/report.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import json
2+
import os
3+
from datetime import datetime
4+
5+
def generate_report(results, config):
6+
report_path = config['reporting']['save_path']
7+
os.makedirs(report_path, exist_ok=True)
8+
filename = os.path.join(report_path, f"scan_report_{datetime.now().isoformat()}.json")
9+
with open(filename, "w") as file:
10+
json.dump(results, file, indent=4)
11+
print(f"Report saved to {filename}")

core/scan_insecure.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from bandit.core import manager
2+
3+
def run_bandit_scan(file_path):
4+
bandit_manager = manager.BanditManager()
5+
bandit_manager.discover_files([file_path])
6+
bandit_manager.run_tests()
7+
results = [f"{issue.fname}:{issue.lineno} - {issue.text}" for issue in bandit_manager.get_issue_list()]
8+
return results

requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
GitPython
2+
bandit
3+
click
4+
requests
5+
pyyaml

scanner.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import click
2+
from core import clone_repo, detect_malicious, scan_insecure, dependency_check, policy_config, report
3+
4+
@click.command()
5+
@click.option("--repo", prompt="GitHub repository URL", help="URL of the GitHub repository")
6+
def main(repo):
7+
"""Secure Source Code Scanner CLI."""
8+
config = policy_config.load_policy("config.yaml")
9+
10+
# Clone repository
11+
repo_dir = clone_repo.clone_repository(repo)
12+
if not repo_dir:
13+
click.echo("Failed to clone repository.")
14+
return
15+
16+
# Scan repository for malicious code
17+
malicious_results = []
18+
insecure_results = []
19+
20+
# Perform scans on each .py file
21+
for root, _, files in os.walk(repo_dir):
22+
for file in files:
23+
if file.endswith('.py'):
24+
file_path = os.path.join(root, file)
25+
malicious_results += detect_malicious.detect_malicious_patterns(file_path, config)
26+
insecure_results += scan_insecure.run_bandit_scan(file_path)
27+
28+
# Check dependencies
29+
dependency_results = dependency_check.check_dependencies(repo_dir, config)
30+
31+
# Generate report
32+
results = {
33+
"malicious": malicious_results,
34+
"insecure": insecure_results,
35+
"dependencies": dependency_results
36+
}
37+
report.generate_report(results, config)
38+
39+
# Cleanup cloned repository
40+
clone_repo.cleanup_repository(repo_dir)
41+
42+
if __name__ == "__main__":
43+
main()

0 commit comments

Comments
 (0)