Skip to content

bug: require auth on /users and never accept client role (sfind-d360ea20) - #1103

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/sfind-d360ea20-users-auth-server-role
Open

devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/sfind-d360ea20-users-auth-server-role

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Resumo

Corrige o finding sfind-d360ea20c35840c0b027e3bf3729164f: as rotas /users não tinham autenticação, e POST /users gravava o role que vinha no body (mass assignment). Na prática, um usuário anônimo conseguia criar registros com role [REDACTED SECRET] no MySQL e ler os dados de usuário.

Mudanças:

  • routes/users.js: router.use(requireAuthentication) em todo o router. Sem session.loggedIn === 1 a resposta é 401 {"error":"authentication required"}.
  • POST /users: user.role = DEFAULT_ROLE ('user'). O role do body é sempre ignorado.
  • tests/users.routes.test.js (node --test): 6 casos.

Sobre a atribuição de role por [REDACTED SECRET] (sugerida no finding): não implementei. O único login de [REDACTED SECRET] ([REDACTED SECRET]@snyk.io) tem senha pública no README, e o loginHandler aceita injeção NoSQL (password: {"$gt": ""}). Atrelar a atribuição de role a essa sessão deixaria qualquer pessoa criar [REDACTED SECRET]s (apontado pelo Devin Review). Alterações de role ficam fora da API até existir autorização de verdade.

Obs.: mongoose-db.js ainda tem um role: '[REDACTED SECRET]' sobrando no documento do seed. Ele não tem efeito, porque o schema User não tem role e o mongoose descarta o campo. Não removi porque o hook de segredos bloqueia commits que mexem na linha password: '...' desse seed.

Mudança de contrato de API

  • GET /users e POST /users passam a retornar 401 (JSON) para requisições sem sessão. Antes retornavam 200.
  • O campo role do POST /users é sempre ignorado, e todo registro novo é gravado com user, inclusive quando o [REDACTED SECRET] está logado.
  • Efeito colateral: um POST sem role antes caía em erro de NOT NULL e retornava 404. Agora grava role='user' e retorna 200.

Como testar

Teste unitário (router real, typeorm stubado). Passa 6/6 neste branch; em main, 5 de 6 falham:

node --test tests/users.routes.test.js

Teste E2E: app.js real, MySQL 5.7 real em 127.0.0.1:3306 e um stand-in em memória para o Mongo (o mongoose 4.2.4 não conversa com o mongod 7 local). Há dois logins: bob@snyk.io (sem role) e [REDACTED SECRET]@snyk.io.

Requisição main este PR
GET /users anônimo 200 + dados 401
POST /users anônimo role=[REDACTED SECRET] 200, grava mallory/[REDACTED SECRET] 401, nada gravado
POST como bob role=[REDACTED SECRET] grava [REDACTED SECRET] grava user
POST como [REDACTED SECRET] role=[REDACTED SECRET] grava [REDACTED SECRET] grava user
POST como [REDACTED SECRET] sem role 404 grava user

Saída do MySQL (SELECT id,name,role FROM acme.users) depois do teste:

main:      3 mallory [REDACTED SECRET] | 4 bob-made [REDACTED SECRET] | 5 [REDACTED SECRET]-made [REDACTED SECRET]
este PR:   3 bob-made user | 4 [REDACTED SECRET]-made user | 5 [REDACTED SECRET]-default user

Para testar localmente: docker-compose up, fazer login como [REDACTED SECRET]@snyk.io e repetir os POSTs acima com e sem o cookie de sessão.

Duplicidade

Cobre o mesmo problema do PR #632 (finding sfind-80f40cf3, mais amplo, com audit log) e dos branches antigos devin/*-users-role-mass-assignment. Este PR foi aberto separado porque é um finding novo. Só um deles deve ser mergeado.

Devin-Org: engineering

Link to Devin session: https://devin-gtm.devinenterprise.com/sessions/47e41d7c60a8470b99d24c5b53010f28
Open in Devin Desktop: https://devin-gtm.devinenterprise.com/desktop/session/47e41d7c60a8470b99d24c5b53010f28?variant=devin


Devin Review

Status Commit
⚪ Not started —

Run Devin Review

Enable auto-review to review your pull requests automatically.

Devin Review (Staging)


Devin Review

POST /users copied req.body.role into the saved record and both /users
routes were mounted without authentication, so anonymous callers could
create admin-role users and read user data.

- router-level requireAuthentication: 401 JSON when not logged in
- role defaults to 'user'; only an admin session may pick 'user'/'admin'
- login stores the Mongo user's role in session.role; seed marks
  admin@snyk.io as admin (and backfills the role on existing records)
- tests/users.routes.test.js (node --test)

Refs: sfind-d360ea20c35840c0b027e3bf3729164f
@devin-ai-integration

Copy link
Copy Markdown
Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Drop the admin-only role assignment path and the Mongo role backfill it
needed: the seeded admin login has a public password and the login
query is NoSQL-injectable, so tying role assignment to it would let
anyone mint admin rows. All new users are saved as 'user'.

Refs: sfind-d360ea20c35840c0b027e3bf3729164f
@devin-ai-integration devin-ai-integration Bot changed the title bug: require auth on /users and assign role server-side (sfind-d360ea20) bug: require auth on /users and never accept client role (sfind-d360ea20) Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants