1. Refactor err2 to use scoped loadErr variable (MINOR - sonnet-review-bot)
The else-if branches are mutually exclusive, so the error variable
should be scoped inside the block, not declared outside with err2.
2. Sanitize DisplayName before embedding in Markdown (MINOR - security-review-bot)
Remote persona metadata is untrusted. Added sanitizeMarkdownText() to
escape Markdown special characters and strip control characters.
Applied to both the header title and the footer attribution.
3. Document YAML DoS mitigations (MINOR - security-review-bot)
Added comprehensive comment in remote_persona.go explaining existing
defenses: file size limit, file count cap, depth limit, node count cap,
and alias cycle detection. These collectively mitigate billion-laughs
and stack exhaustion attacks.
Add persona system for specialized review roles. Each persona defines:
- A specific review focus (security, architecture, documentation)
- Custom system prompt additions
- Personality/tone adjustments
Built-in personas: security, architect, docs
Custom personas: load from JSON via persona-file flag
Includes workspace validation to prevent path traversal attacks.
Closes#51
When reviewer-name is set, prepend "# Security Review" / "# Sonnet Review"
etc. as a top-level header. Makes it immediately obvious which role each
review represents in the Gitea UI, especially when multiple reviews come
from the same bot account.
Sentinel-based cleanup:
- Reviews embed <!-- review-bot:NAME --> in body (hidden HTML comment)
- Cleanup matches by sentinel, not token identity
- Each reviewer-name is a logical identity (sonnet, gpt, security)
- Same token can run multiple review types without conflict
- No extra API scopes needed
System prompt file (--system-prompt-file / SYSTEM_PROMPT_FILE):
- Loads a local file with additional review instructions
- Appended to system base as "Additional Review Instructions"
- Enables specialized reviews (security, performance, etc.)
- Partially addresses #5
Security review:
- SECURITY_REVIEW.md prompt focused on vulnerabilities
- 3rd CI matrix entry using same token, different prompt
- Focus: injection, auth, secrets, input validation, crypto, races
CI changes:
- REVIEWER_NAME passed from matrix.name
- SYSTEM_PROMPT_FILE passed from matrix (empty for standard reviews)
- 3 reviewers: sonnet (general), gpt (general), security (focused)