Skip to content

Commit 238b896

Browse files
security: harden mirror workflow and add security documentation (#1)
- Update actions/checkout to v4.2.2 (SHA-pinned) - Update webfactory/ssh-agent to v0.9.1 (SHA-pinned) - Add SSH known host verification for MITM protection - Add concurrency controls to prevent race conditions - Add job timeout limits (10 minutes) - Use dynamic github.repository_owner instead of hardcoded org - Change permissions from read-all to contents: read (more specific) - Add SECURITY.md with vulnerability reporting guidelines - Add CODEOWNERS for workflow review requirements - Add .gitignore for common exclusions - Add ROADMAP.md with project phases and security checklist Co-authored-by: Claude <noreply@anthropic.com>
1 parent 96c5ef6 commit 238b896

File tree

5 files changed

+284
-10
lines changed

5 files changed

+284
-10
lines changed

.github/CODEOWNERS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# CODEOWNERS - Defines code ownership for review requirements
2+
# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
3+
4+
# Default owners for everything in the repo
5+
* @hyperpolymath
6+
7+
# Workflow files require maintainer review (security-critical)
8+
/.github/workflows/ @hyperpolymath
9+
10+
# Security policy requires maintainer review
11+
/SECURITY.md @hyperpolymath

.github/workflows/mirror.yml

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,93 @@ on:
66
branches: [main, master]
77
workflow_dispatch:
88

9-
permissions: read-all
9+
# Prevent concurrent mirror operations to avoid race conditions
10+
concurrency:
11+
group: mirror-${{ github.ref }}
12+
cancel-in-progress: false
13+
14+
permissions:
15+
contents: read
16+
17+
env:
18+
# SSH known hosts for security - prevents MITM attacks
19+
# These are the official SSH host keys for each platform
20+
GITLAB_HOST_KEY: "gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf"
21+
CODEBERG_HOST_KEY: "codeberg.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIVIC02vnjFyL+I4RHfvIGNtOgJMe769VTF1VR4EB3ZB"
22+
BITBUCKET_HOST_KEY: "bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO"
1023

1124
jobs:
1225
mirror-gitlab:
1326
runs-on: ubuntu-latest
27+
timeout-minutes: 10
1428
if: vars.GITLAB_MIRROR_ENABLED == 'true'
1529
steps:
16-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
30+
- name: Add GitLab to known hosts
31+
run: |
32+
mkdir -p ~/.ssh
33+
echo "${{ env.GITLAB_HOST_KEY }}" >> ~/.ssh/known_hosts
34+
chmod 600 ~/.ssh/known_hosts
35+
36+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1737
with:
1838
fetch-depth: 0
19-
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
39+
40+
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
2041
with:
2142
ssh-private-key: ${{ secrets.GITLAB_SSH_KEY }}
43+
2244
- name: Mirror to GitLab
2345
run: |
24-
git remote add gitlab git@gitlab.com:hyperpolymath/${GITHUB_REPOSITORY#*/}.git || true
46+
git remote add gitlab "git@gitlab.com:${{ github.repository_owner }}/${GITHUB_REPOSITORY#*/}.git" || true
2547
git push gitlab --all --force
2648
git push gitlab --tags --force
2749
2850
mirror-codeberg:
2951
runs-on: ubuntu-latest
52+
timeout-minutes: 10
3053
if: vars.CODEBERG_MIRROR_ENABLED == 'true'
3154
steps:
32-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
55+
- name: Add Codeberg to known hosts
56+
run: |
57+
mkdir -p ~/.ssh
58+
echo "${{ env.CODEBERG_HOST_KEY }}" >> ~/.ssh/known_hosts
59+
chmod 600 ~/.ssh/known_hosts
60+
61+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3362
with:
3463
fetch-depth: 0
35-
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
64+
65+
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
3666
with:
3767
ssh-private-key: ${{ secrets.CODEBERG_SSH_KEY }}
68+
3869
- name: Mirror to Codeberg
3970
run: |
40-
git remote add codeberg git@codeberg.org:hyperpolymath/${GITHUB_REPOSITORY#*/}.git || true
71+
git remote add codeberg "git@codeberg.org:${{ github.repository_owner }}/${GITHUB_REPOSITORY#*/}.git" || true
4172
git push codeberg --all --force
4273
git push codeberg --tags --force
4374
4475
mirror-bitbucket:
4576
runs-on: ubuntu-latest
77+
timeout-minutes: 10
4678
if: vars.BITBUCKET_MIRROR_ENABLED == 'true'
4779
steps:
48-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
80+
- name: Add Bitbucket to known hosts
81+
run: |
82+
mkdir -p ~/.ssh
83+
echo "${{ env.BITBUCKET_HOST_KEY }}" >> ~/.ssh/known_hosts
84+
chmod 600 ~/.ssh/known_hosts
85+
86+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
4987
with:
5088
fetch-depth: 0
51-
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
89+
90+
- uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
5291
with:
5392
ssh-private-key: ${{ secrets.BITBUCKET_SSH_KEY }}
93+
5494
- name: Mirror to Bitbucket
5595
run: |
56-
git remote add bitbucket git@bitbucket.org:hyperpolymath/${GITHUB_REPOSITORY#*/}.git || true
96+
git remote add bitbucket "git@bitbucket.org:${{ github.repository_owner }}/${GITHUB_REPOSITORY#*/}.git" || true
5797
git push bitbucket --all --force
5898
git push bitbucket --tags --force

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# OS generated files
2+
.DS_Store
3+
.DS_Store?
4+
._*
5+
.Spotlight-V100
6+
.Trashes
7+
ehthumbs.db
8+
Thumbs.db
9+
10+
# IDE and editor files
11+
.idea/
12+
.vscode/
13+
*.swp
14+
*.swo
15+
*~
16+
17+
# Secrets and credentials (never commit these)
18+
*.pem
19+
*.key
20+
.env
21+
.env.*
22+
!.env.example
23+
credentials.json
24+
secrets.yaml
25+
26+
# Logs
27+
*.log
28+
logs/

ROADMAP.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# MAA Framework - Roadmap
2+
3+
## Current Status
4+
5+
The MAA Framework repository is configured as a **hub-and-spoke mirror system** that automatically synchronizes code across multiple Git hosting platforms:
6+
7+
- **GitHub** (hub/primary)
8+
- **GitLab** (mirror)
9+
- **Codeberg** (mirror)
10+
- **Bitbucket** (mirror)
11+
12+
---
13+
14+
## Phase 1: Infrastructure & Security (Completed)
15+
16+
- [x] Hub-and-spoke mirror workflow
17+
- [x] SHA-pinned GitHub Actions for supply chain security
18+
- [x] SSH host key verification (MITM protection)
19+
- [x] Concurrency controls for race condition prevention
20+
- [x] Job timeouts to prevent resource exhaustion
21+
- [x] SECURITY.md policy document
22+
- [x] CODEOWNERS for review requirements
23+
- [x] Dynamic repository owner (not hardcoded)
24+
25+
---
26+
27+
## Phase 2: Enhanced CI/CD Pipeline
28+
29+
### Workflow Improvements
30+
- [ ] Add status badges to README
31+
- [ ] Implement failure notifications (Slack/Discord/Email)
32+
- [ ] Add workflow status checks before mirroring
33+
- [ ] Create PR preview environments (if applicable)
34+
35+
### Testing & Quality
36+
- [ ] Add workflow linting (actionlint)
37+
- [ ] Implement YAML schema validation
38+
- [ ] Add Dependabot for action version updates
39+
- [ ] Set up CodeQL for security scanning
40+
41+
### Documentation
42+
- [ ] Add README.md with setup instructions
43+
- [ ] Document mirror configuration process
44+
- [ ] Create CONTRIBUTING.md guidelines
45+
- [ ] Add architecture diagrams
46+
47+
---
48+
49+
## Phase 3: Advanced Mirroring Features
50+
51+
### Selective Mirroring
52+
- [ ] Branch filtering (exclude feature branches from mirrors)
53+
- [ ] Tag filtering (only release tags)
54+
- [ ] Path-based exclusions for platform-specific files
55+
56+
### Mirror Health
57+
- [ ] Add mirror verification step (compare HEADs)
58+
- [ ] Implement automatic retry with exponential backoff
59+
- [ ] Create mirror drift detection alerts
60+
- [ ] Add periodic full-sync workflow (scheduled)
61+
62+
### Platform-Specific Features
63+
- [ ] GitLab CI/CD configuration mirroring
64+
- [ ] Codeberg-specific integrations
65+
- [ ] Bitbucket Pipelines compatibility
66+
67+
---
68+
69+
## Phase 4: Governance & Compliance
70+
71+
### Access Control
72+
- [ ] Branch protection rules
73+
- [ ] Required reviews for workflow changes
74+
- [ ] Signed commits enforcement
75+
- [ ] Deploy key rotation schedule
76+
77+
### Audit & Compliance
78+
- [ ] Mirror operation audit logs
79+
- [ ] Secret rotation reminders
80+
- [ ] Compliance documentation (GDPR, etc.)
81+
- [ ] License compliance checking
82+
83+
### Disaster Recovery
84+
- [ ] Backup verification procedures
85+
- [ ] Mirror promotion playbook (if GitHub unavailable)
86+
- [ ] Recovery time objectives (RTO) documentation
87+
88+
---
89+
90+
## Phase 5: Framework Development
91+
92+
*Pending project direction - the following are suggested based on "MAA Framework" naming:*
93+
94+
### Core Framework
95+
- [ ] Define framework purpose and scope
96+
- [ ] Establish coding standards
97+
- [ ] Create project structure
98+
- [ ] Set up dependency management
99+
100+
### Developer Experience
101+
- [ ] Local development setup
102+
- [ ] Testing framework
103+
- [ ] Code formatting/linting
104+
- [ ] Pre-commit hooks
105+
106+
---
107+
108+
## Security Checklist
109+
110+
| Item | Status | Notes |
111+
|------|--------|-------|
112+
| SHA-pinned actions | Done | v4.2.2 checkout, v0.9.1 ssh-agent |
113+
| SSH host verification | Done | ed25519 keys for all platforms |
114+
| Minimal permissions | Done | contents: read only |
115+
| Secret management | Done | GitHub encrypted secrets |
116+
| Concurrency control | Done | Prevents parallel runs |
117+
| Job timeouts | Done | 10 minutes per job |
118+
| CODEOWNERS | Done | Maintainer review required |
119+
| Security policy | Done | SECURITY.md |
120+
| Dependabot | Pending | Phase 2 |
121+
| CodeQL scanning | Pending | Phase 2 |
122+
| Signed commits | Pending | Phase 4 |
123+
124+
---
125+
126+
## Version History
127+
128+
| Date | Version | Changes |
129+
|------|---------|---------|
130+
| 2025-12-17 | 0.1.0 | Initial mirror workflow |
131+
| 2025-12-17 | 0.2.0 | Security hardening, SECURITY.md, CODEOWNERS |
132+
133+
---
134+
135+
## Contributing
136+
137+
See [CONTRIBUTING.md](CONTRIBUTING.md) (to be created) for guidelines on contributing to this project.
138+
139+
## License
140+
141+
AGPL-3.0-or-later

SECURITY.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
| Version | Supported |
6+
| ------- | ------------------ |
7+
| main | :white_check_mark: |
8+
9+
## Reporting a Vulnerability
10+
11+
If you discover a security vulnerability in this project, please report it responsibly:
12+
13+
1. **Do NOT** create a public GitHub issue for security vulnerabilities
14+
2. Send a private report to the repository maintainers via GitHub's private vulnerability reporting feature
15+
3. Include as much detail as possible:
16+
- Description of the vulnerability
17+
- Steps to reproduce
18+
- Potential impact
19+
- Suggested fix (if any)
20+
21+
## Security Measures
22+
23+
This repository implements the following security practices:
24+
25+
### GitHub Actions Security
26+
27+
- **SHA-pinned actions**: All GitHub Actions are pinned to specific commit SHAs to prevent supply chain attacks
28+
- **Minimal permissions**: Workflows use the least privilege principle with `contents: read` permission
29+
- **SSH host key verification**: Known hosts are verified to prevent MITM attacks during mirroring
30+
- **Concurrency controls**: Prevents race conditions during parallel workflow runs
31+
- **Timeout limits**: All jobs have timeout limits to prevent resource exhaustion
32+
33+
### Secret Management
34+
35+
- SSH keys for mirror targets are stored as GitHub encrypted secrets
36+
- Mirror operations are conditionally enabled via repository variables
37+
- No secrets are logged or exposed in workflow outputs
38+
39+
### Force Push Warning
40+
41+
This repository uses `--force` push for mirroring operations. This is intentional for maintaining exact mirrors but means:
42+
- History on mirror targets will be overwritten
43+
- Tags on mirror targets will be force-updated
44+
- Only trusted maintainers should have push access to the main branch
45+
46+
## Dependency Updates
47+
48+
This project monitors for security updates in:
49+
- GitHub Actions (checkout, ssh-agent)
50+
- SSH host keys for mirror targets
51+
52+
## Contact
53+
54+
For security concerns, use GitHub's private security advisory feature or contact the repository maintainers directly.

0 commit comments

Comments
 (0)