Search docs

Jump between documentation pages.

Runtime protections that travel with your app

These protections live inside @daloyjs/core and run at request time in your app process. They apply regardless of where you host the repo or which CI you use: private GitHub, GitLab, Bitbucket, Azure DevOps, Gitea, self-managed Jenkins, or on-prem runners. They are also unaffected by whether you keep or delete the optional GitHub Actions bundle from create-daloy.

Think of DaloyJS supply-chain and security posture as three independent layers. This page documents the first one.

The three layers, side by side

LayerWhere it runsTravels to GitLab / Bitbucket / Azure / on-prem?
Runtime guardrails (this page)Inside your app, every request. Lives in @daloyjs/core.Yes. Always on. No CI host required.
Install-time hardening.npmrc in pnpm scaffolds, plus pnpm verify:lockfile.Yes when you use pnpm. The hardened .npmrc ships in the project itself.
CI / CD hardening.github/workflows/*.yml from create-daloy --with-ci.GitHub only (public or private repo / org). On other CIs you have to translate the rules yourself.

Backend footguns the framework handles by default

Every row below describes behavior that is on by default in a fresh DaloyJS app. You do not need to install a plugin, deploy on a specific CI, or open a particular file to get these.

FootgunWhat DaloyJS does
Unsafe CORS defaultsCross-origin state-changing requests are refused unless cors() explicitly allows the origin. No reflective Access-Control-Allow-Origin: * with credentials.
Missing CSRF on stateful routesBooting session() with mutating routes but without csrf() is refused at startup, not silently allowed.
Weak session secretsShort / low-entropy session secrets are refused at boot. Production requires a real secret.
Missing secure response headerssecureHeaders() is auto-applied: HSTS, frame deny, no-sniff, strict referrer policy, baseline CSP.
Prototype pollution via JSON bodiessafeJsonParse strips __proto__, constructor, and prototype keys before the value reaches your handler.
Path traversalRouter rejects .. segments and // before route resolution.
Body-size abuseStreamed reads with a hard cap (default 1 MiB); oversize requests return 413 before they hit your handler.
Hung handlers / slow-lorisrequestTimeoutMs aborts handlers (default 30s); the Node adapter sets socket-level timeouts.
Bad reverse-proxy assumptionsX-Forwarded-* headers are not trusted by default. First request returns 500 with a clear error until you opt in via behindProxy.
Auth response caching401, 403, and 429 automatically set Cache-Control: no-store so proxies and CDNs cannot reuse them.
Duplicate dangerous headersDuplicate Host and Content-Length are rejected at parse time to block request-smuggling shapes.
Weak JWT secretscreateJwtSigner() refuses HS* secrets shorter than the algorithm requires.
Missing JWT expirySigning without an exp claim is refused, not defaulted to a forever token.
Unsafe compression cases (BREACH)compression() skips Set-Cookie, Authorization, session / CSRF cookie responses, and already-encoded content; downgrades strong ETags per RFC 9110.
Unsafe file-upload assumptionsmultipartObject + fileField enforce per-field size caps, MIME allowlists, and magic-byte checks.
Leaky production errorsProduction mode strips detail from 5xx problem+json automatically; stack traces never leak through the default error path.
Unsupported content typesRoutes with body schemas reject non-allowed content-types with 415.
Method confusionReal 405 with Allow header instead of a misleading 404.
Header / response splittingsanitizeHeaderName / sanitizeHeaderValue reject CRLF and NUL in header values.

What this page does not cover

The following protections only apply if you keep using the matching scaffolded bits:

  • Install-time hardening (blocked install scripts, 24h release-age cooldown, source-verified lockfile, zero-runtime-dep gate) applies when you use the pnpm scaffold and keep its .npmrc + pnpm verify:lockfile script.
  • CI / CD hardening (pinned actions, harden-runner, top-level permissions: {}, CODEOWNERS, Dependabot, CodeQL / Scorecard / zizmor) applies when you use the create-daloy --with-ciGitHub Actions bundle. On GitLab, Bitbucket, Azure DevOps, Jenkins, or on-prem runners you have to translate those rules into your CI's own configuration.
  • Branch protection, environment approvals, secret hygiene, runner isolation, and org policy are decisions of the host (GitHub / GitLab / Azure / Bitbucket / your own infra). DaloyJS cannot enforce them from inside your code.

What the generated GitHub Actions bundle actually does

If you scaffold with create-daloy --with-ci and keep the generated workflows, the YAML itself encodes these protections. They apply equally to public repos, private repos, and private organizations — being private is not a substitute for any of them:

  • Top-level permissions: {} with least-privilege per-job permissions.
  • Third-party Actions pinned to a commit SHA (not a moving tag).
  • actions/checkout with persist-credentials: false.
  • step-security/harden-runner with egress policy on every job.
  • Lifecycle scripts disabled during CI installs (--ignore-scripts for npm/yarn, ignore-scripts=true in the scaffolded .npmrc for pnpm).
  • No shared Actions cache by default.
  • Dependabot config for npm + Actions ecosystems.
  • CODEOWNERS for security-sensitive files.
  • CodeQL, OpenSSF Scorecard, zizmor, and vulnerability-scan workflows where included.
  • Manual-only deploy.yml starter instead of automatic publish or deploy on push.

This is generated GitHub CI hardening, not “default supply-chain protection everywhere”. If you delete the workflows, rewrite them, or use a different CI host, DaloyJS cannot give you these guarantees automatically.

The honest matrix

Use this table to figure out which protections you actually get for a given setup.

User setupWhat DaloyJS can protect
create-daloy --with-ci on GitHub (private or public repo / org)Runtime guardrails + pnpm install-time hardening (if pnpm) + full generated GitHub Actions starter protections.
create-daloy with pnpm, no CI bundleRuntime guardrails + hardened install defaults via .npmrc and pnpm verify:lockfile.
npm / yarn / bun users (no pnpm scaffold)Runtime guardrails. CI install commands still benefit if you keep the generated workflows on GitHub.
GitLab / Bitbucket / Azure DevOps / Jenkins / on-premRuntime guardrails and portable docs / patterns. No GitHub Actions protections.Translate the YAML rules into your CI's own configuration.
User deletes or rewrites the generated workflowsRuntime guardrails only. DaloyJS cannot guarantee CI supply-chain posture once the workflows are gone.
Branch protection, environment approvals, secret hygiene, runner isolation, egress policy, org settings, deploy-platform configOut of scope. These are decisions of your repo host and deploy platform; DaloyJS cannot enforce them from inside your code.

See Secure-by-default, Boot guards, and Supply-chain security for the full surface of each layer.