The 5 Pillars of a Secure SDLC, Mapped to DaloyJS
Aikido's 'Secure SDLC Explained' lists the five pillars every engineering team needs — Visibility, Early Feedback, Developer Adoption, Consistency, Actionability. Here's the honest per-pillar mapping of what a DaloyJS app and its create-daloy scaffold already give you on day one, what you still configure, and the few items no framework can own.
A reader sent me Aikido's "Secure SDLC Explained: The 5 Pillars of a Secure Software Development Lifecycle" with the same question they always ask: are we doing anything about this?
The piece is a fine high-level checklist for CTOs and engineering leaders. It groups everything a Secure SDLC needs into five pillars — Visibility, Early Feedback, Developer Adoption, Consistency, and Actionability— and argues, correctly, that "framework alone cannot guarantee security": culture, tools, and consistent processes have to line up. Fair. But a framework can absolutely make the right process the path of least resistance, and that's exactly what DaloyJS is built to do.
Below is the honest per-pillar mapping of what an app built on DaloyJS — and scaffolded with pnpm create daloy@latest --with-ci— already gives you on day one, what you still configure yourself, and the few items no framework can own. The TL;DR: if you ship the scaffold, you get four-and-a-half of the five pillars wired into a brand-new repo before the first commit. The half you still drive is the cultural piece — but the tools don't fight you on it.
Pillar 1 — Visibility
- DaloyJS ships
- CycloneDX SBOM generated and signed on every release. OSV-Scanner against the lockfile in CI. A daily scheduled vuln-scan.yml that runs the package manager's audit against the committed lockfile — so newly-disclosed CVEs are surfaced even when no PR or push has run CI (SOC 2 CC7.1 continuous-vulnerability-management evidence). Per-request structured logs with correlated requestId go to your SIEM. RFC 9457 problem+json error bodies carry the same requestId for one-click drill-down.
- You still own
- Pick the SIEM (Datadog, CloudWatch, Loki, whatever) and wire the structured log stream to it. Decide which alerts page humans and which don't. The framework gives you the structured event surface; the dashboard is yours.
The "can you immediately tell whether a new CVE affects you?" question is the whole point of the SBOM. Daloy's verify:sbomgate fails the build if the SBOM is missing or stale — there is no "we'll generate one for the audit" mode. Every release carries one. Every scaffolded project gets the same workflow.
On the runtime side, every 4xx / 5xx response is RFC 9457 problem+json and carries the same requestId that shows up in the structured log line:
Full detail: /docs/security/supply-chain and /docs/tracing.
Pillar 2 — Early Feedback
- DaloyJS ships
- 14+ verify:* CI gates run on every PR and block the merge button on failure. CodeQL + Opengrep run two SAST engines (different bug classes). OSV-Scanner runs against the lockfile. gitleaks scans the diff on PR. The TypeScript compiler + Zod / Valibot / ArkType schemas catch entire vulnerability classes (mass assignment, missing input validation, wrong-type body) at edit time, in the IDE, before the PR is even opened.
- You still own
- Read the PR comments. Don't merge a red build. Don't paste 'allow: ['*']' into fetchGuard() because a test fails — the AGENTS.md asks you not to, but the framework can't physically stop you from disabling a check you wrote.
And the workflows that run them:
The reason there are two SAST engines (CodeQL + Opengrep) is the same point Aikido themselves make in their Ultimate SAST Guide: different engines catch different bug classes. Running both is the recommended layered posture, and the scaffolder gives you both with neither sitting in your supply chain as a third-party action — Opengrep's binary is downloaded from a pinned release and verified by its sigstore cosign signature before it runs.
The DAST half (Pillar 1 + 2 both touch this) is in dast.yml: a weekly OWASP ZAP baseline against the booted app, with HIGH-risk findings blocking and MEDIUM / LOW / INFO surfaced for triage. See Aikido's SAST vs DAST for why you need both.
Pillar 3 — Developer Adoption
- DaloyJS ships
- The safest configuration is the default constructor. There is no 'production hardening checklist' to remember on launch day — secureHeaders(), problem+json, body limits, request timeouts, prototype-pollution-safe JSON, CRLF refusal, path-traversal rejection, prod-mode redaction, and __Host-/Secure/HttpOnly/SameSite=Lax cookies are all on by default. Schema validation is a route-level requirement, not an afterthought. The scaffolder ships AGENTS.md + a SKILL.md so coding agents (Copilot, Claude, Cursor, GPT) read the rules before generating code.
- You still own
- Use the scaffolder. Don't manually delete the verify:* gates from ci.yml because a postinstall script 'needs' to run. Treat the secure default as the boring one — because it is.
The "agent reads the rules before it writes code" piece is the file layout the scaffolder drops into a brand-new project:
Aikido's point is that adoption fails when tooling switches context. Daloy's answer is to put the rules in the file the agent already loads into its context window — the AGENTS.md scaffold pattern — and to make the secure default the shortest line of code you can type.
Pillar 4 — Consistency
- DaloyJS ships
- The same verify:* gate set ships in every create-daloy template. The same secure-by-default constructor runs on every supported runtime — Node, Bun, Deno, Cloudflare Workers, Vercel Edge. verify:runtime-parity-audits and verify:parity-audits make sure no adapter quietly drops a security guard. verify:governance-audits keeps the security docs in sync with the code. The whole posture travels with the framework; a new service started this week gets the same gates as a service started last quarter.
- You still own
- Run the scaffolder for every new service. Don't fork the templates and then forget to merge upstream security fixes — the Dependabot config that ships in the scaffold updates @daloyjs/core for you, and a new version usually re-syncs the templates.
The reason this works is the audit framing. Daloy's verify:parity-audits, verify:runtime-parity-audits, and verify:routing-hardening-audits are not documentation — they are scripts in scripts/ that fail the build if a defense exists in one path but not another. The framework cannot ship a release where the JWT algorithm allowlist is enforced on Node but not on Workers, because the parity gate would catch it.
Consistency in the user's app is the same story extended outward: the scaffolded project carries the same gates, so a ten-service organization that scaffolds each one with pnpm create daloy@latest ends up with ten repos that enforce the same standards. ISO 27001 and SOC 2 evidence becomes a directory listing, not an interview.
Pillar 5 — Actionability
- DaloyJS ships
- problem+json on every 4xx / 5xx — the type URL is a documented page on this site, the requestId correlates to the SIEM log line, the message tells the caller what to fix. For published CVEs in the framework, every advisory is a GitHub Security Advisory with a CVE through GitHub's CNA — and SECURITY.md publishes a CVSS-keyed patch SLA (Critical 48h, High 7d, Medium 30d, Low 90d, measured from triage) so downstream NIS2 / EU CRA procurement clauses have something concrete to point at.
- You still own
- Read the advisories you're subscribed to. Apply the patch within your own deploy window. The framework's SLA covers the upstream release; the consumer's pnpm install is the consumer's deploy event.
Aikido's point is that "thousands of findings without context" means developers either ignore the alerts or fix things at random. Daloy's answer at the framework level is to be parsimonious about what it reports. The router does not log a warning for every path-traversal attempt — it returns 400 and moves on. The body-limit guard does not page anyone — it returns 413. The findings that do bubble up to a human come from the verify gates (which are binary: red build or green) and the DAST / SAST workflows (which are scored). Every one comes with a documented fix.
For framework-level vulnerabilities, the compliance docs spell out the per-severity patch SLA, the three timestamps every advisory carries (Discovered, Patch available, Fix deployed), and the npm --provenancesigstore attestation that binds the published version to the source commit. That's the evidence shape a NIS2-aligned procurement audit asks for, and it's built in.
The whole thing in one shell command
One command. Day-one coverage for four-and-a-half of the five pillars. The half you still drive is the "does the team actually use the tools" piece, and the AGENTS.md the scaffolder drops keeps even the coding agent honest.
What we honestly do not do
- We do not run the ASPM dashboard. Aikido (and Snyk, and Wiz, and Semgrep, and a dozen others) sell that piece, and they do it well. Daloy gives you the structured signal — SBOMs, SARIF, problem+json with requestId, OpenAPI 3.1 — that an ASPM tool ingests. Pick one and point it at the repo.
- We do not enforce the cultural side of a Secure SDLC: code review discipline, threat modeling, post-incident reviews, security champions in every team. Those are organizational practices, not framework primitives. What we do is make the framework boring enough that a thoughtful reviewer can focus on business logic instead of catching the same five bugs every PR.
- We do not chase 100% line coverage on every defensive branch. The repo runs
pnpm coveragewith a 90% line / 90% function / 90% branch floor, and the README is clear that writing throwaway tests for unreachablecatchblocks is not worth blocking a release on. Security gates that cannot be unit-tested (signal handlers, OS-level shutdown races) are documented instead. - We do not stop you from disabling a guard in your own app. The verify gates run in yourCI; if you remove the workflow file, they don't run. The framework's job is to ship the safe defaults and the agent-readable rules — the merge-button discipline is on the team.
The honest answer to the original question
Are we doing anything about the Secure SDLC five pillars? Yes — the framework, the scaffolder, and the templates were designed against this exact shape of checklist. Aikido's five-pillar framing maps one-for-one onto primitives that already ship today: SBOM + vuln-scan for Visibility, the verify:* family + DAST + dual SAST for Early Feedback, the secure-by-default constructor + AGENTS.md for Developer Adoption, the parity-audit gates + uniform templates for Consistency, and problem+json + GHSA + the CVSS-keyed SLA in SECURITY.md for Actionability.
What the framework cannot do is the culture — but the framework also stops being the bottleneck. The team can spend its security attention on threat modeling and review, not on remembering to set SameSite=Lax or chasing the next chalk-style postinstall worm.
Related reading on this blog: Secure by Default, Supply-chain hardening for TypeScript libraries, Vibe Coding Security, Cloud Security Architecture, Mapped, OWASP Top 10 for Agentic Applications, Mapped, Scaffolding a production-ready DaloyJS app in 60 seconds. Relevant docs: /docs/security, supply chain, compliance, runtime protections, secure defaults.