Security
Security work is treated as a product feature. This page lists concrete controls currently present in the app and the boundaries users should understand.
Current controls
- Files are parsed client-side before entering the workspace.
- Aggregate result links keep the source file and respondent-level rows in the creator's browser. Counts, labels, and user-selected context are encoded in a URL fragment that the recipient's browser decodes locally.
- Browsers omit URL fragments from HTTP requests and HTTP referrer headers, so the fragment is not received or stored by Crosstabs through the share-link workflow.
- Exports sanitize CSV text cells that could otherwise be interpreted as spreadsheet formulas.
- PDF and XLSX report exports include audit metadata so settings travel with the analysis output.
- Saved projects remain in versioned browser IndexedDB when available, with localStorage as a compatibility fallback. Saved analysis templates remain in localStorage.
- Portable .ctproj imports verify SHA-256 project and manifest checksums, schema versions, and inventory before creating a new local copy; an imported id never overwrites an existing project id.
- Analytics uses a second boundary around sensitive URLs: pageview queries and fragments are removed before sending, a strict-origin referrer policy prevents paths and queries from being forwarded as referrer data, all analytics is excluded from /s snapshot routes, and activation events are limited to coarse enum properties.
- Continuous integration runs zero-warning lint, unit-test coverage, the production build, browser tests, and Python package tests. These checks are not yet enforced as a Vercel deployment approval gate.
- Server routes include /api/chat for opt-in AI summaries and stateless /api/v1 statistical endpoints for submitted contingency tables.
- Robots configuration disallows crawling /api/ routes.
Known boundaries
- Crosstabs is not claiming SOC 2, HIPAA, GDPR certification, or enterprise data-processing terms.
- Saved projects stay in browser site storage; they are convenient local copies, not encrypted vault storage or synchronized backups.
- Portable project files are checksummed but not encrypted or digitally signed. Checksums detect changes; they do not authenticate the sender.
- An aggregate result link is a bearer disclosure: anyone with the complete link can read its contents. Encoding a fragment is not encryption and does not authenticate the recipient.
- Aggregate result links have no server-side storage, expiration, or revocation. Clearing local data or changing the original analysis does not invalidate a link that someone already copied.
- The server AI path depends on the configured AI provider and should be disabled or replaced for regulated data.
- Dependency advisories change over time and require a current review before release; this page does not claim a permanent zero-vulnerability state.
- Large or sensitive datasets should be handled according to the user's organization policy.
Current dependency review
As of , the raw npm audit reports two linked high-severity infinite-loop advisories in image-size, an indirect dependency declared by PptxGenJS. Upstream lists no patched release. Crosstabs does not suppress this result: a machine-checked exception expires after August 26, 2026 and fails on any advisory, version, dependency-path, browser mapping, or input-boundary drift.
- The distributed PptxGenJS helper that would inspect generic image files is unused, and its browser package map disables image-size.
- Report branding accepts only bounded PNG or JPEG data URLs whose declared MIME and magic bytes agree; disguised ICNS, HEIF, and JPEG XL payloads have regression tests.
- Editable PPTX/DOCX generation and manual-edit-preserving refresh remain release-tested. The exception must be removed or explicitly re-reviewed when upstream publishes a viable fix.
Review the upstream ICNS advisory and JXL/HEIF advisory.
Enterprise control contract
- OIDC and SAML interfaces are declared, but no identity provider is configured. Provisioning is manual.
- Local-project residency is the browser profile; local retention lasts until the user deletes the project or clears site data.
- The optional cloud data plane is not configured, so no cloud residency region, retention term, deletion SLA, or SSO deployment is claimed.
- Project roles, row-free client views, append-only project audit events, human-approved AI changes, and evidence-linked exports are implemented controls.
- 3 independent evidence gates remain pending: statistical review, monitoring history/alert proof, and PyPI alignment.
The evaluated contract is available as machine-readable JSON.
See the evidence-linked AI analysis governance contract for the shipped citation checks, typed proposal boundary, human approval, conflict detection, audit evidence, and guarded undo behavior.
Operational checklist
CI and preview builds validate the deployable trust foundation and report missing external evidence. A production foundation build fails closed on malformed claims or an unverified GitHub/main source identity; the separate Phase-1 certification fails closed while required external evidence is missing or stale. These code-level checks do not replace Vercel deployment checks, role controls, or post-deploy verification.