GitPDM is a FreeCAD workbench that connects to GitHub for backing up CAD files. This document describes the security architecture, implemented safeguards, and how to report security issues.
GitPDM uses OAuth Device Flow (RFC 8628) to authenticate users with GitHub:
- No passwords stored: Users authenticate directly with GitHub; GitPDM never sees passwords
- Minimal scopes: Requests only
read:user(profile) andrepo(repository access) - Scope validation: Validates granted scopes match requested scopes to prevent privilege downgrade
- Secure token storage: Tokens stored in OS credential storage (Windows Credential Manager, macOS Keychain, Linux Secret Service)
- Token expiry detection: Automatically detects expired tokens and refreshes using refresh_token
- Hardened polling: 15-minute absolute timeout, exponential backoff with jitter, correlation IDs for audit
To prevent abuse and respect GitHub's secondary rate limits:
- Global rate limit: 100 requests/minute across all users
- Per-user rate limit: 30 requests/minute per authenticated user
- Circuit breaker: Automatically trips after 5 consecutive failures; 30s cooldown
- Request coalescing: Deduplicates redundant API calls
- Automatic backoff: Exponential backoff with jitter on 5xx errors
- Secondary rate limit detection: Respects
Retry-Afterheaders from GitHub abuse detection
All user-controlled inputs are validated before use:
- Repository names: Alphanumeric + dots/hyphens/underscores only; max 100 chars
- Owner names: Alphanumeric + hyphens/underscores; max 39 chars (GitHub limit)
- Branch names: Valid Git ref names; no path traversal sequences
- Commit messages: Control characters stripped; max 50KB
- File paths: Path traversal protection (no
..); validated against repo root - GitHub URLs: HTTPS only; github.com domain validated
-
Read-only by default: Most operations use read-only API calls
-
Write operations gated: Commit/push only when user explicitly initiates
-
No admin scopes: Never requests repo admin or org-level permissions
-
Short-lived tokens: Tokens automatically refreshed; prefer shortest TTL
-
Required
reposcope: GitPDM requests therepoOAuth scope, which grants broad access to all repositories. This is required because:- Git push operations via HTTPS require
reposcope (GitHub's requirement) - Creating repositories via API requires
reposcope - The alternative
public_reposcope only works with public repositories
Mitigation: GitPDM never modifies repositories without explicit user action (clicking "Commit & Push", "New Repository", etc.). All write operations are user-initiated and clearly labeled in the UI.
- Git push operations via HTTPS require
- HTTPS only: All GitHub communication uses TLS 1.2+
- Certificate validation: Full certificate chain validation (no insecure flags)
- No credential logging: Authorization headers never logged
- Timeout enforcement: All network calls have strict timeouts (10-180s)
Risk: Attacker obtains user's OAuth token
Impact: Unauthorized repo access until token expires/revoked
Mitigations:
- Tokens stored in OS credential storage (encrypted at rest)
- Tokens never logged or written to FreeCAD settings
- Token expiry detection with automatic refresh
- Users can revoke via GitHub → Settings → Applications
Risk: Malicious commit messages/file names execute shell commands
Impact: Arbitrary code execution with user privileges
Mitigations:
- All Git commands use
subprocesswith list arguments (no shell expansion) - Commit messages sanitized (control chars removed)
- File paths validated against repo root
- No user input passed to shell directly
Risk: Malicious file paths access files outside repo
Impact: Leak/modify files outside intended scope
Mitigations:
- All file paths validated with
Path.resolve()andrelative_to()checks - Parent directory references (
..) rejected - Absolute paths resolved and validated against repo root
Risk: Attacker triggers thousands of API requests
Impact: GitHub throttles/blocks the app; service denial for other users
Mitigations:
- Global + per-user rate limiting with token buckets
- Circuit breaker prevents retry storms
- Exponential backoff with jitter
- Request coalescing reduces redundant calls
- 15-minute hard timeout on OAuth device flow
Risk: User grants fewer permissions than requested
Impact: App fails unpredictably or operates with insufficient permissions
Mitigations:
- Scope validation after token grant
- Clear error message if required scopes missing
- Re-authentication required if scopes insufficient
Risk: Attacker intercepts/modifies GitHub communication
Impact: Token theft, injected content, denial of service
Mitigations:
- HTTPS with full certificate validation
- Pinned domain (github.com only)
- No fallback to insecure protocols
- Network timeouts prevent hanging connections
Risk: Malicious code in Python dependencies
Impact: Arbitrary code execution, data exfiltration
Mitigations:
- Minimal dependencies (stdlib-only where possible)
- Dependabot/Renovate for automatic updates
- Code review for dependency changes
- PyPI package verification
-
Revoke tokens you don't recognize
GitHub → Settings → Applications → Authorized OAuth Apps -
Don't share your FreeCAD user directory
Contains cached credentials (encrypted but sensitive) -
Keep FreeCAD updated
Security patches distributed via FreeCAD Addon Manager -
Verify repo ownership
Before pushing, confirm you're writing to your own repo -
Use branch protection
Enable GitHub branch protection rules for important branches -
Review commit history
Periodically check for unexpected commits
- Authenticated requests: 5,000 req/hour per user (GitHub's limit)
- GitPDM enforces stricter limits to stay well below this
- Global: 100 requests/minute
- Per-user: 30 requests/minute
- Circuit breaker: 5 failures → 30s cooldown
- Request is rejected immediately (no API call made)
- Error message shows wait time
- UI suggests retrying after cooldown
- Background operations automatically queued
Check rate limit status in GitPDM diagnostics (Help → GitPDM Diagnostics):
- Global tokens remaining
- Per-user tokens remaining
- Circuit breaker state
If you observe GitPDM being used for malicious purposes:
- Email: Create security issue on GitHub
- Include: Description, timestamps, affected repos/users
- Response time: 48 hours for acknowledgment
- Repo spam: Automated creation of many repositories
- Comment spam: Automated comments via Git commits
- Rate limit testing: Intentional exhaustion of quotas
- Per-user rate limits isolate noisy users
- Circuit breakers prevent retry storms
- Scope limitations prevent org-wide actions
- Input validation blocks injection attempts
Please DO NOT open public issues for security vulnerabilities
Report security vulnerabilities via:
- GitHub Security Advisory: https://github.com/nerd-sniped/GitPDM/security/advisories/new
- Email: (if provided in repository)
Include:
- Description of vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
- 24 hours: Acknowledgment
- 7 days: Initial assessment and severity classification
- 30 days: Fix developed and tested
- Release: Coordinated disclosure with security advisory
In scope:
- OAuth token leakage
- Command injection
- Path traversal
- API abuse mechanisms
- Credential storage weaknesses
Out of scope:
- GitHub.com vulnerabilities (report to GitHub)
- FreeCAD core vulnerabilities (report to FreeCAD)
- Denial of service via resource exhaustion (rate limits prevent this)
- Security fixes released as new workbench version
- Announced via GitHub Security Advisories
- Users notified via FreeCAD Addon Manager
- Critical patches may auto-update (with user consent)
- Patch releases (x.y.Z): Security fixes, no breaking changes
- Minor releases (x.Y.0): Security + features, backward compatible
- Major releases (X.0.0): May include breaking changes
Check CHANGELOG.md for security-related updates marked with 🔒
GitPDM does NOT collect or transmit:
- Usage analytics
- Telemetry
- Crash reports
- Personal information
The only network requests are to GitHub's API for repo operations.
GitPDM stores locally (never uploaded to our servers):
- OAuth tokens (in OS credential storage, encrypted)
- Repository paths (in FreeCAD settings)
- Last commit timestamps (in FreeCAD settings)
Users can:
- Access: View stored credentials via OS credential manager
- Delete: Remove credentials by signing out
- Portability: Export repo history via Git
- Right to be forgotten: Delete all local GitPDM data by uninstalling
GitHub's data handling described in their privacy policy: https://docs.github.com/en/site-policy/privacy-policies/github-privacy-statement
- ✅ Rate limiter with circuit breaker
- ✅ Scope validation
- ✅ Token expiry and refresh
- ✅ OAuth hardening (timeouts, jitter, correlation IDs)
- ✅ Input sanitization
- 🔲 Webhook signature verification (if webhook support added)
- 🔲 Per-repo operation quotas
- 🔲 Audit log export for enterprise users
- 🔲 Support for GitHub Enterprise Server
- 🔲 Hardware token (FIDO2) support for OAuth
- Fine-grained personal access tokens (when GitHub stabilizes API)
- Signed commits (GPG/SSH key integration)
- Encrypted repository contents (client-side encryption)
- Security issues: https://github.com/nerd-sniped/GitPDM/security/advisories/new
- General support: https://github.com/nerd-sniped/GitPDM/issues
- Documentation: https://github.com/nerd-sniped/GitPDM/docs
Last updated: 2026-01-01
Security policy version: 1.0