Skip to content
Cardinal
cardinal.wiki
GitLab
Security

Who can see what, and how you'd know.

Access in Cardinal.js is decided the same way for a person, a script and an agent: page rules on groups, a classification cap, and a site scope. Everything that changes is written down.

Sign-in

OIDC, SAML, LDAP and fifteen more

Eighteen providers, including Okta, Keycloak, Microsoft, Google and GitLab. Passkeys (WebAuthn) for passwordless sign-in. TOTP second factors with recovery codes, enforced for every local account or required per user, and checked on provider logins too. Login attempts are rate-limited.

Access

Page rules, and a level on every page

Groups carry rules like read:pages or write:assets on paths, tags or classification levels, as allow or deny. Classification rules outrank path and tag rules, and a token’s classification limit holds even when its owner is a system admin. A page is never more open than its parent, and lowering a level takes its own permission. Site settings can be delegated per site without instance-wide admin.

Tokens and agents

Expiring, scopable, and always someone

Personal access tokens act as their owner, always expire, can be narrowed by scope, site and classification, and are re-checked on every call. The MCP server is the same process under the same page rules, so an agent sees what its token’s owner sees. Admin-issued keys can never create or edit a page, because there would be no author.

scope          read:pages
site           docs.example.com
classification public, internal
expires        30 days … 3 years (no “never”)
Audit

Who changed access, kept as long as you say

Sign-ins and failures, user and group changes, token issue and revoke, classification changes, MCP sessions and writes, and admin actions land in the audit log, kept for a window you set. Filter by actor, event and date; export as NDJSON. Page edits live in page history.

Deployment

TLS at the edge, air-gapped if you need

Cardinal.js never terminates TLS itself: put a proxy in front. Or run fully offline, with locales and icons sideloaded; semantic search embeds on a local model, so no content leaves the instance. Custom blocks are trusted code, so only admins with manage:sites can upload one, and an optional CSP narrows what it can load.

Reporting a vulnerability

Found something? Please tell us quietly first.

Email [email protected] or open a confidential issue on the GitLab project. We acknowledge within three working days and publish a review once a fix ships, the way the existing reviews in docs/audits/security-reviews/ do.

in scopeAuthentication and session handling, page-rule and classification enforcement, the MCP and REST surfaces, the migration tooling, custom block upload.
please avoidTesting against docs.cardinal.wiki with anything louder than a read. Run your own instance; it takes a few minutes.
supportedThe latest 0.x minor; Cardinal.js is pre-1.0 and fixes land on its next patch. The full policy is in SECURITY.md.