chore(skills): добавлены скиллы docstring и security-audit
- Зачем:
- напоминание моделям про Google-style docstring'ы и Ruff-конфиг.
- чеклист безопасности для ревью кода и зависимостей.
- Что:
- добавлен docstring (DeerHide): вычищены мёртвые ссылки, добавлен Ruff select, правило языка проекта.
- добавлен security-audit: чеклист OWASP, severity-уровни, формат отчёта.
- убраны test-generator (Node.js стек) и api-docs (избыточен).
- Проверка:
- ls agents/.agents/skills/{docstring,security-audit}/SKILL.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
168b40ddd7
commit
77adaad441
2 files changed
+673
No files matched your search
@@ -0,0 +1,445 @@
|
|||||||
|
---
|
||||||
|
name: python-docstring
|
||||||
|
description: A skill for writing consistent, well-structured Python docstrings following the Google style convention.
|
||||||
|
metadata:
|
||||||
|
author: Deerhide
|
||||||
|
version: 1.0.0
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python Docstring Skill
|
||||||
|
|
||||||
|
## When to use this skill?
|
||||||
|
|
||||||
|
- Use this skill when writing or updating Python documentation strings (docstrings).
|
||||||
|
- This skill is useful for ensuring consistent documentation across a Python codebase.
|
||||||
|
- It should be applied when documenting modules, classes, functions, methods, and attributes.
|
||||||
|
- Use it during code reviews to verify docstring quality and completeness.
|
||||||
|
|
||||||
|
# Language
|
||||||
|
|
||||||
|
Язык docstring'ов определяется по проекту: если в существующем коде комментарии и docstring'ы на русском — пиши на русском, если на английском — на английском. Не смешивай языки внутри одного проекта.
|
||||||
|
|
||||||
|
# Docstring Style Convention
|
||||||
|
|
||||||
|
We follow the **Google style** docstring convention. This style is chosen for its:
|
||||||
|
- Readability and clean formatting
|
||||||
|
- Wide adoption in the Python community
|
||||||
|
- Excellent support in documentation tools (Sphinx, MkDocs)
|
||||||
|
- Native support in linting tools (Ruff, Pylint)
|
||||||
|
|
||||||
|
# Module Docstrings
|
||||||
|
|
||||||
|
Every Python module should start with a docstring describing its purpose.
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Module for handling user authentication and session management.
|
||||||
|
|
||||||
|
This module provides utilities for user authentication, token generation,
|
||||||
|
and session lifecycle management. It integrates with OAuth2 providers
|
||||||
|
and supports JWT-based authentication.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Basic usage of the authentication service::
|
||||||
|
|
||||||
|
from auth import AuthService
|
||||||
|
|
||||||
|
service = AuthService(secret_key="my-secret")
|
||||||
|
token = service.create_token(user_id=123)
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
DEFAULT_TOKEN_EXPIRY (int): Default token expiration time in seconds.
|
||||||
|
SUPPORTED_ALGORITHMS (list): List of supported JWT algorithms.
|
||||||
|
|
||||||
|
Todo:
|
||||||
|
* Add support for refresh tokens
|
||||||
|
* Implement rate limiting for failed attempts
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_TOKEN_EXPIRY = 3600
|
||||||
|
SUPPORTED_ALGORITHMS = ["HS256", "RS256"]
|
||||||
|
```
|
||||||
|
|
||||||
|
# Class Docstrings
|
||||||
|
|
||||||
|
Class docstrings should describe the class purpose and list its attributes.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class UserRepository:
|
||||||
|
"""Repository for managing user data persistence.
|
||||||
|
|
||||||
|
This class provides CRUD operations for user entities and handles
|
||||||
|
database connections and transactions.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
connection: Database connection instance.
|
||||||
|
table_name: Name of the users table.
|
||||||
|
cache_enabled: Whether caching is enabled for queries.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Creating and using a repository::
|
||||||
|
|
||||||
|
repo = UserRepository(connection=db_conn)
|
||||||
|
user = repo.find_by_id(user_id=42)
|
||||||
|
repo.save(user)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, connection: DatabaseConnection) -> None:
|
||||||
|
"""Initialize the UserRepository.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connection: Active database connection to use for operations.
|
||||||
|
"""
|
||||||
|
self.connection = connection
|
||||||
|
self.table_name = "users"
|
||||||
|
self.cache_enabled = True
|
||||||
|
```
|
||||||
|
|
||||||
|
# Function and Method Docstrings
|
||||||
|
|
||||||
|
Functions and methods should document their purpose, arguments, return values, and exceptions.
|
||||||
|
|
||||||
|
## Basic Function
|
||||||
|
|
||||||
|
```python
|
||||||
|
def calculate_discount(price: float, percentage: float) -> float:
|
||||||
|
"""Calculate the discounted price.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
price: Original price of the item.
|
||||||
|
percentage: Discount percentage (0-100).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The discounted price after applying the percentage reduction.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If percentage is not between 0 and 100.
|
||||||
|
TypeError: If price or percentage are not numeric.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> calculate_discount(100.0, 20)
|
||||||
|
80.0
|
||||||
|
"""
|
||||||
|
if not 0 <= percentage <= 100:
|
||||||
|
raise ValueError("Percentage must be between 0 and 100")
|
||||||
|
return price * (1 - percentage / 100)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Method with Complex Arguments
|
||||||
|
|
||||||
|
```python
|
||||||
|
def create_user(
|
||||||
|
self,
|
||||||
|
username: str,
|
||||||
|
email: str,
|
||||||
|
*,
|
||||||
|
role: str = "user",
|
||||||
|
metadata: dict[str, Any] | None = None,
|
||||||
|
) -> User:
|
||||||
|
"""Create a new user in the system.
|
||||||
|
|
||||||
|
Creates a user entity with the provided information and persists
|
||||||
|
it to the database. Sends a welcome email upon successful creation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
username: Unique username for the new user. Must be alphanumeric
|
||||||
|
and between 3-50 characters.
|
||||||
|
email: Valid email address for the user.
|
||||||
|
role: User role assignment. Defaults to "user".
|
||||||
|
Valid options are "user", "admin", "moderator".
|
||||||
|
metadata: Optional dictionary of additional user metadata.
|
||||||
|
Keys must be strings, values can be any JSON-serializable type.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The newly created User instance with assigned ID.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
DuplicateUserError: If username or email already exists.
|
||||||
|
ValidationError: If input validation fails.
|
||||||
|
DatabaseError: If database operation fails.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This method triggers a background task for sending the welcome email.
|
||||||
|
The email sending is non-blocking and failures are logged but not raised.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Creating a basic user::
|
||||||
|
|
||||||
|
user = service.create_user(
|
||||||
|
username="johndoe",
|
||||||
|
email="john@example.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
Creating an admin user with metadata::
|
||||||
|
|
||||||
|
admin = service.create_user(
|
||||||
|
username="admin",
|
||||||
|
email="admin@example.com",
|
||||||
|
role="admin",
|
||||||
|
metadata={"department": "IT"}
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Async Functions
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def fetch_user_data(user_id: int, timeout: float = 30.0) -> UserData:
|
||||||
|
"""Fetch user data from the remote service.
|
||||||
|
|
||||||
|
Asynchronously retrieves user information from the external API
|
||||||
|
with automatic retry logic for transient failures.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: Unique identifier of the user to fetch.
|
||||||
|
timeout: Maximum time in seconds to wait for response.
|
||||||
|
Defaults to 30.0 seconds.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
UserData object containing the user's information.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
UserNotFoundError: If no user exists with the given ID.
|
||||||
|
TimeoutError: If the request exceeds the timeout duration.
|
||||||
|
ServiceUnavailableError: If the remote service is unreachable.
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
# Generator and Iterator Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
def paginate_results(
|
||||||
|
query: Query,
|
||||||
|
page_size: int = 100,
|
||||||
|
) -> Iterator[list[Record]]:
|
||||||
|
"""Paginate through query results.
|
||||||
|
|
||||||
|
Yields pages of records from the query, handling cursor-based
|
||||||
|
pagination automatically.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
query: Database query to paginate.
|
||||||
|
page_size: Number of records per page. Defaults to 100.
|
||||||
|
|
||||||
|
Yields:
|
||||||
|
Lists of Record objects, each list containing up to page_size items.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> for page in paginate_results(query, page_size=50):
|
||||||
|
... process_records(page)
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
# Property Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
@property
|
||||||
|
def full_name(self) -> str:
|
||||||
|
"""Return the full name of the user.
|
||||||
|
|
||||||
|
Combines first_name and last_name with proper spacing.
|
||||||
|
Returns an empty string if both names are unset.
|
||||||
|
"""
|
||||||
|
return f"{self.first_name} {self.last_name}".strip()
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_active(self) -> bool:
|
||||||
|
"""Return whether the user account is currently active.
|
||||||
|
|
||||||
|
An account is considered active if it has been verified
|
||||||
|
and has not been suspended or deleted.
|
||||||
|
"""
|
||||||
|
return self.verified and not self.suspended
|
||||||
|
```
|
||||||
|
|
||||||
|
# Context Manager Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
@contextmanager
|
||||||
|
def database_transaction(
|
||||||
|
connection: Connection,
|
||||||
|
isolation_level: str = "READ_COMMITTED",
|
||||||
|
) -> Iterator[Transaction]:
|
||||||
|
"""Context manager for database transactions.
|
||||||
|
|
||||||
|
Provides automatic commit on success and rollback on failure.
|
||||||
|
Nested transactions are supported via savepoints.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
connection: Active database connection.
|
||||||
|
isolation_level: Transaction isolation level.
|
||||||
|
Options: "READ_UNCOMMITTED", "READ_COMMITTED",
|
||||||
|
"REPEATABLE_READ", "SERIALIZABLE".
|
||||||
|
Defaults to "READ_COMMITTED".
|
||||||
|
|
||||||
|
Yields:
|
||||||
|
Transaction object for executing queries.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TransactionError: If transaction cannot be started.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> with database_transaction(conn) as tx:
|
||||||
|
... tx.execute("INSERT INTO users VALUES (?)", [user])
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
# Dataclass and Pydantic Model Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
@dataclass
|
||||||
|
class OrderItem:
|
||||||
|
"""Represents a single item in an order.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
product_id: Unique identifier of the product.
|
||||||
|
quantity: Number of units ordered. Must be positive.
|
||||||
|
unit_price: Price per unit in the order currency.
|
||||||
|
discount: Applied discount as a decimal (0.0-1.0).
|
||||||
|
"""
|
||||||
|
|
||||||
|
product_id: str
|
||||||
|
quantity: int
|
||||||
|
unit_price: Decimal
|
||||||
|
discount: Decimal = Decimal("0.0")
|
||||||
|
|
||||||
|
|
||||||
|
class UserSettings(BaseModel):
|
||||||
|
"""User preference settings.
|
||||||
|
|
||||||
|
Stores user-configurable settings for the application,
|
||||||
|
including notification preferences and display options.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
theme: UI theme preference. Either "light" or "dark".
|
||||||
|
notifications_enabled: Whether to send notifications.
|
||||||
|
language: Preferred language code (ISO 639-1).
|
||||||
|
timezone: User's timezone (IANA format).
|
||||||
|
"""
|
||||||
|
|
||||||
|
theme: Literal["light", "dark"] = "light"
|
||||||
|
notifications_enabled: bool = True
|
||||||
|
language: str = "en"
|
||||||
|
timezone: str = "UTC"
|
||||||
|
```
|
||||||
|
|
||||||
|
# Enum Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
class OrderStatus(Enum):
|
||||||
|
"""Status values for order lifecycle.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
PENDING: Order created but not yet processed.
|
||||||
|
CONFIRMED: Order confirmed and awaiting fulfillment.
|
||||||
|
SHIPPED: Order has been shipped to customer.
|
||||||
|
DELIVERED: Order successfully delivered.
|
||||||
|
CANCELLED: Order was cancelled before fulfillment.
|
||||||
|
"""
|
||||||
|
|
||||||
|
PENDING = "pending"
|
||||||
|
CONFIRMED = "confirmed"
|
||||||
|
SHIPPED = "shipped"
|
||||||
|
DELIVERED = "delivered"
|
||||||
|
CANCELLED = "cancelled"
|
||||||
|
```
|
||||||
|
|
||||||
|
# Exception Docstrings
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ValidationError(Exception):
|
||||||
|
"""Raised when input validation fails.
|
||||||
|
|
||||||
|
This exception is raised when user input or API request data
|
||||||
|
fails validation rules.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
field: Name of the field that failed validation.
|
||||||
|
message: Human-readable error message.
|
||||||
|
code: Machine-readable error code for client handling.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> raise ValidationError(
|
||||||
|
... field="email",
|
||||||
|
... message="Invalid email format",
|
||||||
|
... code="INVALID_EMAIL"
|
||||||
|
... )
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, field: str, message: str, code: str) -> None:
|
||||||
|
"""Initialize ValidationError.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
field: Name of the field that failed validation.
|
||||||
|
message: Human-readable description of the error.
|
||||||
|
code: Machine-readable error code.
|
||||||
|
"""
|
||||||
|
self.field = field
|
||||||
|
self.message = message
|
||||||
|
self.code = code
|
||||||
|
super().__init__(f"{field}: {message}")
|
||||||
|
```
|
||||||
|
|
||||||
|
# Docstring Sections Reference
|
||||||
|
|
||||||
|
The following sections are supported in Google style docstrings:
|
||||||
|
|
||||||
|
| Section | Purpose |
|
||||||
|
|---------|---------|
|
||||||
|
| `Args:` | Document function/method parameters |
|
||||||
|
| `Returns:` | Describe the return value |
|
||||||
|
| `Yields:` | Describe yielded values (generators) |
|
||||||
|
| `Raises:` | List exceptions that may be raised |
|
||||||
|
| `Attributes:` | Document class/module attributes |
|
||||||
|
| `Example:` / `Examples:` | Provide usage examples |
|
||||||
|
| `Note:` | Additional information or caveats |
|
||||||
|
| `Warning:` | Important warnings for users |
|
||||||
|
| `Todo:` | Future improvements or tasks |
|
||||||
|
| `See Also:` | References to related functions/classes |
|
||||||
|
|
||||||
|
# Best Practices
|
||||||
|
|
||||||
|
1. **Be Concise**: First line should be a brief summary under 79 characters.
|
||||||
|
2. **Use Imperative Mood**: Write "Calculate the sum" not "Calculates the sum".
|
||||||
|
3. **Document All Public APIs**: Every public function, class, and method needs a docstring.
|
||||||
|
4. **Rely on Type Hints**: Avoid duplicating type information in docstrings when type hints are present. Modern documentation tools extract types from annotations.
|
||||||
|
5. **Provide Examples**: Complex functions benefit from usage examples.
|
||||||
|
6. **Document Exceptions**: List all exceptions that can be raised.
|
||||||
|
7. **Keep Updated**: Update docstrings when code changes.
|
||||||
|
8. **Use Proper Indentation**: Continuation lines should be indented consistently.
|
||||||
|
|
||||||
|
# Linting Configuration
|
||||||
|
|
||||||
|
Recommended Ruff configuration for `pyproject.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["D", "F", "E", "W", "I", "UP", "B", "SIM", "S", "A", "C90", "RET", "PERF"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "google"
|
||||||
|
```
|
||||||
|
|
||||||
|
Key rule groups: **D** (docstrings), **F** (pyflakes), **E/W** (pycodestyle),
|
||||||
|
**I** (imports), **UP** (pyupgrade), **B** (bugbear), **SIM** (simplify),
|
||||||
|
**S** (security/bandit), **A** (builtins shadowing), **C90** (complexity),
|
||||||
|
**RET** (return statements), **PERF** (performance).
|
||||||
|
|
||||||
|
# Common Ruff Docstring Rules
|
||||||
|
|
||||||
|
| Rule | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| D100 | Missing docstring in public module |
|
||||||
|
| D101 | Missing docstring in public class |
|
||||||
|
| D102 | Missing docstring in public method |
|
||||||
|
| D103 | Missing docstring in public function |
|
||||||
|
| D107 | Missing docstring in `__init__` |
|
||||||
|
| D200 | One-line docstring should fit on one line |
|
||||||
|
| D205 | 1 blank line required between summary and description |
|
||||||
|
| D400 | First line should end with a period |
|
||||||
|
| D401 | First line should be in imperative mood |
|
||||||
|
| D417 | Missing argument descriptions in docstring |
|
||||||
|
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
---
|
||||||
|
name: security-audit
|
||||||
|
description: Audit code and dependencies for security vulnerabilities. Use when reviewing PRs, checking dependencies, preparing for deployment, or when user mentions security, vulnerabilities, or audit.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Security Audit Skill
|
||||||
|
|
||||||
|
Perform comprehensive security audits on codebases to identify vulnerabilities before they reach production.
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- User mentions "security", "audit", "vulnerability", "CVE"
|
||||||
|
- Before deployment commands
|
||||||
|
- During PR reviews
|
||||||
|
- User asks about dependencies
|
||||||
|
- Periodic security checks
|
||||||
|
|
||||||
|
## Audit Checklist
|
||||||
|
|
||||||
|
### 1. Secrets Exposure
|
||||||
|
|
||||||
|
**Check for hardcoded secrets:**
|
||||||
|
```bash
|
||||||
|
# Search for common secret patterns
|
||||||
|
grep -rn "API_KEY\|SECRET\|TOKEN\|PASSWORD" --include="*.{js,ts,py,go,rb,java}" .
|
||||||
|
grep -rn "sk-\|pk_\|api_\|secret_" --include="*.{js,ts,py,go,rb,java}" .
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verify .gitignore:**
|
||||||
|
```bash
|
||||||
|
# Ensure sensitive files are ignored
|
||||||
|
cat .gitignore | grep -E "\.env|secret|credential|\.pem|\.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check git history for leaked secrets:**
|
||||||
|
```bash
|
||||||
|
# Search recent commits (requires git-secrets or truffleHog)
|
||||||
|
git log -p --all -S "API_KEY" --since="30 days ago"
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ Pass criteria:
|
||||||
|
- No hardcoded API keys, tokens, or passwords
|
||||||
|
- `.env` files in `.gitignore`
|
||||||
|
- No secrets in git history
|
||||||
|
|
||||||
|
### 2. Dependency Vulnerabilities
|
||||||
|
|
||||||
|
**Node.js:**
|
||||||
|
```bash
|
||||||
|
npm audit
|
||||||
|
# or
|
||||||
|
yarn audit
|
||||||
|
# or
|
||||||
|
pnpm audit
|
||||||
|
```
|
||||||
|
|
||||||
|
**Python:**
|
||||||
|
```bash
|
||||||
|
pip-audit
|
||||||
|
# or
|
||||||
|
safety check
|
||||||
|
```
|
||||||
|
|
||||||
|
**Go:**
|
||||||
|
```bash
|
||||||
|
govulncheck ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rust:**
|
||||||
|
```bash
|
||||||
|
cargo audit
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ Pass criteria:
|
||||||
|
- No critical vulnerabilities
|
||||||
|
- No high vulnerabilities > 30 days old
|
||||||
|
- Dependencies updated within last 90 days
|
||||||
|
|
||||||
|
### 3. Input Validation
|
||||||
|
|
||||||
|
**Check for:**
|
||||||
|
- User inputs sanitized before use
|
||||||
|
- SQL queries use parameterized statements
|
||||||
|
- File paths validated and sandboxed
|
||||||
|
- HTML content escaped before rendering
|
||||||
|
- Command injection prevention
|
||||||
|
|
||||||
|
**Common vulnerable patterns:**
|
||||||
|
```javascript
|
||||||
|
// BAD: SQL injection
|
||||||
|
db.query(`SELECT * FROM users WHERE id = ${userId}`)
|
||||||
|
|
||||||
|
// GOOD: Parameterized query
|
||||||
|
db.query('SELECT * FROM users WHERE id = ?', [userId])
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# BAD: Command injection
|
||||||
|
os.system(f"convert {user_file}")
|
||||||
|
|
||||||
|
# GOOD: Use subprocess with list
|
||||||
|
subprocess.run(["convert", user_file], check=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Authentication & Authorization
|
||||||
|
|
||||||
|
**Check for:**
|
||||||
|
- Passwords hashed with bcrypt/argon2 (not MD5/SHA1)
|
||||||
|
- Session tokens are cryptographically random
|
||||||
|
- Sessions expire appropriately
|
||||||
|
- CSRF protection on state-changing endpoints
|
||||||
|
- Rate limiting on auth endpoints
|
||||||
|
- Account lockout after failed attempts
|
||||||
|
|
||||||
|
**Look for:**
|
||||||
|
```javascript
|
||||||
|
// BAD: Weak hashing
|
||||||
|
crypto.createHash('md5').update(password)
|
||||||
|
|
||||||
|
// GOOD: Bcrypt
|
||||||
|
bcrypt.hash(password, 12)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. HTTPS & Transport Security
|
||||||
|
|
||||||
|
**Check for:**
|
||||||
|
- HTTPS enforced (HSTS header)
|
||||||
|
- Secure cookie flags (`Secure`, `HttpOnly`, `SameSite`)
|
||||||
|
- No mixed content warnings
|
||||||
|
- TLS 1.2+ required
|
||||||
|
|
||||||
|
### 6. Error Handling
|
||||||
|
|
||||||
|
**Check for:**
|
||||||
|
- Stack traces not exposed in production
|
||||||
|
- Generic error messages for users
|
||||||
|
- Detailed errors only in logs
|
||||||
|
- Sensitive data not in error messages
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// BAD: Exposes internals
|
||||||
|
res.status(500).send({ error: err.stack })
|
||||||
|
|
||||||
|
// GOOD: Generic message
|
||||||
|
res.status(500).send({ error: 'An unexpected error occurred' })
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. File Upload Security
|
||||||
|
|
||||||
|
If file uploads exist:
|
||||||
|
- Validate file type server-side (not just extension)
|
||||||
|
- Limit file size
|
||||||
|
- Scan for malware
|
||||||
|
- Store outside webroot
|
||||||
|
- Rename uploaded files
|
||||||
|
|
||||||
|
### 8. API Security
|
||||||
|
|
||||||
|
- Authentication required on all sensitive endpoints
|
||||||
|
- Authorization checks per resource
|
||||||
|
- Rate limiting implemented
|
||||||
|
- CORS configured restrictively
|
||||||
|
- API versioning in place
|
||||||
|
|
||||||
|
## Severity Levels
|
||||||
|
|
||||||
|
| Level | Description | Action Required |
|
||||||
|
|-------|-------------|-----------------|
|
||||||
|
| 🔴 Critical | Actively exploitable | Block deployment |
|
||||||
|
| 🟠 High | Exploitable with effort | Fix within 7 days |
|
||||||
|
| 🟡 Medium | Requires conditions | Fix within 30 days |
|
||||||
|
| 🟢 Low | Minimal impact | Fix when convenient |
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Security Audit Results
|
||||||
|
|
||||||
|
**Project:** [name]
|
||||||
|
**Date:** [date]
|
||||||
|
**Auditor:** Claude (automated)
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
| Severity | Count |
|
||||||
|
|----------|-------|
|
||||||
|
| 🔴 Critical | 0 |
|
||||||
|
| 🟠 High | 1 |
|
||||||
|
| 🟡 Medium | 2 |
|
||||||
|
| 🟢 Low | 3 |
|
||||||
|
|
||||||
|
### Findings
|
||||||
|
|
||||||
|
#### 1. [🟠 High] Hardcoded API Key
|
||||||
|
|
||||||
|
**Location:** `src/config.js:15`
|
||||||
|
**Description:** API key for payment provider is hardcoded
|
||||||
|
**Risk:** If source code is leaked, attackers gain API access
|
||||||
|
**Recommendation:** Move to environment variable
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- const STRIPE_KEY = 'sk_live_abc123...'
|
||||||
|
+ const STRIPE_KEY = process.env.STRIPE_SECRET_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. [🟡 Medium] Missing Rate Limiting
|
||||||
|
|
||||||
|
**Location:** `src/routes/auth.js`
|
||||||
|
**Description:** Login endpoint has no rate limiting
|
||||||
|
**Risk:** Enables brute force attacks
|
||||||
|
**Recommendation:** Add rate limiting middleware
|
||||||
|
|
||||||
|
### Recommendations
|
||||||
|
|
||||||
|
1. [ ] Fix critical and high issues before next deployment
|
||||||
|
2. [ ] Schedule medium issues for next sprint
|
||||||
|
3. [ ] Add low issues to backlog
|
||||||
|
4. [ ] Re-run audit after fixes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands to Run
|
||||||
|
|
||||||
|
After completing the audit, provide the user with:
|
||||||
|
|
||||||
|
1. Summary of findings
|
||||||
|
2. Prioritized fix list
|
||||||
|
3. Commands to address each issue
|
||||||
|
4. Timeline recommendation
|
||||||
Reference in new issue
Block a user