The ProjectAchilles team takes security vulnerabilities seriously. We appreciate your efforts to responsibly disclose your findings.
Please DO NOT report security vulnerabilities through public GitHub issues.
Instead, please report them via one of the following methods:
-
GitHub Security Advisories (Preferred)
- Navigate to the Security tab
- Click "Report a vulnerability"
- Provide detailed information about the vulnerability
-
Email
- Send an email to the repository maintainers
- Use a descriptive subject line:
[SECURITY] Brief description
Please include the following information in your report:
- Type of vulnerability (e.g., XSS, SQL injection, authentication bypass)
- Affected component (frontend, backend, agent, specific module)
- Steps to reproduce the vulnerability
- Proof of concept (if applicable)
- Potential impact of the vulnerability
- Suggested fix (if you have one)
| Action | Timeline |
|---|---|
| Initial acknowledgment | Within 48 hours |
| Initial assessment | Within 7 days |
| Status update | Every 14 days |
| Fix development | Dependent on severity |
| Public disclosure | After fix is released |
| Severity | Description | Example |
|---|---|---|
| Critical | Immediate threat, full system compromise | Remote code execution, authentication bypass |
| High | Significant impact, data exposure | SQL injection, sensitive data leak |
| Medium | Limited impact, requires user interaction | Stored XSS, CSRF |
| Low | Minimal impact | Information disclosure, minor issues |
| Version | Supported |
|---|---|
| 1.x.x (latest) | Yes |
ProjectAchilles uses a multi-layer authentication model:
- Clerk (Web UI) — All web routes require Clerk JWT authentication
- Social login (Google, Microsoft, GitHub)
- Short-lived tokens with automatic refresh
- Session isolation per authenticated user
- Agent API Keys — Agents authenticate with unique keys issued during enrollment
- Separate from Clerk — agents do not require web UI credentials
- Keys are bound to a specific agent ID and organization
- Keys rotatable with zero downtime — new key delivered via heartbeat, old key valid for 5-minute grace period
- Stored encrypted at rest (AES-256-GCM with machine-bound key derivation)
- Enrollment Tokens — One-time or limited-use tokens for agent registration
- Configurable TTL (time-to-live) and maximum usage count
- Revocable through the admin interface
- Integration Credentials — Third-party service credentials stored encrypted
- Microsoft Defender:
DEFENDER_TENANT_ID,DEFENDER_CLIENT_ID,DEFENDER_CLIENT_SECRET - Slack webhook URL for alerting
- SMTP credentials for email alerting
- All encrypted at rest with AES-256-GCM in
~/.projectachilles/integrations.json
- Microsoft Defender:
The agent-server communication channel has been hardened through a dedicated internal security audit. See Agent Security Findings for the full audit report covering 9 findings.
Transport Security:
- TLS Enforcement —
skip_tls_verifyblocked for non-localhost servers at config validation; explicit--allow-insecureCLI flag required for self-signed certificate scenarios - Replay Protection — Agent sends
X-Request-Timestamp(RFC3339 UTC) on every request; server rejects timestamps with >5 minute clock skew; heartbeat payloads include a second timestamp for defense-in-depth
Authentication & Credential Management:
- API Key Rotation — Zero-downtime key rotation via heartbeat delivery; 5-minute grace period where both old and new keys authenticate; agent auto-saves rotated key to encrypted config
- Timing Oracle Prevention — Constant-time bcrypt comparison on both enrollment and agent auth middleware; dummy hash comparison when no candidate matches to prevent distinguishing "no tokens exist" from "wrong token"
- Encrypted Credential Storage — Agent API key encrypted at rest with AES-256-GCM; encryption key derived via HMAC-SHA256 from machine ID (
/etc/machine-id,IOPlatformUUID, or WindowsMachineGuid); config is non-portable across machines
Binary Integrity:
- SHA256 Verification — Agents verify test binary integrity via checksum before execution
- Ed25519 Update Signatures — Server signs agent binary SHA256 hashes with an Ed25519 keypair; agents verify signatures before applying self-updates; public key distributed during enrollment
- Isolated Execution — Test binaries run in temporary directories (0700) that are cleaned up after execution
Rate Limiting:
- Enrollment: 5 requests / 15 minutes per IP
- Agent device endpoints: 100 requests / 15 minutes per agent
- Binary download: 10 requests / 15 minutes per IP
- Key rotation: 3 requests / 15 minutes per IP
Platform Hardening:
- File Permissions — Agent binary
0700(owner-only), config0600, work directories0700, log files0640 - Windows ACLs — Binary and config restricted via
icaclstoNT AUTHORITY\SYSTEMandBUILTIN\Administratorsonly; inherited permissions stripped - Permission Enforcement — Hardened at three points: install time, self-update time, and runtime file creation
- Heartbeat Jitter — ±5s randomization on poll intervals to prevent thundering herd
- Graceful Shutdown — Agents handle SIGINT/SIGTERM for clean termination
- Encrypted Storage — Certificate PFX passwords are encrypted at rest using a machine-derived or explicit encryption key (
ENCRYPTION_SECRET) - Certificate Isolation — Each certificate stored in its own timestamped subdirectory under
~/.projectachilles/certs/ - Certificate Limits — Maximum 5 certificates (uploaded + generated combined)
- Authenticode Signing — Windows binaries signed using osslsigncode for tamper detection
- Settings Encryption — Elasticsearch credentials and other sensitive settings encrypted at rest
- No Credential Logging — API responses mask sensitive fields (Cloud IDs, API keys)
- Session Security — HttpOnly cookies, secure flag in production, SameSite protection
- Never expose the backend API directly to the internet without proper authentication
- Use HTTPS in production environments
- Configure appropriate CORS origins for your deployment
- Set strong session secrets via environment variables
- Set
ENCRYPTION_SECRETexplicitly in Docker/PaaS deployments (do not rely on machine-derived keys) - Implement rate limiting at the infrastructure level
- Use HTTPS for
AGENT_SERVER_URLin production — the agent enforces TLS for non-localhost servers - Use ngrok or a reverse proxy with TLS termination for agent-to-server communication
- Revoke enrollment tokens after use to prevent unauthorized agent registration
- Rotate API keys regularly via the admin UI — agents receive new keys automatically with zero downtime
- Monitor agent heartbeats for unexpected offline/online patterns
- Agent config files are encrypted with machine-bound keys — copying a config to another machine will not work
- Do not expose Elasticsearch ports publicly when using the local ES profile
- Set
NODE_ENV=productionfor production deployments - Generate unique
SESSION_SECRETandENCRYPTION_SECRETvalues per deployment - Use Docker secrets or environment variable injection — avoid hardcoding credentials
# Production environment variables (example)
SESSION_SECRET=<strong-random-secret>
ENCRYPTION_SECRET=<strong-random-secret>
CORS_ORIGIN=https://your-domain.com
NODE_ENV=production
AGENT_SERVER_URL=https://your-agent-endpoint.com- Deploy behind a reverse proxy (nginx, Cloudflare, etc.)
- Implement Web Application Firewall (WAF) rules
- Monitor for suspicious activity
- Keep dependencies updated
| Feature | Implementation |
|---|---|
| Helmet.js | Security headers |
| Rate Limiting | Tiered per-endpoint limits: enrollment (5/15min), device (100/15min), download (10/15min), rotation (3/15min), auth (20/15min) |
| Session Security | HttpOnly cookies, secure in production |
| Input Validation | Zod schema validation |
| CORS | Configurable origin restrictions |
| TLS Enforcement | skip_tls_verify blocked for remote servers; --allow-insecure override with warning |
| Replay Protection | Timestamp validation (5-min window) on all agent requests + payload-level defense-in-depth |
| Binary Verification | SHA256 checksum + Ed25519 signature verification on agent-side |
| Code Signing | Windows Authenticode via osslsigncode, macOS ad-hoc via rcodesign |
| API Key Rotation | Zero-downtime dual-key rotation with heartbeat delivery |
| Credential Encryption | AES-256-GCM for agent config (machine-bound), AES for backend settings |
| Enrollment Tokens | TTL + max-use limits, revocable, timing-oracle-resistant |
| File Permission Hardening | Binary 0700, config 0600, Windows ACLs via icacls |
| Dependabot | Automated dependency vulnerability monitoring |
| Semgrep SAST | 11 community rulesets + 5 custom rules in CI; Claude security review on PRs |
| Integration Credential Encryption | Defender, Slack, SMTP credentials AES-256-GCM encrypted at rest |
We follow a coordinated disclosure process:
- Reporter submits vulnerability
- We acknowledge and assess the report
- We develop and test a fix
- We release the fix
- We publicly disclose the vulnerability (with reporter credit, if desired)
We believe in recognizing security researchers who help improve our project. With your permission, we will:
- Credit you in the security advisory
- Add you to our security acknowledgments
- Provide a letter of appreciation (upon request)
Security updates are released as patch versions. We recommend:
- Watching this repository for releases
- Subscribing to GitHub security advisories
- Regularly updating to the latest version
- Keeping the Go agent updated (agents support self-updating)
For security-related inquiries that don't fit the above categories, please open a GitHub issue with the security label (for non-sensitive matters only).
Thank you for helping keep ProjectAchilles and its users safe.