[pull] preview from makeplane:preview#53
Merged
Conversation
#9189) The web/admin/space Docker image builds fail at the Vite/PostCSS step with "Cannot find module '@tailwindcss/postcss'". These apps load the shared @plane/tailwind-config/postcss.config.js, which references the @tailwindcss/postcss plugin by name, but the plugin was only declared as a dependency of packages/tailwind-config. The Docker build installs via turbo prune + 'pnpm fetch' + 'pnpm install --offline', which lays out node_modules so PostCSS resolves the plugin relative to the app directory (apps/<app>), where it is not reachable. A plain 'pnpm install' resolves it from tailwind-config's context instead, which is why local builds passed and masked the issue. Declare @tailwindcss/postcss as a direct devDependency of the three apps that run Vite/PostCSS so it is symlinked into each app's node_modules and resolves under the isolated linker regardless of install flow. Verified by reproducing the exact Docker flow (prune -> fetch -> --frozen-lockfile offline install -> build) for admin, space and web: all install in sync and build successfully with full Tailwind CSS output.
* fix: bump npm deps to resolve Dependabot advisories Resolve 8 open Dependabot alerts (all npm, in pnpm-lock.yaml) by bumping the affected packages in pnpm-workspace.yaml and regenerating the lockfile: - axios 1.15.2 -> 1.16.0 (catalog): CVE-2026-44494/44492/44490/44489 - tmp -> 0.2.6 (override): CVE-2026-44705 path traversal - ws 8.x -> 8.20.1 (catalog + scoped override): CVE-2026-45736 - qs 6.14.2 -> 6.15.2 (override): CVE-2026-8723 DoS - brace-expansion 5.0.5 -> 5.0.6 (override): CVE-2026-45149 DoS brace-expansion and qs were pinned to their vulnerable versions in the overrides block, so the pins had to be bumped directly. ws is scoped to the 8.x major (ws@7.5.10 is below the vulnerable >=8.0.0 floor). All bumps are semver-compatible patch/minor upgrades; no source changes required. * fix: use named axios `create` import after 1.16.0 bump axios 1.16.0 newly exposes `create` as a named export, so oxlint's import/no-named-as-default-member rule now flags `axios.create(...)`. That added one warning to @plane/services (7 > its --max-warnings=6 baseline) and to apps/web and apps/live, failing check:lint — surfaced on this PR because the lockfile change busts Turbo's lint cache. Switch the three `axios.create(...)` call sites to a named `{ create }` import. `create` is a real value+type export in axios 1.16.0 (verified via tsc). isCancel/CancelToken are left as `axios.*`: CancelToken is only a type export (cannot be a value import under verbatimModuleSyntax) and both were already counted within the existing baselines. Verified locally: full `pnpm check:lint` (16/16) and `check:types` (15/15) pass.
…A-9pvm-fcf6-9234) (#9130) * fix(api): rate-limit magic-code verification and bound per-token attempts The magic-link sign-in / sign-up endpoints accept a 6-digit numeric code (900k-value space, 600s TTL) but never increment a failure counter on a wrong-code verify and extend django.views.View rather than DRF APIView, so DRF's AuthenticationThrottle never runs against them. The space-side generate endpoint also lacked throttle_classes. Combined, this allowed an unauthenticated attacker who knew a victim's email to brute-force the code within the TTL window and log in as the victim. - Add MAX_VERIFY_ATTEMPTS=5 in MagicCodeProvider.set_user_data: failed comparisons now persist verify_attempts in Redis under the remaining TTL and, on hitting the limit, delete the key and raise EMAIL_CODE_ATTEMPT_EXHAUSTED. This is the load-bearing fix - it caps total attempts per issued token regardless of request rate. - Add authentication_throttle_allows() so plain Django Views can apply AuthenticationThrottle without converting to APIView (would change CSRF + request-parsing semantics for the redirect-flow endpoints). - Apply the throttle to MagicSignIn/UpEndpoint and the space variants; add throttle_classes to MagicGenerateSpaceEndpoint to match its app sibling. Refs GHSA-9pvm-fcf6-9234. * fix(api): make verify-attempt increment atomic, expose throttle rate via env Address PR review feedback: - Replace the JSON read-modify-write of verify_attempts with a Lua EVAL script that INCRs a dedicated counter key and EXPIREs it only on the first increment. The previous round-trip was racy: parallel wrong-code requests could read the same value and both write the same incremented count, letting an attacker exceed MAX_VERIFY_ATTEMPTS under concurrency. Counter is now reset on each new token issuance and cleared on successful verify / exhaustion. - Make AuthenticationThrottle.rate configurable via the AUTHENTICATION_RATE_LIMIT env var (default 10/minute, down from 30 to tighten the budget on unauth auth-adjacent endpoints). Document it in deployments/aio and deployments/cli variables.env. * test(api): cover magic-code attempt cap, counter reset, and auth throttle Add the contract tests called out in the PR test plan: - TestMagicSignInVerifyAttempts: - test_exhausted_after_max_wrong_attempts: after MAX_VERIFY_ATTEMPTS wrong codes the next verify redirects with EMAIL_CODE_ATTEMPT_ EXHAUSTED_SIGN_IN and both Redis keys are deleted; a follow-up verify reports EXPIRED. - test_counter_increments_on_each_wrong_attempt: the dedicated verify_attempts counter advances by exactly one per wrong POST, matching the atomic Lua INCR. - test_counter_resets_on_token_regeneration: regenerating the magic-link clears the counter so the user isn't pre-locked-out by a prior session's wrong attempts. - TestMagicSignUpVerifyAttempts.test_signup_exhausted_after_max_wrong_attempts: the sign-up endpoint returns EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP on the exhausting attempt. - TestAuthenticationThrottle: exercises authentication_throttle_allows on the plain-View redirect-flow endpoints by patching the rate down and asserting RATE_LIMIT_EXCEEDED is appended to the redirect URL once the per-IP budget is exceeded, for both magic-sign-in and magic-sign-up. Each new class clears Django cache (DRF throttle storage) and the per-email Redis keys around every test so runs are independent. * fix(api): clamp remaining_ttl to >=1 for verify-attempt counter EXPIRE ri.ttl() returns 0 when the token has less than one second remaining (Redis floors to whole seconds). The previous clamp only caught None and < 0, so a sub-second TTL would pass through and the Lua script's EXPIRE counter 0 would immediately delete the key — letting an attacker bypass MAX_VERIFY_ATTEMPTS during the final second of the token's life. Switch the comparison to <= 0. Narrow real-world impact (sub-second window, throttle still bounds the rate) but the cap should hold regardless of timing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )