Docs/Security
Security

Security & Trust

Security model — how DocsCI keeps your code and data safe

DocsCI executes user-supplied code. This page documents how we isolate that execution, how access control is enforced at the database layer, and what limits apply to every run.

📦 Sandbox isolation

Sandbox architecture: Every code snippet runs inside an ephemeral sandbox that is torn down immediately after execution. We use two sandbox strategies:

JavaScript / TypeScript

vm2 / isolated-vm

  • Runs in a restricted V8 context via isolated-vm
  • No access to Node.js built-ins (fs, child_process, net)
  • Separate V8 isolate — no shared heap with the host
  • Memory limit: 64 MB per isolate
  • CPU timeout: per-snippet (default 20 s)

Python

Pyodide (WebAssembly)

  • Runs in a WebAssembly sandbox via Pyodide
  • No native system calls from Python
  • File system is a virtual in-memory FS (memfs)
  • No network access by default
  • Memory limit: 128 MB per instance

⚠️ Secret scanning before execution

Every snippet is scanned for credentials (AWS keys, API tokens, private keys, connection strings) using 40+ regex patterns before it enters the sandbox. Snippets containing secrets are flagged as findings and not executed.

🔐 Org roles

Three roles exist at the organization level. Roles are stored in docsci_org_members.role and enforced both in the API layer and at the database via RLS.

Permission👁 Viewer✏️ Editor👑 Owner
Trigger CI runs
View findings & run history
Manage projects
Invite members
Change member roles
Remove members
Delete organization
Change billing
Create owner invites

The last owner of an organization cannot be demoted or removed. Attempting to do so returns HTTP 409.

🛡️ Row-Level Security (RLS)

All tables use Postgres Row-Level Security. Even if the API layer is bypassed, data is inaccessible unless the authenticated user has a matching membership record.

docsci_orgs

SELECTUser is a member of the org
UPDATEUser is owner or editor
INSERTAny authenticated user (own org creation)

docsci_org_members

SELECTUser is in the same org
INSERTCaller is owner of the org
UPDATECaller is owner of the org
DELETECaller is owner, or removing themselves

docsci_projects

SELECTUser is a member of the project's org
UPDATE/INSERTUser is owner or editor in the org

docsci_runs

SELECTUser is a member of the run's org
INSERTUser is owner or editor (viewers blocked)

docsci_invite_tokens

SELECTUser is owner or editor in the org
INSERTUser is owner or editor in the org
DELETEUser is owner in the org

⏱️ Runtime caps

Every sandbox run enforces hard limits. These cannot be overridden by docsci.yml beyond the stated maximums.

CapDefaultNote
Snippet execution timeout20 sMax 60 s via docsci.yml
JS/TS memory per isolate64 MBHard limit — OOM kills the isolate
Python memory (Pyodide)128 MBWASM linear memory limit
Run total timeout5 minAll snippets in a run
Snippets per run500Additional snippets skipped with warning
Docs files per run1 000glob expansion cap
Doc file size1 MBFiles larger than 1 MB are skipped
OpenAPI spec size2 MBLarger specs rejected at API
Secret scan patterns40+Runs before execution, not configurable off
Network allowlist entries20Per org, owner-configurable

🌐 Network allowlist

By default, snippet sandboxes have no outbound network access. Private RFC-1918 ranges are always blocked (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). Outbound calls will silently fail or time out.

To allow specific domains (e.g. your staging API), configure an allowlist in docsci.yml:

security:
  network_isolated: false          # default
  allowlist:
    - api.example.com
    - "*.stripe.com"

Set network_isolated: true to enforce a total network block — useful for regulated environments.

The allowlist is enforced at the sandbox level, not the DNS level. Wildcard patterns (*.example.com) match one subdomain level only.

🔑 Secrets & Credentials

DocsCI does not store any customer secrets or API keys. Each run uses an ephemeral credential scoped to the specific Supabase project for the duration of the run.

What we do store:

  • GitHub/GitLab OAuth tokens (encrypted at rest, Supabase-managed)
  • Org membership records and roles
  • Run results, findings, and snippets (your CI output)
  • Your API keys, env vars, or production credentials
  • The contents of your sandbox network requests

📬 Responsible Disclosure

If you find a security vulnerability in DocsCI, please report it responsibly. We aim to acknowledge reports within 48 hours and release a fix within 14 days for critical issues.

How to report

  • 📧 Email: hello@snippetci.com with subject line [SECURITY]
  • 🔒 Use our PGP key (linked in email signature) for sensitive reports
  • 🚫 Please do not open public GitHub issues for security vulnerabilities

We do not currently offer a paid bug bounty program but will credit responsible reporters in our changelog and security advisory.

🏆

Enterprise security review

Need a security questionnaire, SOC 2 report, or pen test results? Contact us and we'll send our security package within one business day.

Request security package →