# Python Security Standards

## No Hardcoded Secrets

NEVER hardcode secrets:

```python
# Bad - NEVER
API_KEY = "sk-abc123xyz789"
DATABASE_URL = "postgresql://user:password@host/db"

# Good - environment variables
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    api_key: str
    database_url: str
    model_config = {"env_prefix": "ROBOCO_"}
```

## SQL Injection Prevention

NEVER use string concatenation for SQL:

```python
# Bad - SQL injection vulnerability
query = f"SELECT * FROM users WHERE id = '{user_id}'"

# Good - parameterized query
result = await session.execute(
    select(User).where(User.id == user_id)
)
```

## Command Injection Prevention

NEVER pass user input directly to shell:

```python
# Bad - command injection
import os
os.system(f"process_file {filename}")

# Good - use subprocess with list
import subprocess
subprocess.run(["process_file", filename], check=True)
```

## No eval() or exec()

NEVER use on untrusted input:

```python
# Bad - code injection
result = eval(user_input)

# Good - safe parsing
import ast
result = ast.literal_eval(user_input)  # Only literals
```

## Non-Security Hashes

When hashing for non-security purposes:

```python
import hashlib

content_hash = hashlib.md5(
    content.encode(),
    usedforsecurity=False  # Required flag
).hexdigest()[:12]
```

## Security Tools

Run before merge:

```bash
# Security scan
uv run bandit -r roboco/ -ll

# Dependency audit
uv run pip-audit
```
