Harden deployment security

This commit is contained in:
Codex
2026-07-21 12:28:06 -05:00
parent 5c2ac5f7e1
commit 63c3a1b0f8
15 changed files with 286 additions and 45 deletions

View File

@@ -1,8 +1,23 @@
const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const os = require("os");
const path = require("path");
const request = require("supertest");
const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "dws-test-"));
process.env.DATABASE_PATH = path.join(testRoot, "site.sqlite");
process.env.UPLOAD_DIR = path.join(testRoot, "uploads");
process.env.BACKUP_DIR = path.join(testRoot, "backups");
process.env.SESSION_SECRET = "test-session-secret-with-more-than-thirty-two-characters";
process.env.SETUP_TOKEN = "test-setup-token-with-enough-length";
const { app } = require("../src/server");
function csrfFrom(html) {
return /name="_csrf" value="([^"]+)"/.exec(html)?.[1] || "";
}
test("public pages load", async () => {
for (const path of ["/", "/items", "/services", "/about-contact", "/healthz"]) {
const response = await request(app).get(path);
@@ -15,10 +30,79 @@ test("admin redirects to setup or login", async () => {
assert.equal([302, 303].includes(response.status), true);
});
test("owner setup requires the private setup token", async () => {
const agent = request.agent(app);
const locked = await agent.get("/admin/setup");
assert.equal(locked.status, 403);
const setupPage = await agent.get("/admin/setup?token=test-setup-token-with-enough-length");
assert.equal(setupPage.status, 200);
const token = csrfFrom(setupPage.text);
const takeover = await agent
.post("/admin/setup")
.type("form")
.send({
_csrf: token,
name: "Attacker",
email: "attacker@example.com",
password: "attacker-password"
});
assert.equal(takeover.status, 403);
const created = await agent
.post("/admin/setup")
.type("form")
.send({
_csrf: token,
setup_token: "test-setup-token-with-enough-length",
name: "Owner",
email: "owner@example.com",
password: "owner-password-123"
});
assert.equal(created.status, 302);
assert.equal(created.headers.location, "/admin/dashboard");
const dashboard = await agent.get("/admin/dashboard");
assert.equal(dashboard.status, 200);
const setupAfterClaim = await agent.get("/admin/setup?token=test-setup-token-with-enough-length");
assert.equal(setupAfterClaim.status, 302);
assert.equal(setupAfterClaim.headers.location, "/admin/login");
});
test("multipart admin uploads pass CSRF after form parsing", async () => {
const agent = request.agent(app);
const loginPage = await agent.get("/admin/login");
const loginToken = csrfFrom(loginPage.text);
const login = await agent
.post("/admin/login")
.type("form")
.send({
_csrf: loginToken,
email: "owner@example.com",
password: "owner-password-123"
});
assert.equal(login.status, 302);
const mediaPage = await agent.get("/admin/media");
const uploadToken = csrfFrom(mediaPage.text);
const sampleImage = path.join(__dirname, "..", "public", "uploads", "sample-hero.png");
const upload = await agent
.post("/admin/media")
.field("_csrf", uploadToken)
.field("title", "Test upload")
.field("alt", "Test upload")
.attach("images", sampleImage);
assert.equal(upload.status, 302);
assert.equal(upload.headers.location, "/admin/media");
});
test("contact form requires complete fields", async () => {
const agent = request.agent(app);
const page = await agent.get("/about-contact");
const token = /name="_csrf" value="([^"]+)"/.exec(page.text)?.[1];
const token = csrfFrom(page.text);
const response = await agent
.post("/contact")
.send(`_csrf=${encodeURIComponent(token || "")}&name=&email=bad&subject=&message=`);