HaiderMalik12/nestjs-fundamentals

15 errors, 63 warningsmain

2 critical findings to fix first.

15 errors and 63 warnings in the paths between 58 routes and 15 tables.

ROUTE FINDINGS56 of 58 · 12/12 rules
ROUTES
58
TABLES
15
FILES READ
1616/1616
RULES RUN
12/12

78 findings

2 critical13 high33 medium30 low

  • Criticalhigh confidencePOST /playlists can reach users without authenticating.

    Anyone, signed in or not, can read users (email, password) — personal or secret fields.

    Data reached
    users (read) · sensitive: email, password
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-06-relations/lesson-02-and-lesson-03/src/playlists/playlists.controller.ts.
    Path
    POST /playlists → users

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/playlists' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/playlists")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /playlists rejects a signed-out caller", async () => {
      const res = await request(app).post("/playlists");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: public sensitive data is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Criticalhigh confidencePOST /applications can reach Customer without authenticating.

    Anyone, signed in or not, can write to Customer (email, addressId) — personal or secret fields.

    Data reached
    Customer (write) · sensitive: email, addressId
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-08/src/applications/applications.controller.ts.
    Path
    POST /applications → Customer

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/applications' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/applications")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /applications rejects a signed-out caller", async () => {
      const res = await request(app).post("/applications");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /playlists can reach playlists without authenticating.

    An unauthenticated caller can write to playlists. Writes are how data gets corrupted or planted.

    Data reached
    playlists (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-06-relations/lesson-02-and-lesson-03/src/playlists/playlists.controller.ts.
    Path
    POST /playlists → playlists

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/playlists' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/playlists")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /playlists rejects a signed-out caller", async () => {
      const res = await request(app).post("/playlists");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePATCH /songs/:id can reach Song without authenticating.

    An unauthenticated caller can write to Song. Writes are how data gets corrupted or planted.

    Data reached
    Song (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-04-and-05/src/songs/songs.controller.ts.
    Path
    PATCH /songs/:id → Song

    Prove it

    # No cookie, no Authorization header.
    curl -i -X PATCH 'https://YOUR_API/songs/1' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Patch("/songs/:id")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("PATCH /songs/:id rejects a signed-out caller", async () => {
      const res = await request(app).patch("/songs/1");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /artists can reach Artist without authenticating.

    An unauthenticated caller can write to Artist. Writes are how data gets corrupted or planted.

    Data reached
    Artist (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-06/src/artists/artists.controller.ts.
    Path
    POST /artists → Artist

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/artists' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/artists")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /artists rejects a signed-out caller", async () => {
      const res = await request(app).post("/artists");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /users can reach User without authenticating.

    An unauthenticated caller can write to User. Writes are how data gets corrupted or planted.

    Data reached
    User (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-07/src/users/users.controller.ts.
    Path
    POST /users → User

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/users' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/users")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /users rejects a signed-out caller", async () => {
      const res = await request(app).post("/users");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /users can reach User without authenticating.

    Anyone can read User.

    Data reached
    User (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-07/src/users/users.controller.ts.
    Path
    GET /users → User

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/users'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/users")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /users rejects a signed-out caller", async () => {
      const res = await request(app).get("/users");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /posts can reach Post without authenticating.

    An unauthenticated caller can write to Post. Writes are how data gets corrupted or planted.

    Data reached
    Post (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-08/src/posts/posts.controller.ts.
    Path
    POST /posts → Post

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/posts' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/posts")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /posts rejects a signed-out caller", async () => {
      const res = await request(app).post("/posts");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /posts can reach Post without authenticating.

    Anyone can read Post.

    Data reached
    Post (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-08/src/posts/posts.controller.ts.
    Path
    GET /posts → Post

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/posts'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/posts")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /posts rejects a signed-out caller", async () => {
      const res = await request(app).get("/posts");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /sequential can reach Song without authenticating.

    Anyone can read Song.

    Data reached
    Song (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-09/src/app.controller.ts.
    Path
    GET /sequential → Song

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/sequential'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/sequential")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /sequential rejects a signed-out caller", async () => {
      const res = await request(app).get("/sequential");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /sequential can reach Artist without authenticating.

    Anyone can read Artist.

    Data reached
    Artist (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-09/src/app.controller.ts.
    Path
    GET /sequential → Artist

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/sequential'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/sequential")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /sequential rejects a signed-out caller", async () => {
      const res = await request(app).get("/sequential");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /sequential can reach Post without authenticating.

    Anyone can read Post.

    Data reached
    Post (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-09/src/app.controller.ts.
    Path
    GET /sequential → Post

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/sequential'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/sequential")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /sequential rejects a signed-out caller", async () => {
      const res = await request(app).get("/sequential");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidenceGET /sequential can reach Application without authenticating.

    Anyone can read Application.

    Data reached
    Application (read)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-09/src/app.controller.ts.
    Path
    GET /sequential → Application

    Prove it

    # No cookie, no Authorization header.
    curl -i -X GET 'https://YOUR_API/sequential'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Get("/sequential")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("GET /sequential rejects a signed-out caller", async () => {
      const res = await request(app).get("/sequential");
      expect(res.status).toBe(401);
    });

    Intended? If this data is meant to be public (a catalogue, published posts), that is a legitimate design. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /accounts can reach Account without authenticating.

    An unauthenticated caller can write to Account. Writes are how data gets corrupted or planted.

    Data reached
    Account (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-11-interactive-transactions/src/accounts/accounts.controller.ts.
    Path
    POST /accounts → Account

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/accounts' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/accounts")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /accounts rejects a signed-out caller", async () => {
      const res = await request(app).post("/accounts");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Highhigh confidencePOST /accounts/transfer can reach Account without authenticating.

    An unauthenticated caller can write to Account. Writes are how data gets corrupted or planted.

    Data reached
    Account (write)
    Missing
    Authentication before the handler reaches data, and a query scoped to the caller.
    Confidence
    No middleware, guard or wrapper is applied to this route anywhere in module-20-prisma-integration/lesson-11-interactive-transactions/src/accounts/accounts.controller.ts.
    Path
    POST /accounts/transfer → Account

    Prove it

    # No cookie, no Authorization header.
    curl -i -X POST 'https://YOUR_API/accounts/transfer' \
      -H 'content-type: application/json' -d '{}'
    # Expect 401. A 2xx means anyone on the internet can do this.

    Fix

    @UseGuards(AuthGuard("jwt"))
    @Post("/accounts/transfer")
    handler(@Req() req) {
      // ...scope every query to req.user.id
    }

    Regression test

    import request from "supertest";
    
    test("POST /accounts/transfer rejects a signed-out caller", async () => {
      const res = await request(app).post("/accounts/transfer");
      expect(res.status).toBe(401);
    });

    Intended? This cannot be declared intentional: a public write is not a design choice the check will bless. Accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    auth-before-data

  • Mediumhigh confidenceGET /auth/enable-2fa makes calls the check could not follow, so its data access is unknown, not absent: this.userService.findById() — no such method on UsersService; this.userService.updateSecretKey() — no such method on UsersService.

    No rule could run on GET /auth/enable-2fa: it calls into code the check could not follow, so whether it reaches data — and whether that is authenticated — is unknown. A route nobody can trace is where a rescue gets hurt.

    Missing
    Evidence of what it touches. Could not follow: this.userService.findById() — no such method on UsersService; this.userService.updateSecretKey() — no such method on UsersService.
    Confidence
    The check is certain it could not follow these calls; it is not claiming the route is wrong.

    Intended? Trace the chain by hand or log at the data access and hit the route. If it touches no data, record it in the baseline; if it does, that is the path to review first.

    unresolved-data-reach

  • Mediumhigh confidencePOST /auth/validate-2fa makes calls the check could not follow, so its data access is unknown, not absent: this.userService.findById() — no such method on UsersService.

    No rule could run on POST /auth/validate-2fa: it calls into code the check could not follow, so whether it reaches data — and whether that is authenticated — is unknown. A route nobody can trace is where a rescue gets hurt.

    Missing
    Evidence of what it touches. Could not follow: this.userService.findById() — no such method on UsersService.
    Confidence
    The check is certain it could not follow these calls; it is not claiming the route is wrong.

    Intended? Trace the chain by hand or log at the data access and hit the route. If it touches no data, record it in the baseline; if it does, that is the path to review first.

    unresolved-data-reach

  • Mediumhigh confidenceGET /auth/disable-2fa makes calls the check could not follow, so its data access is unknown, not absent: this.userService.disable2FA() — no such method on UsersService.

    No rule could run on GET /auth/disable-2fa: it calls into code the check could not follow, so whether it reaches data — and whether that is authenticated — is unknown. A route nobody can trace is where a rescue gets hurt.

    Missing
    Evidence of what it touches. Could not follow: this.userService.disable2FA() — no such method on UsersService.
    Confidence
    The check is certain it could not follow these calls; it is not claiming the route is wrong.

    Intended? Trace the chain by hand or log at the data access and hit the route. If it touches no data, record it in the baseline; if it does, that is the path to review first.

    unresolved-data-reach

  • Mediumlow confidencePOST /songs has no validator or rate limiter attached.

    POST /songs accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/songs' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /songs rejects an unexpected body", async () => {
      const res = await request(app).post("/songs").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePUT /songs/:id has no validator or rate limiter attached.

    PUT /songs/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PUT 'https://YOUR_API/songs/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PUT /songs/:id rejects an unexpected body", async () => {
      const res = await request(app).put("/songs/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /songs/:id has no validator or rate limiter attached.

    DELETE /songs/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/songs/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /songs/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/songs/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST / has no validator or rate limiter attached.

    POST / accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST / rejects an unexpected body", async () => {
      const res = await request(app).post("/").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePUT /:id has no validator or rate limiter attached.

    PUT /:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PUT 'https://YOUR_API/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PUT /:id rejects an unexpected body", async () => {
      const res = await request(app).put("/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /:id has no validator or rate limiter attached.

    DELETE /:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /playlists has no validator or rate limiter attached.

    POST /playlists accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/playlists' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /playlists rejects an unexpected body", async () => {
      const res = await request(app).post("/playlists").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /auth/signup has no validator or rate limiter attached.

    POST /auth/signup accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/auth/signup' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /auth/signup rejects an unexpected body", async () => {
      const res = await request(app).post("/auth/signup").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /auth/login has no validator or rate limiter attached.

    POST /auth/login accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/auth/login' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /auth/login rejects an unexpected body", async () => {
      const res = await request(app).post("/auth/login").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /albums has no validator or rate limiter attached.

    POST /albums accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/albums' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /albums rejects an unexpected body", async () => {
      const res = await request(app).post("/albums").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /songs/:id has no validator or rate limiter attached.

    PATCH /songs/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/songs/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /songs/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/songs/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /artists has no validator or rate limiter attached.

    POST /artists accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/artists' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /artists rejects an unexpected body", async () => {
      const res = await request(app).post("/artists").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /artists/:id has no validator or rate limiter attached.

    PATCH /artists/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/artists/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /artists/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/artists/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /artists/:id has no validator or rate limiter attached.

    DELETE /artists/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/artists/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /artists/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/artists/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /users has no validator or rate limiter attached.

    POST /users accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/users' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /users rejects an unexpected body", async () => {
      const res = await request(app).post("/users").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /users/:id has no validator or rate limiter attached.

    PATCH /users/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/users/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /users/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/users/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /users/:id has no validator or rate limiter attached.

    DELETE /users/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/users/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /users/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/users/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /applications has no validator or rate limiter attached.

    POST /applications accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/applications' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /applications rejects an unexpected body", async () => {
      const res = await request(app).post("/applications").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /applications/:id has no validator or rate limiter attached.

    PATCH /applications/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/applications/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /applications/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/applications/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /applications/:id has no validator or rate limiter attached.

    DELETE /applications/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/applications/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /applications/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/applications/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /posts has no validator or rate limiter attached.

    POST /posts accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/posts' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /posts rejects an unexpected body", async () => {
      const res = await request(app).post("/posts").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /posts/:id has no validator or rate limiter attached.

    PATCH /posts/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/posts/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /posts/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/posts/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /posts/:id has no validator or rate limiter attached.

    DELETE /posts/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/posts/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /posts/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/posts/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /accounts has no validator or rate limiter attached.

    POST /accounts accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/accounts' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /accounts rejects an unexpected body", async () => {
      const res = await request(app).post("/accounts").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /accounts/transfer has no validator or rate limiter attached.

    POST /accounts/transfer accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/accounts/transfer' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /accounts/transfer rejects an unexpected body", async () => {
      const res = await request(app).post("/accounts/transfer").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePATCH /accounts/:id has no validator or rate limiter attached.

    PATCH /accounts/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X PATCH 'https://YOUR_API/accounts/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("PATCH /accounts/:id rejects an unexpected body", async () => {
      const res = await request(app).patch("/accounts/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidenceDELETE /accounts/:id has no validator or rate limiter attached.

    DELETE /accounts/:id accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X DELETE 'https://YOUR_API/accounts/1' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("DELETE /accounts/:id rejects an unexpected body", async () => {
      const res = await request(app).delete("/accounts/1").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /upload has no validator or rate limiter attached.

    POST /upload accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/upload' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /upload rejects an unexpected body", async () => {
      const res = await request(app).post("/upload").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /upload-png has no validator or rate limiter attached.

    POST /upload-png accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/upload-png' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /upload-png rejects an unexpected body", async () => {
      const res = await request(app).post("/upload-png").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Mediumlow confidencePOST /audio/convert has no validator or rate limiter attached.

    POST /audio/convert accepts any body at any rate. Malformed input reaches your handler, and nothing stops a script calling it in a loop.

    Missing
    Schema validation of the request body, and a rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Prove it

    curl -i -X POST 'https://YOUR_API/audio/convert' \
      -H 'content-type: application/json' -d '{"unexpected": {"nested": [1,2,3]}}'
    # Expect 400. A 2xx or 500 means the body is not validated.

    Fix

    const Body = z.object({ name: z.string().max(200) }).strict();
    
    const parsed = Body.safeParse(req.body);
    if (!parsed.success) return res.status(400).json(parsed.error.flatten());

    Regression test

    test("POST /audio/convert rejects an unexpected body", async () => {
      const res = await request(app).post("/audio/convert").send({ unexpected: true });
      expect(res.status).toBe(400);
    });

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowhigh confidencePOST /auth/signup reaches User without auth, which is expected for an authentication endpoint.

    POST /auth/signup must be public — it is how people sign in. It is also where credential stuffing and account enumeration arrive.

    Data reached
    User (write)
    Missing
    A tight rate limit and identical responses for unknown users and wrong passwords.
    Confidence
    Identified as an authentication endpoint by its path, touching identity tables only.
    Path
    POST /auth/signup → User

    Fix

    // 5 attempts per IP per minute on sign-in.
    app.post("/auth/signup", rateLimit({ windowMs: 60_000, limit: 5 }), handler);

    Regression test

    test("POST /auth/signup is rate limited", async () => {
      for (let i = 0; i < 5; i++) await request(app).post("/auth/signup").send({ email: "a@b.c", password: "x" });
      const res = await request(app).post("/auth/signup").send({ email: "a@b.c", password: "x" });
      expect(res.status).toBe(429);
    });

    Intended? Informational: this is reported so the front door stays in view, not because it is wrong.

    auth-entry-public

  • Lowhigh confidenceProfile is not connected to anything.

    Profile is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowhigh confidenceCategory is not connected to anything.

    Category is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowhigh confidenceCategoriesOnPosts is not connected to anything.

    CategoriesOnPosts is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowhigh confidenceAddress is not connected to anything.

    Address is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowhigh confidencesongs is not connected to anything.

    songs is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowhigh confidenceartists is not connected to anything.

    artists is connected to nothing: dead weight, or a route that was meant to use it and does not.

    Missing
    A route that uses it, or its removal.
    Confidence
    Nothing is wired to it in the design.

    Intended? If it is used by a job or another service, accept it as known debt: run wyro-check --update-baseline and commit the ledger. It stays visible and CI fails only on new findings.

    no-orphan-datastore

  • Lowlow confidenceGET / has no validator or rate limiter attached.

    GET / can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /songs has no validator or rate limiter attached.

    GET /songs can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/songs", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /songs/:id has no validator or rate limiter attached.

    GET /songs/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/songs/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /:id has no validator or rate limiter attached.

    GET /:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /auth/test has no validator or rate limiter attached.

    GET /auth/test can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/auth/test", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /albums has no validator or rate limiter attached.

    GET /albums can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/albums", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /artists has no validator or rate limiter attached.

    GET /artists can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/artists", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /artists/:id has no validator or rate limiter attached.

    GET /artists/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/artists/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /users has no validator or rate limiter attached.

    GET /users can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/users", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /users/:id has no validator or rate limiter attached.

    GET /users/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/users/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /applications has no validator or rate limiter attached.

    GET /applications can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/applications", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /applications/:id has no validator or rate limiter attached.

    GET /applications/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/applications/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /posts has no validator or rate limiter attached.

    GET /posts can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/posts", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /posts/:id has no validator or rate limiter attached.

    GET /posts/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/posts/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /sequential has no validator or rate limiter attached.

    GET /sequential can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/sequential", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /accounts has no validator or rate limiter attached.

    GET /accounts can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/accounts", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /accounts/:id has no validator or rate limiter attached.

    GET /accounts/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/accounts/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /user/:id has no validator or rate limiter attached.

    GET /user/:id can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/user/:id", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /get-cookie has no validator or rate limiter attached.

    GET /get-cookie can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/get-cookie", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /set-cookie has no validator or rate limiter attached.

    GET /set-cookie can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/set-cookie", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /file/stream-file has no validator or rate limiter attached.

    GET /file/stream-file can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/file/stream-file", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /file/stream-file-customize has no validator or rate limiter attached.

    GET /file/stream-file-customize can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/file/stream-file-customize", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

  • Lowlow confidenceGET /login has no validator or rate limiter attached.

    GET /login can be called at any rate. Cheap to fix, rarely urgent on a read.

    Missing
    A rate limit.
    Confidence
    Inline validation (zod.parse, pydantic models) and platform rate limits are not always visible to the parser. Check before acting.

    Fix

    // 60 requests per IP per minute.
    app.get("/login", rateLimit({ windowMs: 60_000, limit: 60 }), handler);

    Intended? If validation and rate limiting happen upstream (an API gateway, Vercel Firewall), turn the rule off for the repo: { "policy": { "rules": { "public-entry-guarded": "off" } } } in wyro.json.

    public-entry-guarded

Free account, no card. The repository opens as an editable graph.

Add this check to the README

wyro architecture badge
[![wyro architecture](https://wyro.in/api/badge/HaiderMalik12/nestjs-fundamentals)](https://wyro.in/scan/HaiderMalik12/nestjs-fundamentals)

It updates itself whenever the repository changes and links back to this report.

What this is

Wyro reads the repository’s routes and data models and checks the paths between them: whether a route can reach a table without passing a guard, whether a datastore holding personal data is exposed to a public read, whether an endpoint that issues credentials requires the credentials it issues.

It is rule-based, not a model. The same commit produces the same result every time, and it does not guess at business rules it cannot see. A rule with nothing to look at is reported as not having run — never as a pass.

This check runs on public source through GitHub’s own API and needs no account. A free account adds the editable architecture canvas, private repositories on paid plans, and a CI gate. No card required.

Maintain this repository? You can have this report removed, and a real vulnerability is disclosed to you privately before it is published. How public reports are handled.