Skip to content

fix: read the caller's team, and carry two ReDoS patches - #137

Merged
catinspace-au merged 3 commits into
mainfrom
fix/team-scope-and-redos
Oct 10, 2026
Merged

catinspace-au merged 3 commits into
mainfrom
fix/team-scope-and-redos

Conversation

@catinspace-au

Copy link
Copy Markdown
Contributor

Summary

Two fixes. Every member was reading the first team's record, and two chart-config regexes ran in quadratic time on input a member stores.

Team scoping

  • getTeam(id) ignored id and returned the first team in the store. Upstream runs one team per deployment, so it never shows there. DFE runs one per org plus the platform team, so GET /me and GET /team gave every member the first team's name, API key and query limits.
  • Fixed with one expression in controllers/team.ts: findOne({}) to findOne({ _id: id }). Catalogued in .fork-surface and docs/fork/what-we-changed.md.
  • /me now strips apiKey and allowedAuthMethods for anyone but the engine, the same as /team.
  • The existing /team strip never worked on the real response. The router hands res.json a mongoose document, whose fields are getters, so the filter saw $__ and _doc and the API key went out inside _doc. Both strips now filter the serialised record.
  • dfe/__tests__/team-scope.int.test.ts seeds two teams against the real app and MongoDB. It fails with the old lookup, the old strip, or the /me mount removed.

Quadratic regexes

  • Carried as security/patches/0001 and 0002, generated by scripts/security-override.py --apply, so the upstream merge never sees them.
  • Groupby literal strip: 2.2 s at 64 KiB before, 6 ms at 1 MiB after. Sort-direction split: 5.5 s at 64 KiB before, 5 ms at 1 MiB after.
  • Same result as the old pattern on every input the call site sees: 0 differences over 24,887 distinct string literals from the repo's tests and 262,222 distinct random inputs. common-utils unit suite: 2803 passing.
  • The third flagged regex, in core/utils.ts, is NOT in this PR. Its input is the source's timestampValueExpression, which only the engine writes in DFE, and the conflict-surface guard does not yet know about security patches on uncatalogued files.

How to test on Vercel preview

N/A, non-UI change.

References

  • Code-scanning alerts 3 and 4 (polynomial ReDoS).

getTeam ignored its id and returned the first team in the store. Upstream runs one team per deployment so it never shows. DFE runs one per org, so every member's GET /me and GET /team carried the first team's name, API key and query limits.

- getTeam now looks the team up by id. One expression in controllers/team.ts, catalogued in .fork-surface and docs/fork/what-we-changed.md.
- /me strips apiKey and allowedAuthMethods for anyone but the engine, the same as /team.
- The /team strip never worked against the real response. The router sends a mongoose document, whose fields are getters, so the filter saw $__ and _doc and passed the API key through inside _doc. Both strips now filter the serialised record.
- dfe/__tests__/team-scope.int.test.ts seeds two teams against the real app and MongoDB. It fails with the old lookup, the old strip, or the /me mount removed.
Two regexes in renderChartConfig.ts take time in the square of their input, and a member controls both inputs through a stored dashboard tile. 64 KiB costs 2.2 s on the groupBy literal strip and 5.5 s on the sort-direction split. At 1 MiB the rewrites take 6 ms and 5 ms.

These are TEMPORARY, so they ride as security/patches/0001 and 0002, generated into the tree by scripts/security-override.py --apply and stripped by --unapply before every upstream merge. Each patch header carries the advisory, the vector and the upstream tracker.

Both rewrites give the same result as the old pattern for every input the call site can see: 0 differences over 24,887 distinct string literals from the repo's own tests and 262,222 distinct random inputs.
Comment thread packages/api/src/api-app.ts Fixed
Upstream's /me mount line stays byte-identical, so the sync sees an added line instead of a modified one. It also stops code scanning re-reporting the existing rate-limit finding on that line as new.
@catinspace-au
catinspace-au merged commit 27fa6b5 into main Oct 10, 2026
28 checks passed
@catinspace-au
catinspace-au deleted the fix/team-scope-and-redos branch October 10, 2026 09:22
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.

2 participants