
Performing Security Code Review
- 29 installs
- 82 repo stars
- Updated August 2, 2026
- aaaaqwq/claude-code-skills
performing-security-code-review is a Claude Code skill that runs a security-focused code review to find vulnerabilities and recommend fixes.
About
This skill invokes a security-agent plugin to review code for vulnerabilities like SQL injection, XSS, authentication flaws, and insecure dependencies. A developer uses it when auditing a codebase or a specific query before shipping. It returns a structured report listing each finding with severity, the affected code, and recommended fixes.
- Runs a security-focused code review via the security-agent plugin
- Flags SQL injection, XSS, auth flaws, and insecure dependencies
- Produces a structured report with severity, locations, and remediation
Performing Security Code Review by the numbers
- 29 all-time installs (skills.sh)
- Ranked #1,498 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
performing-security-code-review capabilities & compatibility
- Capabilities
- security audit · code review · dependency scanning
- Use cases
- security audit · code review
What performing-security-code-review says it does
it analyzes code for potential vulnerabilities like sql injection, xss, authentication flaws, and insecure dependencies.
The security-agent produces a structured report detailing identified vulnerabilities, their severity, affected code locations, and recommended remediation steps.
npx skills add https://github.com/aaaaqwq/claude-code-skills --skill performing-security-code-reviewAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 29 |
|---|---|
| repo stars | ★ 82 |
| Last updated | August 2, 2026 |
| Repository | aaaaqwq/claude-code-skills ↗ |
What it does
Audit a codebase for security vulnerabilities and get a report with severity and remediation before release.
Who is it for?
Auditing code for security vulnerabilities before shipping
When should I use this skill?
You ask for a security scan, audit, or vulnerability check of code
What you get
A structured security report with vulnerabilities, severity, locations, and remediation steps.
- security vulnerability report
- remediation recommendations
By the numbers
- allowed-tools: Read, Write, Edit, Grep, Glob, Bash
Files
Security Agent
This skill provides automated assistance for security agent tasks.
Overview
This skill empowers Claude to act as a security expert, identifying and explaining potential vulnerabilities within code. It leverages the security-agent plugin to provide detailed security analysis, helping developers improve the security posture of their applications.
How It Works
1. Receiving Request: Claude identifies a user's request for a security review or audit of code. 2. Activating Security Agent: Claude invokes the security-agent plugin to analyze the provided code. 3. Generating Security Report: The security-agent produces a structured report detailing identified vulnerabilities, their severity, affected code locations, and recommended remediation steps.
When to Use This Skill
This skill activates when you need to:
- Review code for security vulnerabilities.
- Perform a security audit of a codebase.
- Identify potential security risks in a software application.
Examples
Example 1: Identifying SQL Injection Vulnerability
User request: "Please review this database query code for SQL injection vulnerabilities."
The skill will: 1. Activate the security-agent plugin to analyze the database query code. 2. Generate a report identifying potential SQL injection vulnerabilities, including the vulnerable code snippet, its severity, and suggested remediation, such as using parameterized queries.
Example 2: Checking for Insecure Dependencies
User request: "Can you check this project's dependencies for known security vulnerabilities?"
The skill will: 1. Utilize the security-agent plugin to scan the project's dependencies against known vulnerability databases. 2. Produce a report listing any vulnerable dependencies, their Common Vulnerabilities and Exposures (CVE) identifiers, and recommendations for updating to secure versions.
Best Practices
- Specificity: Provide the exact code or project you want reviewed.
- Context: Clearly state the security concerns you have regarding the code.
- Iteration: Use the findings to address vulnerabilities and request further reviews.
Integration
This skill integrates with Claude's code understanding capabilities and leverages the security-agent plugin to provide specialized security analysis. It can be used in conjunction with other code analysis tools to provide a comprehensive assessment of code quality and security.
Prerequisites
- Appropriate file access permissions
- Required dependencies installed
Instructions
1. Invoke this skill when the trigger conditions are met 2. Provide necessary context and parameters 3. Review the generated output 4. Apply modifications as needed
Output
The skill produces structured output relevant to the task.
Error Handling
- Invalid input: Prompts for correction
- Missing dependencies: Lists required components
- Permission errors: Suggests remediation steps
Resources
- Project documentation
- Related skills and commands
#!/usr/bin/env python3
"""
Example secure code snippets demonstrating how to remediate common vulnerabilities.
This module provides examples of secure coding practices to address various security concerns.
It includes functions demonstrating secure authentication, input validation, and more.
"""
import hashlib
import hmac
import os
import secrets
import re
def secure_password_hashing(password: str, salt: bytes = None) -> tuple[str, str]:
"""
Hashes a password using a strong hashing algorithm (e.g., bcrypt or scrypt).
Args:
password: The password to hash.
salt: Optional salt to use. If None, a new salt is generated.
Returns:
A tuple containing the salt (as a hex string) and the hash (as a hex string).
"""
try:
if salt is None:
salt = secrets.token_bytes(16) # Generate a 16-byte salt
hashed_password = hashlib.scrypt(
password.encode('utf-8'),
salt=salt,
n=2**14, # CPU/memory cost parameter
r=8, # Block size parameter
p=1, # Parallelization parameter
dklen=64 # Desired key length
)
return salt.hex(), hashed_password.hex()
except Exception as e:
print(f"Error in secure_password_hashing: {e}")
return None, None
def verify_password(password: str, salt_hex: str, hash_hex: str) -> bool:
"""
Verifies a password against a stored hash and salt.
Args:
password: The password to verify.
salt_hex: The salt used to hash the password (as a hex string).
hash_hex: The stored hash of the password (as a hex string).
Returns:
True if the password matches the stored hash, False otherwise.
"""
try:
salt = bytes.fromhex(salt_hex)
stored_hash = bytes.fromhex(hash_hex)
hashed_password = hashlib.scrypt(
password.encode('utf-8'),
salt=salt,
n=2**14, # CPU/memory cost parameter
r=8, # Block size parameter
p=1, # Parallelization parameter
dklen=64 # Desired key length
)
return hmac.compare_digest(hashed_password, stored_hash)
except ValueError as ve:
print(f"ValueError in verify_password (likely invalid hex): {ve}")
return False
except Exception as e:
print(f"Error in verify_password: {e}")
return False
def sanitize_input(input_string: str) -> str:
"""
Sanitizes user input to prevent common injection vulnerabilities.
This function removes or escapes characters that could be used in SQL injection,
cross-site scripting (XSS), or other injection attacks.
Args:
input_string: The string to sanitize.
Returns:
The sanitized string.
"""
try:
# Example: Escape HTML entities
sanitized_string = input_string.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """).replace("'", "'")
# Example: Remove potentially dangerous characters (e.g., for SQL injection)
sanitized_string = re.sub(r"[;'\"]", "", sanitized_string)
return sanitized_string
except Exception as e:
print(f"Error in sanitize_input: {e}")
return ""
def validate_email(email: str) -> bool:
"""
Validates an email address using a regular expression.
Args:
email: The email address to validate.
Returns:
True if the email address is valid, False otherwise.
"""
try:
# A more robust email regex can be used
email_regex = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return re.match(email_regex, email) is not None
except Exception as e:
print(f"Error in validate_email: {e}")
return False
def secure_file_upload(filename: str, file_content: bytes, upload_dir: str) -> str:
"""
Handles secure file uploads, preventing common vulnerabilities like path traversal.
Args:
filename: The original filename of the uploaded file.
file_content: The content of the uploaded file as bytes.
upload_dir: The directory to store the uploaded files.
Returns:
The path to the saved file, or None on error.
"""
try:
# Sanitize filename to prevent path traversal attacks
sanitized_filename = os.path.basename(filename) # Remove directory components
sanitized_filename = re.sub(r"[^a-zA-Z0-9._-]", "", sanitized_filename) # Remove invalid characters
if not sanitized_filename:
print("Invalid filename.")
return None
filepath = os.path.join(upload_dir, sanitized_filename)
# Ensure the upload directory exists
os.makedirs(upload_dir, exist_ok=True)
# Write the file content
with open(filepath, "wb") as f:
f.write(file_content)
return filepath
except OSError as ose:
print(f"OSError in secure_file_upload: {ose}")
return None
except Exception as e:
print(f"Error in secure_file_upload: {e}")
return None
def generate_secure_random_token(length: int = 32) -> str:
"""
Generates a cryptographically secure random token.
Args:
length: The length of the token in bytes.
Returns:
A hex-encoded string representing the random token.
"""
try:
return secrets.token_hex(length)
except Exception as e:
print(f"Error in generate_secure_random_token: {e}")
return None
if __name__ == "__main__":
# Example usage
password = "my_secret_password"
# Secure password hashing
salt, password_hash = secure_password_hashing(password)
if salt and password_hash:
print(f"Salt: {salt}")
print(f"Password Hash: {password_hash}")
# Verify password
is_valid = verify_password(password, salt, password_hash)
print(f"Password is valid: {is_valid}")
is_invalid = verify_password("wrong_password", salt, password_hash)
print(f"Wrong password is valid: {is_invalid}")
else:
print("Password hashing failed.")
# Input sanitization
user_input = "<script>alert('XSS');</script>"
sanitized_input = sanitize_input(user_input)
print(f"Original input: {user_input}")
print(f"Sanitized input: {sanitized_input}")
# Email validation
email = "test@example.com"
is_valid_email = validate_email(email)
print(f"Email '{email}' is valid: {is_valid_email}")
invalid_email = "invalid-email"
is_valid_invalid_email = validate_email(invalid_email)
print(f"Email '{invalid_email}' is valid: {is_valid_invalid_email}")
# Secure file upload (example)
filename = "important.txt"
file_content = b"This is some sensitive data."
upload_dir = "uploads"
filepath = secure_file_upload(filename, file_content, upload_dir)
if filepath:
print(f"File uploaded to: {filepath}")
else:
print("File upload failed.")
# Generate secure random token
token = generate_secure_random_token()
print(f"Secure random token: {token}")#!/usr/bin/env python3
"""
Example code snippets demonstrating common vulnerabilities.
This module provides examples of vulnerable code that can be used for
security testing and education. It includes examples of:
- SQL Injection
- Cross-Site Scripting (XSS)
- Path Traversal
- Command Injection
- Buffer Overflow (simulated in Python)
- Insecure Deserialization
"""
import os
import subprocess
import pickle
import base64
import sys
def sql_injection_example(user_input):
"""
Demonstrates a simple SQL injection vulnerability.
Args:
user_input (str): A string that could be malicious.
Returns:
str: A dummy SQL query string.
"""
try:
query = "SELECT * FROM users WHERE username = '" + user_input + "'"
# In a real application, this query would be executed against a database.
print(f"Generated query: {query}") # For demonstration purposes only
return query
except Exception as e:
print(f"Error in sql_injection_example: {e}")
return None
def xss_example(user_input):
"""
Demonstrates a simple XSS vulnerability.
Args:
user_input (str): A string that could contain malicious JavaScript.
Returns:
str: The potentially vulnerable HTML output.
"""
try:
output = "<h1>Welcome, " + user_input + "!</h1>"
# In a real application, this output would be rendered in a web page.
print(f"Generated HTML: {output}") # For demonstration purposes only
return output
except Exception as e:
print(f"Error in xss_example: {e}")
return None
def path_traversal_example(filename):
"""
Demonstrates a path traversal vulnerability.
Args:
filename (str): A filename provided by the user.
Returns:
str: The contents of the file (if accessible). Returns None on error.
"""
try:
# Vulnerable to path traversal: user can use "../" to access other files.
filepath = os.path.join("data", filename)
with open(filepath, "r") as f:
content = f.read()
print(f"File content (if accessible): {content}")
return content
except FileNotFoundError:
print(f"File not found: {filename}")
return None
except Exception as e:
print(f"Error in path_traversal_example: {e}")
return None
def command_injection_example(user_input):
"""
Demonstrates a command injection vulnerability.
Args:
user_input (str): A string that could contain malicious commands.
Returns:
str: The output of the executed command (if any). Returns None on error.
"""
try:
# Vulnerable to command injection: user can inject shell commands.
command = "echo " + user_input
result = subprocess.run(command, shell=True, capture_output=True, text=True)
output = result.stdout
print(f"Command output: {output}")
return output
except Exception as e:
print(f"Error in command_injection_example: {e}")
return None
def buffer_overflow_example(data, buffer_size):
"""
Simulates a buffer overflow vulnerability in Python.
Python is generally memory-safe, so this is a simplified simulation.
Args:
data (str): The data to write to the buffer.
buffer_size (int): The size of the buffer.
"""
try:
buffer = bytearray(buffer_size)
if len(data.encode('utf-8')) > buffer_size:
print("Simulating Buffer Overflow: Data exceeds buffer size.")
# Normally this would overwrite adjacent memory, but in Python,
# this will raise an IndexError. We avoid the error by truncating.
buffer[:] = data.encode('utf-8')[:buffer_size] # Truncate to buffer size
else:
buffer[:] = data.encode('utf-8')
print(f"Buffer content: {buffer.decode('utf-8', 'ignore')}")
except Exception as e:
print(f"Error in buffer_overflow_example: {e}")
def insecure_deserialization_example(serialized_data):
"""
Demonstrates an insecure deserialization vulnerability using pickle.
Args:
serialized_data (str): A base64 encoded pickled object.
Returns:
The deserialized object, or None if an error occurs.
"""
try:
# Deserialize the data (potentially dangerous if the data is untrusted)
decoded_data = base64.b64decode(serialized_data)
obj = pickle.loads(decoded_data)
print(f"Deserialized object: {obj}")
return obj
except Exception as e:
print(f"Error in insecure_deserialization_example: {e}")
return None
if __name__ == "__main__":
print("Example Vulnerable Code Snippets:")
print("\nSQL Injection Example:")
sql_injection_example("'; DROP TABLE users; --")
print("\nXSS Example:")
xss_example("<script>alert('XSS Vulnerability!')</script>")
print("\nPath Traversal Example:")
# Create a dummy file for the path traversal example.
if not os.path.exists("data"):
os.makedirs("data")
with open("data/test.txt", "w") as f:
f.write("This is a test file.")
path_traversal_example("../example_code_vulnerable.py") # Attempt to access this file
print("\nCommand Injection Example:")
command_injection_example("&& ls -l")
print("\nBuffer Overflow Example:")
buffer_overflow_example("A" * 100, 10)
print("\nInsecure Deserialization Example:")
# Create a malicious object and serialize it.
class MaliciousClass:
def __reduce__(self):
return (os.system, ("rm -rf /",)) # DANGEROUS: Never do this in real code!
malicious_object = MaliciousClass()
serialized_data = base64.b64encode(pickle.dumps(malicious_object)).decode('utf-8')
print(f"Serialized data: {serialized_data}")
# WARNING: Deserializing this will execute the 'rm -rf /' command (if permitted)
# This line is commented out for safety. UNCOMMENT AT YOUR OWN RISK AND ONLY IN A SAFE ENVIRONMENT.
# insecure_deserialization_example(serialized_data)
print("\nNote: Some examples are commented out for safety. Exercise caution when running these examples.")Assets
Bundled resources for security-agent skill
- [ ] report_template.md: A Markdown template for generating security review reports with placeholders for findings, severity ratings, and remediation advice.
- [ ] example_code_vulnerable.py: Example code snippets demonstrating common vulnerabilities.
- [ ] example_code_secure.py: Corresponding secure code snippets demonstrating how to remediate the vulnerabilities.
Security Review Report
Date: [Date of Review] Project: [Project Name] Reviewer: [Reviewer Name/Security Agent]
Executive Summary
[Briefly summarize the overall security posture of the reviewed code. Highlight the most critical findings and recommendations.]
Scope of Review
[Clearly define the scope of the review, including the specific files, modules, or components that were analyzed. Example: "This review covers the authentication module located in /src/auth/ and the user profile management API endpoints."]
Methodology
[Describe the methods used for the security review. Example: "The review involved static code analysis, manual code inspection, and dynamic testing with sample payloads."]
Findings
Critical Vulnerabilities
[List any critical vulnerabilities identified. Critical vulnerabilities pose an immediate and significant risk to the application and its users.]
Vulnerability ID: CRIT-001 Description: [Detailed description of the vulnerability, including its potential impact. Example: "SQL injection vulnerability in the user search functionality. An attacker can inject arbitrary SQL code via the searchTerm parameter, potentially leading to data leakage or modification."] Severity: Critical Affected Component: /src/api/user_search.php Proof of Concept: [Provide a proof of concept demonstrating the vulnerability. Example: curl -X GET "https://example.com/api/user_search.php?searchTerm='; DROP TABLE users; --"] Recommendation: [Provide specific and actionable recommendations for remediation. Example: "Implement parameterized queries or prepared statements to prevent SQL injection."]
High Vulnerabilities
[List any high vulnerabilities identified. High vulnerabilities can lead to significant security breaches if exploited.]
Vulnerability ID: HIGH-002 Description: [Detailed description of the vulnerability, including its potential impact. Example: "Cross-site scripting (XSS) vulnerability in the user profile display. User-supplied input is not properly sanitized before being displayed, allowing an attacker to inject malicious JavaScript code."] Severity: High Affected Component: /src/profile/display.php Proof of Concept: [Provide a proof of concept demonstrating the vulnerability. Example: <script>alert('XSS')</script> inserted into the user's profile name.] Recommendation: [Provide specific and actionable recommendations for remediation. Example: "Implement proper output encoding using a library like OWASP Java Encoder or similar for your language."]
Medium Vulnerabilities
[List any medium vulnerabilities identified. Medium vulnerabilities may not be directly exploitable but could be chained with other vulnerabilities or lead to privilege escalation.]
Vulnerability ID: MED-003 Description: [Detailed description of the vulnerability, including its potential impact. Example: "Insecure direct object reference (IDOR) vulnerability in the password reset functionality. An attacker can potentially reset the password of another user by manipulating the user ID in the password reset request."] Severity: Medium Affected Component: /src/password_reset/reset.php Proof of Concept: [Provide a proof of concept demonstrating the vulnerability. Example: Changing the userId parameter in the password reset URL to another user's ID.] Recommendation: [Provide specific and actionable recommendations for remediation. Example: "Implement proper authorization checks to ensure that users can only reset their own passwords. Use a random, non-predictable token for password reset links."]
Low Vulnerabilities
[List any low vulnerabilities identified. Low vulnerabilities are typically minor issues that do not pose a significant risk but should still be addressed for best security practices.]
Vulnerability ID: LOW-004 Description: [Detailed description of the vulnerability, including its potential impact. Example: "Missing HTTP Strict Transport Security (HSTS) header. This can allow man-in-the-middle attacks to downgrade the connection to HTTP."] Severity: Low Affected Component: Web Server Configuration Proof of Concept: [Provide a proof of concept demonstrating the vulnerability. Example: Checking the HTTP response headers with a tool like curl -I and observing the absence of the Strict-Transport-Security header.] Recommendation: [Provide specific and actionable recommendations for remediation. Example: "Configure the web server to send the HSTS header with a long max-age and includeSubDomains directive."]
General Recommendations
[Provide general recommendations for improving the overall security of the application. Examples:
- Implement a comprehensive security testing strategy.
- Keep all software and dependencies up to date.
- Follow secure coding practices.]
Conclusion
[Summarize the key findings and recommendations. Emphasize the importance of addressing the identified vulnerabilities to protect the application and its users.]
Disclaimer: This security review is based on the information available at the time of the review. New vulnerabilities may be discovered in the future. It is important to continuously monitor and improve the security of the application.
References
Bundled resources for security-agent skill
- [ ] owasp_top_10.md: A summary of the OWASP Top 10 vulnerabilities with examples and remediation strategies.
- [ ] secure_coding_practices.md: A guide to secure coding practices for various languages and frameworks.
- [ ] api_documentation.md: Documentation for any external APIs used by the code being reviewed, focusing on security considerations.
#!/usr/bin/env python3
"""
security-agent - Analysis Script
Analyzes code snippets for common vulnerabilities (SQL injection, XSS, etc.) and generates a report.
Generated: 2025-12-10 03:48:17
"""
import os
import json
import argparse
from pathlib import Path
from typing import Dict, List
from datetime import datetime
class Analyzer:
def __init__(self, target_path: str):
self.target_path = Path(target_path)
self.stats = {
'total_files': 0,
'total_size': 0,
'file_types': {},
'issues': [],
'recommendations': []
}
def analyze_directory(self) -> Dict:
"""Analyze directory structure and contents."""
if not self.target_path.exists():
self.stats['issues'].append(f"Path does not exist: {self.target_path}")
return self.stats
for file_path in self.target_path.rglob('*'):
if file_path.is_file():
self.analyze_file(file_path)
return self.stats
def analyze_file(self, file_path: Path):
"""Analyze individual file."""
self.stats['total_files'] += 1
self.stats['total_size'] += file_path.stat().st_size
# Track file types
ext = file_path.suffix.lower()
if ext:
self.stats['file_types'][ext] = self.stats['file_types'].get(ext, 0) + 1
# Check for potential issues
if file_path.stat().st_size > 100 * 1024 * 1024: # 100MB
self.stats['issues'].append(f"Large file: {file_path} ({file_path.stat().st_size // 1024 // 1024}MB)")
if file_path.stat().st_size == 0:
self.stats['issues'].append(f"Empty file: {file_path}")
def generate_recommendations(self):
"""Generate recommendations based on analysis."""
if self.stats['total_files'] == 0:
self.stats['recommendations'].append("No files found - check target path")
if len(self.stats['file_types']) > 20:
self.stats['recommendations'].append("Many file types detected - consider organizing")
if self.stats['total_size'] > 1024 * 1024 * 1024: # 1GB
self.stats['recommendations'].append("Large total size - consider archiving old data")
def generate_report(self) -> str:
"""Generate analysis report."""
report = []
report.append("\n" + "="*60)
report.append(f"ANALYSIS REPORT - security-agent")
report.append("="*60)
report.append(f"Target: {self.target_path}")
report.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
report.append("")
# Statistics
report.append("📊 STATISTICS")
report.append(f" Total Files: {self.stats['total_files']:,}")
report.append(f" Total Size: {self.stats['total_size'] / 1024 / 1024:.2f} MB")
report.append(f" File Types: {len(self.stats['file_types'])}")
# Top file types
if self.stats['file_types']:
report.append("\n📁 TOP FILE TYPES")
sorted_types = sorted(self.stats['file_types'].items(), key=lambda x: x[1], reverse=True)[:5]
for ext, count in sorted_types:
report.append(f" {ext or 'no extension'}: {count} files")
# Issues
if self.stats['issues']:
report.append(f"\n⚠️ ISSUES ({len(self.stats['issues'])})")
for issue in self.stats['issues'][:10]:
report.append(f" - {issue}")
if len(self.stats['issues']) > 10:
report.append(f" ... and {len(self.stats['issues']) - 10} more")
# Recommendations
if self.stats['recommendations']:
report.append("\n💡 RECOMMENDATIONS")
for rec in self.stats['recommendations']:
report.append(f" - {rec}")
report.append("")
return "\n".join(report)
def main():
parser = argparse.ArgumentParser(description="Analyzes code snippets for common vulnerabilities (SQL injection, XSS, etc.) and generates a report.")
parser.add_argument('target', help='Target directory to analyze')
parser.add_argument('--output', '-o', help='Output report file')
parser.add_argument('--json', action='store_true', help='Output as JSON')
args = parser.parse_args()
print(f"🔍 Analyzing {args.target}...")
analyzer = Analyzer(args.target)
stats = analyzer.analyze_directory()
analyzer.generate_recommendations()
if args.json:
output = json.dumps(stats, indent=2)
else:
output = analyzer.generate_report()
if args.output:
Path(args.output).write_text(output)
print(f"✓ Report saved to {args.output}")
else:
print(output)
return 0 if len(stats['issues']) == 0 else 1
if __name__ == "__main__":
import sys
sys.exit(main())
Scripts
Bundled resources for security-agent skill
- [ ] code_analyzer.py: Analyzes code snippets for common vulnerabilities (SQL injection, XSS, etc.) and generates a report.
- [ ] dependency_checker.py: Checks project dependencies for known security vulnerabilities using tools like
safetyorpip audit. - [ ] report_formatter.py: Formats the security review findings into a structured report (e.g., JSON, Markdown) for easy consumption.
Related skills
FAQ
What vulnerabilities does it check for?
SQL injection, XSS, authentication flaws, and insecure dependencies, per the skill description.
What does it produce?
A structured report detailing vulnerabilities, severity, affected code locations, and recommended remediation steps.