Hermes — History
Core Context
- Owns security review for application code, dependencies, and CI workflow changes.
- Evaluates risk with the full pipeline in mind, not just single-file diffs.
Learnings
- Branch protection must stay intact; automation should use the shared
branch-protection-pr-workflowskill instead of bypasses. - The current pipeline chains GitHub crawl data, press correlation, AI analysis, content generation, and GitHub Pages deployment, so security review must cover every handoff.
- The safest fallback posture is Copilot CLI first, GitHub Models second, and a bounded no-AI summary path after that.
- Retry logic and prompt sanitation both matter for defense-in-depth when external content can influence analysis prompts.
- Prompt-injection hardening should layer untrusted-content boundaries, pre-render sanitization, output evidence guards, and a closing trusted-mission reminder; sanitize repo descriptions by stripping leading whitespace, escaping boundary-close tags, truncating length, and warning on common injection phrases.
- URL validation must use
urllib.parse.urlparse()instead of substring checks to avoid time-of-check-time-of-use (TOCTOU) vulnerabilities in test contexts and security checks (CodeQL hardening, PR #164). - Config-driven external HTTP fetchers must enforce the intended allowlist in code (HTTPS + approved hosts), per-request timeouts, bounded retries, and bounded concurrency before running in CI.
Cookie Consent & Privacy Policy (Issue #183) — 2026-05-25
Legal Text Patterns Used: - GDPR Article 6(1)(a) explicit consent (opt-in only, no pre-ticked boxes) - GDPR Article 5(1)(a) transparency — all data processors disclosed - GDPR Articles 13/14 privacy information requirements fully covered - GDPR Article 21 right to object — revocation mechanism documented - Zero dark patterns: "Accept all" and "Reject all" equally prominent - Plain English tone, no legalese; links to external authorities (ICO, Google, GitHub) - GA4 processor agreement noted; 14-month retention disclosed as default - Subject access requests via GitHub Issues + direct profile link (proportionate to non-commercial research context)
Files Created:
- content/privacy/_index.md — Hugo privacy policy (~580 words, covers all GDPR minima)
- data/cookieconsent.json — Cookie Consent v3 config (plain English copy, no manipulation)
Cookie Banner BaseURL-Aware Links — 2026-05-25
- Cookie-banner in-site links must not hardcode root-relative paths like
/privacy/because GitHub project Pages deploys SquadScope under/SquadScope/. - Data-file legal copy should use placeholders such as
__PRIVACY_URL__, with Hugo partials substituting them through URL helpers (relURLorabsURL) at render time.
PR #236 Security Review (2026-06-05)
- Security review of PR #236 external RSS feeds integration complete
- Verdict: Request changes (blocking issues found)
- Formal approval blocked by GitHub own-PR rules (self-authored by Hermes as PR author)
- Posted blocking security comment to PR #236
- Blocking Requirements:
- URL validation with
urllib.parse.urlparse(): enforce HTTPS + allowlist hosts only - Reject credentials, local/private/link-local hosts, unexpected ports
- Explicit per-request timeout in feed fetch code path
- Bounded retry/backoff behavior
- Optional
--max-workersconcurrency validation
- URL validation with
- Ownership: Bender assigned as revision owner to avoid Leela reviewing own implementation changes
- Impact: PR #236 cannot merge until security fixes implemented and re-reviewed
PR #236 Security Re-Review (2026-06-05 final)
- Re-reviewed PR #236 at Bender fix commit
e91e2a5b33b816191148125d40192b3fff8fbc6a - All security blockers resolved:
urllib.parse.urlparse()validation implemented with HTTPS + allowlist enforcement- Credentials, localhost/private IPs, invalid ports rejected
- RSS fetches use
urlopen(..., timeout=DEFAULT_FETCH_TIMEOUT_SECONDS)with bounded retries - Parallel RSS crawling capped at
DEFAULT_MAX_WORKERS;--max-workers < 1rejected - Test coverage: unsafe URL rejection, explicit timeout propagation
- Validation: 563 tests passed in isolated PR worktree
- Decision: Security approval/unblock — CodeQL checks green
- GitHub limitation: Formal approval rejected due to own-PR token restrictions; unblock comment posted instead
- Outcome: Technical security gate cleared; awaits admin merge due to policy blocker