Skip to content

Unauthenticated writes on PUT /post/:id/views and PUT /publish/:id (orm/express) #8560

Description

@zyx77550

In orm/express/src/index.ts, both write endpoints take :id straight from the URL and mutate the Post row with no authentication or ownership check:

app.put('/post/:id/views', async (req, res) => {
  const { id } = req.params
  const post = await prisma.post.update({
    where: { id: Number(id) },
    data: { viewCount: { increment: 1 } },
  })
  // ...
})

app.put('/publish/:id', async (req, res) => {
  const { id } = req.params
  // ...
  const post = await prisma.post.update({
    where: { id: Number(id) },
    data: { published: !postData?.published },
  })
})

Anyone who can reach the API can inflate the view count or toggle published on any post by guessing an integer id — there's no caller-identity check anywhere on either path.

I get that this is an intentionally minimal teaching example and auth is out of scope for the "getting started" story — not filing this as a "this repo is broken," more as a heads-up: this example is widely copied into real projects, and this specific gap (writes gated by nothing but a URL param) is one people tend to carry over verbatim. A one-line comment near these two handlers (// no auth check here — add one before shipping this to production) or a short note in the README might be enough to save someone a bad day.

Happy to send a small PR adding that comment / a minimal isOwner stub if useful — let me know which you'd prefer.

(Found while running an automated behavior-proof tool — SPARDA — against a corpus of public Express repos; happy to share the full report if useful.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions