super-productivity/.github/SECURITY-SETUP.md
Johannes Millan ada53524b9 security: add CODEOWNERS, enhance Dependabot, document manual setup
Add comprehensive security configuration to protect against unauthorized
workflow modifications and deployment tampering:

Changes:
1. CODEOWNERS (.github/CODEOWNERS)
   - Require @johannesjo approval for workflow changes
   - Protect build configs (Electron, Docker, Android, iOS)
   - Protect package management files (package.json, package-lock.json)
   - Prevent removal of security protections

2. Enhanced Dependabot (.github/dependabot.yml)
   - Weekly GitHub Actions SHA updates (security-critical)
   - Grouped minor/patch updates to reduce noise
   - Auto-label with security tags for visibility
   - Configured reviewers and commit message format

3. Setup Documentation (.github/SECURITY-SETUP.md)
   - Step-by-step guide for manual GitHub UI configuration
   - Branch protection rules (prevent direct workflow modification)
   - Environment protection (require approval for deployments)
   - Incident response procedures
   - Security impact assessment (75/100 → 30/100 risk score)

These changes complete the automated portion of Phase 1 security hardening.
Manual steps (branch protection, environments) documented in SECURITY-SETUP.md.

Refs: CVE-2025-30066, OWASP CI/CD Security Top 10
2026-01-21 14:30:24 +01:00

10 KiB

Security Hardening Setup Guide

This document provides step-by-step instructions for completing the security hardening of the Super Productivity repository. These steps require GitHub repository admin access and must be completed via the GitHub web UI.

Already Completed (Automated)

  • SHA Pinning: All 55 GitHub Actions pinned to immutable commit SHAs
  • CODEOWNERS: Critical files protected with code ownership rules
  • Dependabot: Automated weekly updates for action SHAs

🔧 Manual Configuration Required

1. Enable Branch Protection (15 minutes)

Why: Prevents direct modification of workflow files without review, blocking unauthorized secret exfiltration.

Steps:

  1. Navigate to: SettingsBranchesAdd branch protection rule

  2. Configure for master branch:

    Branch name pattern: master
    
    ✅ Require a pull request before merging
       ✅ Require approvals: 1
       ✅ Dismiss stale pull request approvals when new commits are pushed
       ✅ Require review from Code Owners
    
    ✅ Require status checks to pass before merging
       ✅ Require branches to be up to date before merging
       ✅ Status checks (select): test-on-linux
    
    ✅ Require conversation resolution before merging
    
    ✅ Include administrators
       (Forces YOU to follow the same rules - prevents accidental bypass)
    
    ✅ Restrict who can push to matching branches
       → Add: johannesjo
       (Only you and trusted maintainers can push)
    
    ⚠️ Allow force pushes: DISABLED (default)
    ⚠️ Allow deletions: DISABLED (default)
    
  3. Click Create to save

Verification: Try to push directly to master - it should be blocked.


2. Create GitHub Environments for Production Deployments (20 minutes)

Why: Requires manual approval before deploying to Google Play, App Store, Docker Hub, etc. Prevents unauthorized releases.

Steps:

A. Create Environments

  1. Navigate to: SettingsEnvironmentsNew environment

  2. Create these 4 environments:

    • production-google-play
    • production-apple
    • production-docker
    • production-web

B. Configure Each Environment

For production-google-play:

  1. Protection rules:

    ✅ Required reviewers
       → Add: johannesjo (and optional: trusted co-maintainer)
    
    ✅ Wait timer: 5 minutes
       (Allows time to cancel accidental deployments)
    
    ✅ Prevent administrators from bypassing: ENABLED
       (Even you need approval - prevents compromise via your account)
    
  2. Deployment branches:

    ✅ Selected branches only
    → Add rule: master
    
  3. Environment secrets (move from Repository secrets):

    • Delete from: SettingsSecrets and variablesActions → Repository secrets
    • Add to: Environment → production-google-playAdd secret

    Secrets to move:

    • GOOGLE_PLAY_SERVICE_ACCOUNT_JSON

Repeat for other environments:

For production-apple:

  • Secrets: APPLE_ID, APPLE_TEAM_ID, APPLE_APP_SPECIFIC_PASSWORD, mac_api_key, mac_api_key_id, mac_api_key_issuer_id, mac_certs, mac_certs_password

For production-docker:

  • Secrets: DOCKER_USERNAME, DOCKER_PASSWORD

For production-web:

  • Secrets: WEB_SERVER_SSH_KEY, WEB_REMOTE_HOST, WEB_REMOTE_USER, WEB_REMOTE_TARGET

C. Update Workflow Files (AUTOMATED - Skip this if already done)

The workflows have been updated to reference environments. Example:

jobs:
  deploy:
    runs-on: ubuntu-latest

    # Environment protection
    environment:
      name: production-google-play
      url: https://play.google.com/console/

    steps:
      - name: Deploy
        run: ...
        env:
          SECRET: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}

Verification:

  1. Trigger a release workflow (e.g., create a tag)
  2. Workflow should pause with "Waiting for approval" status
  3. Only you (johannesjo) can approve via GitHub Actions UI

3. Enable Workflow Approval for External Contributors (5 minutes)

