Coregit
Guides

Security

How Coregit protects your code — encryption, isolation, authentication, and more.

Architecture overview

Coregit runs on a serverless architecture designed to minimize attack surface:

  • Cloudflare Workers — no persistent servers, no SSH access, no long-running processes. Each request runs in an isolated V8 isolate with strict memory limits
  • Cloudflare R2 — object storage for git data, protected by Cloudflare's network and access controls
  • Neon PostgreSQL — managed serverless database with encryption at rest and automated backups

There are no servers to patch, no SSH keys to rotate, and no persistent processes that can be compromised.

Encryption at rest

All data is encrypted at rest across three layers:

LayerEncryptionManaged by
Git objects (R2)AES-256Cloudflare
Database (Neon)AES-256 storage volume encryptionNeon / AWS
External tokens (GitHub/GitLab OAuth)AES-256-GCM with random IVCoregit application layer
Webhook secretsAES-256-GCM with random IVCoregit application layer

External sync tokens and webhook secrets are encrypted at the application level before being written to the database. Even with full database access, these values cannot be read without the encryption key.

Encryption in transit

All connections to Coregit use TLS 1.3, enforced by Cloudflare. HTTP connections are never accepted.

Security headers on every response:

Strict-Transport-Security: max-age=31536000; includeSubDomains

The Git Smart HTTP protocol (git clone, git push) also uses HTTPS exclusively. Custom domains receive automatic SSL certificates via Cloudflare.

Tenant isolation

Customer data is isolated at multiple levels:

Database level — every query includes an org_id filter. There is no API path that can return data from a different organization:

SELECT * FROM repo WHERE org_id = $orgId AND slug = $slug

Object storage level — git objects are stored under organization-scoped paths:

{orgId}/{repoSlug}/objects/{sha[0:2]}/{sha[2:40]}

One organization cannot construct a path that accesses another organization's objects.

API key level — API keys are bound to a single organization at creation time. A key from org A cannot authenticate against org B's resources.

Authentication

Coregit supports two credential types:

CredentialPrefixScopeLifetime
Master API keycgk_live_*Full organization accessUntil rotated
Scoped tokencgt_*Specific repos, read or write1 hour – 30 days

How keys are stored:

  1. The key is shown to the user exactly once at creation
  2. A SHA-256 hash is computed and stored in the database
  3. On each request, the provided key is hashed and compared using a timing-safe comparison to prevent timing attacks
  4. Plaintext keys are never stored or logged

Scoped tokens support granular permissions:

{
  "repos:my-app": ["read", "write"],
  "repos:docs": ["read"]
}

Tokens can be revoked instantly. Expired tokens are rejected automatically.

Rate limiting

Coregit enforces rate limits at two levels to prevent abuse:

LevelBurst limitSustained limit
Per API key600 req/min15,000 req/hr
Per organization2,000 req/min50,000 req/hr

Rate limits use a sliding window algorithm. When limits are exceeded, responses include standard headers:

X-RateLimit-Limit: 600
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1712345678
Retry-After: 12

These limits are intentionally generous — Coregit is designed for AI agent workloads with high request volume.

Input validation

Every input is validated before processing:

InputValidation
SHA hashesMust be exactly 40 lowercase hex characters
Ref/branch namesFollow git-check-ref-format rules — no .., @{, control chars
File pathsNo .. traversal, no null bytes, no empty segments, max 4096 chars
Request bodyMax 5 MB for REST API, 32 MB for git push
Commit changesMax 1,000 files per commit, max 10 MB per file
Commit messagesMax 50 KB
Workspace commandsMax 10,000 characters
Workspace cwdMust be absolute path, max 1024 chars, no null bytes
Workspace envMax 50 variables, cannot override PATH/HOME/LD_PRELOAD
Webhook URLsHTTPS only, no private IPs, no localhost, no cloud metadata endpoints

Content-addressed storage

Git's content-addressed object model provides inherent tamper detection. Every object — blob, tree, commit — is identified by the SHA-1 hash of its contents.

If a single bit of a file changes, its blob hash changes. That changes the tree hash. That changes the commit hash. The entire chain of trust from commits to files is cryptographically linked.

This means:

  • Objects cannot be silently modified after creation
  • Any corruption is immediately detectable
  • Storage deduplication is automatic and safe

Webhook security

Webhook deliveries are signed with HMAC-SHA256:

X-CoreGit-Signature: sha256=5d7c9a...
X-CoreGit-Event: push
X-CoreGit-Webhook-Id: wh_abc123

To verify a webhook delivery:

const crypto = require('crypto');

function verifyWebhook(body, secret, signature) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Webhook URLs must use HTTPS and cannot point to private IP ranges, localhost, or cloud metadata endpoints (SSRF protection).

Audit logging

Every write operation is recorded in an immutable audit log:

  • Repository create, update, delete
  • Branch create, delete, merge
  • Scoped token create, revoke
  • Webhook create, update, delete
  • API commit creation

Each entry includes: actor ID, actor type, action, affected resource, metadata, IP address, request ID, and timestamp.

Query the audit log via API:

curl -H "x-api-key: $API_KEY" \
  "https://api.coregit.dev/v1/audit-log?limit=50&action=repo.delete"

Supports filtering by action, resource type, and date range.

Security headers

Every API response includes these headers:

HeaderValuePurpose
Strict-Transport-Securitymax-age=31536000; includeSubDomainsForce HTTPS
X-Content-Type-OptionsnosniffPrevent MIME sniffing
X-Frame-OptionsDENYPrevent clickjacking
Content-Security-Policydefault-src 'none'; frame-ancestors 'none'Strict CSP
Referrer-Policystrict-origin-when-cross-originLimit referrer leakage
X-Request-Ida1b2c3d4Unique ID for every request

What Coregit does not store

  • No plaintext API keys — only SHA-256 hashes
  • No plaintext external tokens — AES-256-GCM encrypted
  • No plaintext webhook secrets — AES-256-GCM encrypted
  • No server-side sessions — stateless worker architecture
  • No user passwords — authentication is handled by the dashboard app via Better Auth, not the API
  • No request bodies in logs — only method, path, and error messages

Responsible disclosure

If you discover a security vulnerability, please report it to alemzhan@strayl.dev. We will acknowledge receipt within 48 hours and work with you to address the issue.

On this page