security: remove dead free signup route (abuse vector) + add test
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 9m39s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 9m39s
The /v1/signup/free endpoint was still mounted despite free tier being removed in v0.3.0. Anyone could generate unlimited free API keys. - Removed signup route registration from index.ts - Deleted src/routes/signup.ts (dead code) - Added signup-removed.test.ts verifying 404 on signup endpoints - Cleaned up leaked test key from production DB 334 tests passing.
This commit is contained in:
parent
740c70f905
commit
f3a363fb17
3 changed files with 44 additions and 31 deletions
|
|
@ -16,7 +16,7 @@ import { loadKeys, getAllKeys } from "./services/keys.js";
|
|||
import { initDatabase, pool } from "./services/db.js";
|
||||
import { billingRouter } from "./routes/billing.js";
|
||||
import { statusRouter } from "./routes/status.js";
|
||||
import { signupRouter } from "./routes/signup.js";
|
||||
|
||||
import { usageRouter } from "./routes/usage.js";
|
||||
import { openapiSpec } from "./docs/openapi.js";
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ app.use("/health", healthRouter);
|
|||
app.use("/v1/billing", billingRouter);
|
||||
app.use("/status", statusRouter);
|
||||
app.use("/v1/playground", playgroundRouter);
|
||||
app.use("/v1/signup", signupRouter);
|
||||
|
||||
|
||||
// Authenticated routes
|
||||
app.use("/v1/usage", usageRouter);
|
||||
|
|
|
|||
42
src/routes/__tests__/signup-removed.test.ts
Normal file
42
src/routes/__tests__/signup-removed.test.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { describe, it, expect, vi, beforeAll } from "vitest";
|
||||
import request from "supertest";
|
||||
|
||||
// Mock dependencies before importing app
|
||||
vi.mock("../../services/db.js", () => ({
|
||||
initDatabase: vi.fn(),
|
||||
pool: { query: vi.fn(), end: vi.fn() },
|
||||
}));
|
||||
vi.mock("../../services/browser.js", () => ({
|
||||
initBrowser: vi.fn(),
|
||||
closeBrowser: vi.fn(),
|
||||
}));
|
||||
vi.mock("../../services/keys.js", () => ({
|
||||
loadKeys: vi.fn(),
|
||||
getAllKeys: vi.fn().mockReturnValue([]),
|
||||
findKey: vi.fn(),
|
||||
createKey: vi.fn(),
|
||||
}));
|
||||
vi.mock("../../middleware/usage.js", () => ({
|
||||
loadUsageData: vi.fn(),
|
||||
usageMiddleware: vi.fn((_req: any, _res: any, next: any) => next()),
|
||||
}));
|
||||
|
||||
let app: any;
|
||||
beforeAll(async () => {
|
||||
const mod = await import("../../index.js");
|
||||
app = mod.app;
|
||||
});
|
||||
|
||||
describe("Free signup removal (v0.3.0)", () => {
|
||||
it("POST /v1/signup/free should return 404 — free tier removed", async () => {
|
||||
const res = await request(app)
|
||||
.post("/v1/signup/free")
|
||||
.send({ email: "test@example.com" });
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
|
||||
it("GET /v1/signup should return 404", async () => {
|
||||
const res = await request(app).get("/v1/signup");
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import { Router } from "express";
|
||||
import { createKey } from "../services/keys.js";
|
||||
import logger from "../services/logger.js";
|
||||
|
||||
export const signupRouter = Router();
|
||||
|
||||
// Simple signup: email → instant API key (no verification for now)
|
||||
signupRouter.post("/free", async (req, res) => {
|
||||
const { email } = req.body;
|
||||
|
||||
if (!email || typeof email !== "string" || !email.includes("@")) {
|
||||
res.status(400).json({ error: "Valid email required" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const key = await createKey(email.toLowerCase().trim(), "free");
|
||||
logger.info({ email: email.slice(0, 3) + "***" }, "Free signup");
|
||||
res.json({
|
||||
apiKey: key.key,
|
||||
tier: "free",
|
||||
limit: 100,
|
||||
message: "Your API key is ready! 100 free screenshots/month.",
|
||||
});
|
||||
} catch (err: any) {
|
||||
logger.error({ err }, "Signup failed");
|
||||
res.status(500).json({ error: "Signup failed" });
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue