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.)
In
orm/express/src/index.ts, both write endpoints take:idstraight from the URL and mutate thePostrow with no authentication or ownership check:Anyone who can reach the API can inflate the view count or toggle
publishedon 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
isOwnerstub 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.)