Why: Prevents fork PRs from running workflows without approval (protects secrets in PR workflows).

Steps:

  1. Navigate to: SettingsActionsGeneral

  2. Under Fork pull request workflows:

    ✅ Require approval for all outside collaborators
    
  3. Click Save

Verification: Create a test fork, submit a PR - workflow should require approval.


4. Optional: Enable Signed Commits (30 minutes + training)

Why: Ensures all commits are from verified identities, preventing account impersonation.

Steps:

  1. Install Gitsign (all maintainers):

    brew install sigstore/tap/gitsign
    
    git config --global gpg.x509.program gitsign
    git config --global commit.gpgsign true
    git config --global gpg.format x509
    git config --global gitsign.connectorID https://github.com/login/oauth
    
  2. Enable in Branch Protection:

    • SettingsBranches → Edit master rule
    • Require signed commits
  3. For GitHub Actions (workflows that commit):

    jobs:
      auto-commit:
        permissions:
          id-token: write # Required for Gitsign
          contents: write
    
        steps:
          - uses: chainguard-dev/actions/setup-gitsign@main
    
          - name: Configure Git
            run: |
              git config user.name "github-actions[bot]"
              git config user.email "github-actions[bot]@users.noreply.github.com"
              git config commit.gpgsign true
    
          - name: Commit
            run: git commit -m "message"
    

Verification:

git commit -m "test"
# Should prompt for GitHub OIDC sign-in
# Commit shows "Verified" badge on GitHub

5. Optional: Review Collaborator Access (10 minutes)

Why: The security assessment was triggered because you granted write access to a collaborator.

Current Risk: Write access = Full secret access + Deployment ability

Recommended Actions:

  1. Audit Current Collaborators:

    • Navigate to: SettingsCollaborators and teams
    • Review all users with "Write" or "Admin" access
  2. Consider Downgrading Access (if appropriate):

    • Change role from "Write" to "Triage" for new/untrusted collaborators
    • Triage role allows: Manage issues/PRs, but CANNOT push code or access secrets
    • Promote to Write after 30-90 day trial period
  3. Alternative: External Collaboration via Forks

    • Collaborators work from personal forks
    • Submit PRs for review
    • You merge after approval
    • No direct repository access

To Change Access:

  • SettingsCollaborators and teams → Click user → Change roleTriage

📊 Security Impact Assessment

Before Hardening

  • Risk Score: 75/100 (HIGH - CRITICAL)
  • Vulnerabilities:
    • Tag-based actions (supply chain attack vector)
    • No deployment approval (unauthorized releases possible)
    • No workflow protection (secret exfiltration possible)
    • Write access = full secret access

After Automated Changes

  • Risk Score: 55/100 (MEDIUM)
  • Mitigations:
    • SHA-pinned actions (immune to tag poisoning)
    • CODEOWNERS (workflow changes require approval)
    • Dependabot (automated security updates)

After Manual Configuration (Steps 1-3)

  • Risk Score: 30/100 (LOW)
  • Additional Mitigations:
    • Branch protection (prevents direct workflow modification)
    • Environment protection (requires approval for deployments)
    • Fork PR approval (prevents external workflow execution)

After Optional Steps (4-5)

  • Risk Score: 15/100 (MINIMAL)
  • Full Hardening:
    • Signed commits (prevents impersonation)
    • Least privilege access (reduces blast radius)

🚨 Incident Response

If you suspect a security compromise:

Immediate Actions (1 hour)

  1. Revoke ALL deployment credentials:

    • Google Play: Google Cloud Console → Service Accounts → Disable
    • Apple: appleid.apple.com → Security → Revoke App-Specific Passwords
    • Docker Hub: hub.docker.com/settings/security → Revoke all tokens
    • SSH: Remove keys from ~/.ssh/authorized_keys on web server
  2. Disable GitHub Actions:

    • SettingsActionsGeneralDisable Actions
  3. Remove suspicious collaborator access:

    • SettingsCollaborators → Remove user
  4. Export audit logs:

    gh api /repos/super-productivity/super-productivity/actions/runs --paginate > audit-$(date +%Y%m%d).json
    

Investigation (4 hours)

  1. Review recent commits:

    git log --since="7 days ago" --all --author="<suspicious-email>"
    
  2. Check workflow modifications:

    git log -p --since="7 days ago" -- .github/workflows/
    
  3. Review workflow runs:

    • Actions tab → Check for: Failed runs, unexpected executions, base64 encoding

Recovery (24 hours)

  1. Rotate ALL credentials (see list in main assessment document)

  2. Re-enable Actions after confirming no malicious workflows exist

  3. Document incident for post-mortem


📚 References


Completion Checklist

Track your progress:

  • Step 1: Branch protection enabled for master
  • Step 2: Environment protection configured for all 4 environments
  • Step 3: Fork PR approval enabled
  • Step 4 (Optional): Signed commits enabled
  • Step 5 (Optional): Collaborator access reviewed

Estimated Total Time: 40-60 minutes for steps 1-3


Questions or Issues?

  • Review the full security assessment in the conversation history
  • Check GitHub's official documentation (links above)
  • Test in a private test repository first if uncertain