Archived
add analyze_plugins from metrics
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Analyze WordPress plugins for security vulnerabilities using security ratings."""
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
# Import security_rating functions
|
||||
from security_rating import get_plugin_info, calculate_security_score
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
"""Parse command-line arguments.
|
||||
|
||||
Returns:
|
||||
Parsed arguments namespace.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Analyze WordPress plugins for security issues using security ratings."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--input",
|
||||
"-i",
|
||||
required=True,
|
||||
help="Path to input JSON file (from output_recursive_plugins)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
"-o",
|
||||
help="Path to output JSON file (if not specified, prints to stdout)",
|
||||
default=None
|
||||
)
|
||||
parser.add_argument(
|
||||
"--detector-name",
|
||||
"-d",
|
||||
help="Name of detector to use in output (default: Security Rating Analyzer)",
|
||||
default="Security Rating Analyzer"
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def analyze_plugin(slug: str) -> dict:
|
||||
"""Analyze a single plugin and return its status.
|
||||
|
||||
Args:
|
||||
slug: Plugin slug to analyze.
|
||||
|
||||
Returns:
|
||||
Dict with status and reason fields.
|
||||
"""
|
||||
plugin_info = get_plugin_info(slug)
|
||||
|
||||
if not plugin_info:
|
||||
return {
|
||||
"status": "unknown",
|
||||
"reason": f"Could not fetch plugin information from WordPress.org API"
|
||||
}
|
||||
|
||||
score = calculate_security_score(plugin_info)
|
||||
|
||||
# Determine status based on score
|
||||
# Safe: score >= 65 (Excellent or Good)
|
||||
# Vulnerable: score < 65 (Moderate or Poor)
|
||||
if score >= 85:
|
||||
status = "safe"
|
||||
reason = f"Excellent security rating ({score}/100) — Actively maintained and trusted"
|
||||
elif score >= 65:
|
||||
status = "safe"
|
||||
reason = f"Good security rating ({score}/100) — Generally safe but monitor updates"
|
||||
elif score >= 45:
|
||||
status = "vulnerable"
|
||||
reason = f"Moderate security rating ({score}/100) — May be outdated or less popular"
|
||||
else:
|
||||
status = "vulnerable"
|
||||
reason = f"Poor security rating ({score}/100) — High risk of security issues"
|
||||
|
||||
result = {
|
||||
"status": status,
|
||||
"reason": reason,
|
||||
"score": score
|
||||
}
|
||||
|
||||
# Add version if available
|
||||
version = plugin_info.get("version")
|
||||
if version:
|
||||
result["version"] = version
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def analyze_directory(directory_name: str, plugins_dict: dict, detector_name: str) -> dict:
|
||||
"""Analyze all plugins in a directory.
|
||||
|
||||
Args:
|
||||
directory_name: Name of the directory being analyzed.
|
||||
plugins_dict: Dict mapping plugin slug to absolute path.
|
||||
detector_name: Name of the detector.
|
||||
|
||||
Returns:
|
||||
Analysis result in the specified format.
|
||||
"""
|
||||
timestamp = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
analyzed_plugins = {}
|
||||
|
||||
print(f"\nAnalyzing plugins for directory: {directory_name}")
|
||||
print(f"Found {len(plugins_dict)} plugins to analyze")
|
||||
|
||||
for slug, path in plugins_dict.items():
|
||||
print(f" Analyzing {slug}...", end=" ", flush=True)
|
||||
result = analyze_plugin(slug)
|
||||
analyzed_plugins[slug] = result
|
||||
print(f"{result['status']}")
|
||||
|
||||
return {
|
||||
"directory": directory_name,
|
||||
"wordpress": True,
|
||||
"name_of_detector": detector_name,
|
||||
"timestamp": timestamp,
|
||||
"plugins": analyzed_plugins
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for the plugin analyzer."""
|
||||
args = parse_args()
|
||||
|
||||
# Load input JSON
|
||||
try:
|
||||
with open(args.input, "r", encoding="utf-8") as f:
|
||||
input_data = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Input file '{args.input}' not found.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON in '{args.input}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Analyze each directory
|
||||
results = []
|
||||
|
||||
for directory_name, plugins_dict in input_data.items():
|
||||
if not plugins_dict:
|
||||
print(f"Skipping {directory_name} (no plugins found)")
|
||||
continue
|
||||
|
||||
analysis = analyze_directory(directory_name, plugins_dict, args.detector_name)
|
||||
results.append(analysis)
|
||||
|
||||
# Output results
|
||||
if args.output:
|
||||
with open(args.output, "w", encoding="utf-8") as f:
|
||||
json.dump(results, f, ensure_ascii=False, indent=2)
|
||||
print(f"\nWrote analysis results to {args.output}")
|
||||
else:
|
||||
print("\nAnalysis results:")
|
||||
print(json.dumps(results, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user