harden browser routes with csrf checks and lock internal/dev endpoints
This commit is contained in:
@@ -76,7 +76,7 @@ function createApp(options = {}) {
|
||||
betterAuthBasePath: "/api/auth",
|
||||
xOAuthClientId: "x-client-id",
|
||||
xOAuthClientSecret: "x-client-secret",
|
||||
internalApiToken: "",
|
||||
internalApiToken: "internal-token",
|
||||
convexDeploymentUrl: "",
|
||||
convexAuthToken: "",
|
||||
convexStateQuery: "state:getLatestSnapshot",
|
||||
@@ -381,6 +381,7 @@ test("/api/x/mentions returns upstream mentions when configured", async () => {
|
||||
const response = await call(app, {
|
||||
method: "GET",
|
||||
path: "/api/x/mentions",
|
||||
headers: { "x-internal-token": "internal-token" },
|
||||
query: { sinceId: "100" },
|
||||
});
|
||||
|
||||
@@ -390,6 +391,61 @@ test("/api/x/mentions returns upstream mentions when configured", async () => {
|
||||
assert.equal(body.mentions[0].id, "m1");
|
||||
});
|
||||
|
||||
test("/api/x/mentions requires internal token", async () => {
|
||||
const app = createApp({
|
||||
xAdapter: {
|
||||
isConfigured() {
|
||||
return true;
|
||||
},
|
||||
async listMentions() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const response = await call(app, {
|
||||
method: "GET",
|
||||
path: "/api/x/mentions",
|
||||
query: { sinceId: "1" },
|
||||
});
|
||||
|
||||
assert.equal(response.status, 401);
|
||||
});
|
||||
|
||||
test("cross-site browser posts are blocked", async () => {
|
||||
const app = createApp();
|
||||
const response = await call(app, {
|
||||
method: "POST",
|
||||
path: "/app/actions/topup",
|
||||
headers: {
|
||||
cookie: "xartaudio_user=alice",
|
||||
origin: "https://evil.example",
|
||||
"sec-fetch-site": "cross-site",
|
||||
},
|
||||
body: "amount=5",
|
||||
});
|
||||
|
||||
assert.equal(response.status, 403);
|
||||
assert.match(response.body, /csrf_blocked|invalid_origin/);
|
||||
});
|
||||
|
||||
test("dev dashboard routes can be disabled", async () => {
|
||||
const app = createApp({
|
||||
config: {
|
||||
enableDevRoutes: false,
|
||||
},
|
||||
});
|
||||
|
||||
const response = await call(app, {
|
||||
method: "POST",
|
||||
path: "/app/actions/topup",
|
||||
headers: { cookie: "xartaudio_user=alice" },
|
||||
body: "amount=5",
|
||||
});
|
||||
|
||||
assert.equal(response.status, 404);
|
||||
});
|
||||
|
||||
test("simulate mention schedules background audio generation when service is configured", async () => {
|
||||
const queued = [];
|
||||
const app = createApp({
|
||||
@@ -573,7 +629,11 @@ test("internal retention endpoint prunes stale content and assets", async () =>
|
||||
});
|
||||
|
||||
test("internal endpoints are disabled when no token configured", async () => {
|
||||
const app = createApp();
|
||||
const app = createApp({
|
||||
config: {
|
||||
internalApiToken: "",
|
||||
},
|
||||
});
|
||||
const response = await call(app, {
|
||||
method: "POST",
|
||||
path: "/internal/retention/run",
|
||||
|
||||
Reference in New Issue
Block a user