Conversation
…) (#3462) adm-zip < 0.6.0 allows a crafted ZIP to trigger a 4GB memory allocation (DoS). This is reachable: apps/api/src/questionnaire/utils/content-extractor.ts runs `new AdmZip(fileBuffer)` on user-uploaded questionnaire files (xlsx/docx are ZIP containers). Bumps the direct dependency to ^0.6.0 (patched) and updates bun.lock. Our usage (new AdmZip, getEntry, getData, addFile, toBuffer) is unchanged in 0.6.0. Supersedes Dependabot PR #3451, which bumped package.json but left bun.lock out of sync. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…rts (#3464) - engine.io: add bun override to ^6.6.7. The vulnerable 6.5.5 (Engine.IO polling connection-exhaustion DoS, <6.6.7) was pulled transitively via @trigger.dev/core -> socket.io@4.7.4. Override collapses it to 6.6.9 (the version top-level socket.io@4.8.3 already uses); bun.lock now has a single engine.io@6.6.9. Not a reachable DoS for us (we run no engine.io server; trigger.dev uses it client-side) but removes the alert. - body-parser: bump the transitive dep in apps/mcp-server (runtime, via express@5.2.1) 2.2.2 -> 2.3.0 (patched; DoS via invalid limit silently disabling size enforcement). Lockfile-only; express's ^2.2.1 range permits 2.3.0, so it stays transitive and survives SDK regeneration. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
#94-#104) (#3466) A batch of 11 node-tar advisories (Critical->Moderate: decompression DoS, path traversal, symlink/hardlink escape, PAX parsing differentials) flagged every tar copy below 7.5.19. bun.lock had tar@6.2.1 (x5, via build tooling: node-gyp, cacache, @electron/rebuild, app-builder-lib, giget), tar@7.5.11 (fleetctl), and tar@7.5.20 (already patched). node-tar backported no fixes to the 6.x line, so the only remediation is tar >= 7.5.19. Added a bun override "tar": "^7.5.19" — bun.lock now resolves a single tar@7.5.20 for all consumers. tar@7 is a dual CJS/ESM package with a stable extract/create API, so the CJS build tools keep working via require(). Reachability was low pre-fix (all vulnerable copies were build-time tooling or trusted-source CLI extraction, none extract attacker-controlled archives in the runtime API), but the override removes the vulnerable versions entirely. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…S-724) (#3468) * feat(isms): internal audit programme, plan and report — clause 9.2 (CS-724) Adds the ninth ISMS document type: Compliance > ISMS > Internal Audit. - Programme paragraph (editable, seeded with a default) rendered verbatim into the generated document - Audit instances with server-generated IA-YYYY-NN references, templated scope/criteria, auditor pulled from ISMS > Roles > Internal Auditor, planned dates, status, and a conclusion verdict + narrative - Controls Tested table seeded with the default 15-row sample set (management-system clauses + high-impact Annex A controls); result + notes recorded per row - Findings with server-generated F-NN references, type/owner/due date/status/closure evidence, optional link back to a control row - Three sign-off slots per audit, frozen into the published version snapshot and rendered as the document's sign-off table - Submit gate: at least one audit, and a conclusion verdict on every completed audit (enforced server-side, mirrored in the client) * fix(isms): align internal-audit components with design-system prop types The Vercel next build enforces the design-system unions that the local tsc pass missed: Stack gap has no '5', TableCell omits className, and Select.onValueChange passes string | null. * fix(isms): address internal-audit review findings - scope audit/control/finding lookups to the internal-audit document type - seed the programme paragraph only when the draft narrative is empty, so a concurrent setup call can never overwrite an edit - trim required text fields (scope, criteria, control reference) so whitespace-only values are rejected - marking a control row non-conformity/observation now opens the findings form pre-filled with the linked row (per the ticket flow), and the edit form pre-fills clause text like the add form - preserve unsaved sign-off input across sibling register refreshes - gate the control-row Save button on validity - document the audit register fields in the OpenAPI body schema - cover the internal-audit derivation path in generate.spec * fix(isms): make the programme seed atomic and re-key the finding prompt - seed the programme via a conditional update that matches only a NULL draft narrative, removing the read-then-write race entirely (and with it the duplicated empty-narrative predicate) - key the prefilled linked-finding form by row and type, so re-marking the same control with a different result re-initializes the form * fix(isms): treat an empty-object narrative as seedable, matching generate The programme seed's conditional update now matches NULL or {} — the same empty definition generateNarrative uses — so the two seed paths can never drift while still never overwriting a populated draft. * feat(isms): render closure evidence in the exported findings table Closed corrective actions now show how they were evidenced in the generated document — appended to the description cell, keeping the reference document's seven-column findings table. --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 60 files (changes from recent commits).
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
…verwriting published (#3471) * fix(policies): create draft version on policy regenerate instead of overwriting published ## Problem When regenerating a policy, the published version's content is overwritten immediately. This bypasses the approval workflow that should gate any content changes. Regenerating a published policy currently mutates its live content, signedBy metadata, and currentVersionId directly without creating a draft for review. ## Root cause updatePolicyInDatabase in update-policy-helpers.ts rewrites policy.content, currentVersionId, and signedBy on the live published policy record without changing status or requiring approval. Every other content-change path (createVersion, submitForApproval, acceptChanges) creates a draft version first and only publishes on explicit approval; regenerate was the sole exception. ## Fix For published or needs_review policies, regenerate now creates a new draft version (incrementing the version number) with the regenerated content, leaving the published version's content, currentVersionId, signedBy, and status unchanged. This mirrors the existing approval workflow: draft versions are created, then approved, then published with the signing flow triggered for all employees. ## Explicitly NOT touched - Policies not yet published (status: draft) - The signing flow (runs only on explicit publish, unchanged) - Approval/rejection workflows - Version history or deletion logic ## Verification Added regression test asserting that regenerating a published policy creates a new draft version without modifying the published content or status. Existing policy regenerate and versioning unit tests pass locally ✅ * fix(bug-todo): address cubic review Address review findings. * fix(bug-todo): address cubic review Address review findings.
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
…y review (#3473) * fix(isms): harden internal-audit validation and edge cases from deploy review - reject a planned end date before the start date, client-side (zod cross-field rule with inline error) and server-side against the effective merged schedule on update - linked findings inherit the control row's reference as their clause label when none is given, and deleting a control row labels its label-less findings first — no finding is ever left unlabelled - add the optional Notes field to the add-control-row form - render the control-reference validation error in the row editor - preserve paragraph breaks when displaying the programme - don't count a whitespace-only signatory as signed - correct the F-NN reference doc comment (max+1 over surviving rows) * fix(isms): validate the audit schedule under the document lock Re-read the stored dates inside the locked transaction so two concurrent partial updates (one moving the start, one the end) can never persist an inverted schedule. Adds coverage for update-time clause-label inheritance. --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
…h automations (#3469) * fix(policies): rename CreateVersionDto to avoid swagger collision with automations ## Problem The create-policy-version MCP tool is completely broken. Callers either hit a 400 error from the API ("property scriptKey should not exist", "property version should not exist") or are blocked by the MCP client schema validation before the call even goes out. There's no valid path to use this tool. ## Root cause Two DTO classes share the name CreateVersionDto: one in the policies module (with sourceVersionId and changelog) and one in the automations module (with version and scriptKey). NestJS Swagger keys schema components by class name, so they collide in the OpenAPI spec. The merged component ended up with version+scriptKey marked as required. Speakeasy then generated the MCP tool from that collision, making those fields required. But the live policies endpoint validates inbound DTOs with a whitelist that rejects those two fields, causing the 400. ## Fix Renamed the policies DTO class from CreateVersionDto to CreatePolicyVersionDto to eliminate the name collision in Swagger. This allows the correct schema (sourceVersionId and changelog) to be generated for the policies endpoint and for MCP tool regeneration. ## Explicitly NOT touched No changes to endpoint handlers, validation pipe config, auth, RBAC, billing, or automations module. The automations CreateVersionDto remains as-is. ## Verification ✅ Unit tests for policies version creation pass locally with the renamed DTO ✅ Added regression test asserting that the policy version endpoint accepts sourceVersionId and changelog and rejects version/scriptKey in the request body * chore(api): regenerate openapi.json for CreatePolicyVersionDto Regenerate the committed OpenAPI spec so the create-policy-version MCP tool is generated from the corrected schema (CreatePolicyVersionDto with optional sourceVersionId + changelog) instead of the collided CreateVersionDto. The Speakeasy MCP server builds from packages/docs/openapi.json, so the DTO fix only reaches the published tool once this artifact is regenerated. Also catches the spec up to already-merged endpoints whose PRs did not regenerate it: the ISMS bulk-measurements endpoint, four trust-portal request bodies, and extra optional fields on two ISMS register endpoints. All changes are additive — no existing component shape changed and nothing was removed.
…3474) * fix(policies): delete detached PDF objects when regenerating a draft Regenerating an uploaded draft cleared its PDF references but left the objects in S3, orphaning one per regeneration. The detached keys (policy + current version, deduplicated) are now removed best-effort after the database update commits; failures are logged with their keys instead of failing the regeneration. * fix(policies): capture detached PDF keys under the row lock and use APP_AWS config The cleanup client now mirrors the other trigger tasks' APP_AWS_* configuration (region, credentials, optional endpoint) instead of the default chain, and the detached keys are captured inside the transaction after a SELECT ... FOR UPDATE on the policy row — a concurrently uploaded PDF can no longer slip past the cleanup as an untracked orphan. --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com> Co-authored-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
…org owner (#3472) * fix(auth): attribute API-key mutations to the key's creator, not the org owner API keys were org-scoped with no recorded creator, so ActingUserResolver attributed every API-key/MCP mutation to the org's oldest owner. In the audit trail this made all automation look like the owner performed it, masking the real actor — a problem for a compliance product. - Add ApiKey.createdByMemberId (nullable, FK to Member, onDelete: SetNull). Populated on creation with the acting member. Nullable so legacy keys and keys whose creator was removed fall back cleanly. - create-api-key now records the creating member; validateApiKey surfaces it. - HybridAuthGuard puts it on the request; ActingUserResolver attributes the mutation to the creator (when still an active member of the org), else falls back to the org owner as before. - Tests for both the creator-attribution path and the deactivated-creator fallback. No backfill: existing keys have no recorded creator and keep falling back to the org owner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): select createdByMemberId in the legacy API-key lookup path The legacy-key branch's select was missing createdByMemberId (its deeper indentation meant the earlier bulk edit didn't cover it), so the return that references legacyMatch.createdByMemberId failed to typecheck. Add the field to the legacy select to match the primary path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(audit): resolve acting user for API-key mutations so they're logged The global AuditLogInterceptor early-returned when request.userId was absent, so API-key (and MCP) mutations were never audit-logged at all — the createdByMemberId attribution added earlier had no effect on the trail. Inject ActingUserResolver and resolve the responsible user (key creator, else org owner) when there's no session userId; skip logging only when no user can be attributed (no null-FK rows). Also fixes a pre-existing bug surfaced once the spec could load: the control mapping/unmapping descriptions read "policie" because the resolver naive-stripped the trailing "s" of "policies". Use the known Prisma model name (policies→policy) with an "ies"→"y" fallback. The interceptor spec never ran before (it pulled better-auth's ESM subpaths via permission.guard); mock @trycompai/auth like the other specs so all 41 tests execute. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): attribute API-key mutations to the acting user across silent sinks The interceptor fix covered automatic @RequirePermission audit logging. This covers the remaining sinks where an API-key mutation succeeded but attribution was silently lost or credited to the org owner instead of the responsible user: - vendors create + triggerAssessment: the controller now resolves the acting user and threads it as createdByUserId, so the auto-generated risk-assessment task ("created this task") credits the key creator, not the admin fallback. - cloud-security scan: attribute scan_completed via ActingUserResolver instead of raw req.userId (was skipped entirely for API keys). - policies publish-all: per-policy audit rows were dropped for API-key auth (authContext.userId undefined) — resolve the actor first. - isms createRow: enteredById (a Member FK) was null for API keys — resolve the acting member. ActingUserResolver now populates memberId on every path (session member, key creator, or fallback owner's member), so Member-FK sinks like isms enteredById attribute correctly. Owner lookup selects the member id alongside the user id. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): address cubic review — actor attribution edge cases - vendors create/triggerAssessment: 400 when no actor resolves (org has no owner) instead of creating a vendor whose assessment task has no attributed user — matches ActingUserResolver's contract. - cloud-security scan: attribution is best-effort (try/catch) so a transient resolver/audit failure can't fail an already-completed scan and invite a re-run. - isms bulkCreateMeasurements: resolve the acting member (session-first, then api-key creator/owner) so bulk saves via API key don't persist null enteredById. - hybrid-auth guard: service-token x-user-id now sets request.memberId so Member-FK sinks can attribute service-token-acting mutations. - tests: createApiKey creator attribution (session forwards memberId, api-key forwards null), vendors 400-on-null, isms bulk api-key attribution. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auth): restrict service-token x-user-id to active members Cubic follow-up: the x-user-id member lookup didn't filter deactivated / inactive memberships, so an offboarded user supplied via x-user-id could receive new audit / enteredById attribution. Add deactivated:false + isActive:true to the lookup (matching ActingUserResolver's filters); an inactive member now resolves to no acting user and falls back to owner resolution downstream. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(auth): cover service-token active-membership restriction Cubic follow-up: add regression coverage for the x-user-id acting-member resolution — an active member populates request.userId + memberId (and the lookup is scoped to deactivated:false/isActive:true), while a deactivated/ inactive member sets neither, so the restriction can't silently regress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(audit): record caller provenance for non-session attributions Security review follow-up (non-repudiation): API-key / service-token mutations that resolve to the org owner (or key creator) were recorded in the audit trail with no marker, so they read as if the user personally acted in a session. Carry ActingUserResolver's callerLabel through the interceptor and cloud-security scan — append `[via API key "..."]` to the description and store `via` in the audit data JSON. Mirrors the existing exception / scan-mode endpoints. Session actions are unaffected (no label). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(security): add security-review skill, agent, hook, and pre-push gate Adds a first-party security-review skill + security-reviewer agent covering the high-risk vuln classes (broken access control, tenant isolation, injection, secrets, SSRF, auth/session, unsafe uploads, mass assignment, IDOR). Makes it run automatically via a behavior-based PostToolUse nudge (API surface, services, route handlers, trigger jobs, by-id data access, plus content patterns for XSS/ raw SQL/exec), inclusion in production-readiness, and a Husky pre-push hard gate (bypass after review: SECURITY_REVIEWED=1 git push). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(security): auto-run security review before push (PreToolUse agent hook) Adds a PreToolUse agent hook on `git push` that automatically runs the security-reviewer on the outgoing diff (origin/main...HEAD) and blocks the push if it finds an unaddressed P1/P2 — so the security skill triggers automatically on push instead of relying on a manual run. Fires for Claude-driven pushes; the Husky pre-push remains the backstop for terminal/CI pushes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(security): add Claude security-review GitHub Action; drop local push block Adopts Anthropic's official claude-code-security-review Action as the authoritative gate — runs on every PR, diff-scoped, posts inline findings — layered with repo-specific instructions (tenant isolation, authz-vs-attribution, IDOR). Removes the local push friction that doesn't actually run a review: the Husky pre-push hard block and the PostToolUse reminder. The security actually runs in two places now: the PreToolUse agent hook (Claude-driven pushes) and the PR Action (all PRs). Prereq: add an ANTHROPIC_API_KEY repo secret. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(security): remove misfiring PreToolUse security hook The agent hook fired on non-git-push commands and blocked them (its allow/block semantics were inverted and the `if` filter didn't scope). The PR GitHub Action is the reliable auto-run gate; drop the local hook. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(security): review every commit on a PR, not just the first Set run-every-commit so the security Action re-reviews the latest diff on each push to a PR. Without it the action runs once per PR and skips later commits, leaving code added after the first review unchecked while the required check stays green. Findings remain advisory PR comments (no merge block on noise). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(api): regenerate openapi.json after merging main Regenerated from the merged code so the spec carries #3469's CreatePolicyVersionDto rename plus the current ISMS-audit schema (main's committed spec had drifted). Written as-generated by the dev boot. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 3.106.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.
Summary by cubic
Ships Internal Audit for ISMS (ISO 27001 clause 9.2, CS‑724): new document with an editable programme, audits register (IA‑YYYY‑NN), Controls Tested, findings, sign‑off, export, and submit gates; includes a DB migration and UI/API changes. Also deploys security fixes—upgrade
adm-zipto ^0.6.0, pinengine.ioto ^6.6.7, bumpbody-parserto 2.3.0, and overridetarto ^7.5.19—changes policy regenerate to create a new draft, fixes the create‑policy‑version tool schema by renaming the policies DTO toCreatePolicyVersionDto, cleans up detached policy PDFs on draft regenerate, attributes API‑key/service‑token actions to the real actor with full audit logging, and adds a security review workflow/skill.Written for commit 206ed96. Summary will update on new commits.