Conversation
…2079) * feat(app): add 'Remove Device' menu on Employ Devices tab * feat(api): create delete endpoint to remove single host from fleet * feat(app): integrate delete endpoint to remove the host * fix(api): missing host ownership validation allows cross-organization deletion * fix(app): redundant null check after early return guard on handleRemoveDeviceClick * fix(api): duplicated host deletion logic not consolidated on fleet.service * fix(app): remove unnecessary accessorKey on actions column * fix(app): remove duplicated database query for current user member --------- Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
|
PR SummaryHigh Risk Overview Adds migration + cleanup for legacy policies (Trigger.dev tasks for org/all-org batch migration and app-side migration helpers) and new S3 helpers to copy/delete version PDFs; policy deletion now attempts to remove policy + version PDFs from S3 before cascade deletes. Expands adjacent workflows: adds owner-only People API/UI support to remove a single FleetDM host, adds Written by Cursor Bugbot for commit 0cfbce6. This will update automatically on new commits. Configure here. |
* feat(api): add revision note handling for findings update * feat(app): update onStatusChange to support async handling in FindingItem --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/findings/FindingItem.tsx
Show resolved
Hide resolved
| } finally { | ||
| setIsSubmitting(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Revision dialog closes on API failure, losing user input
Medium Severity
The handleRevisionSubmit and handleRevisionSkip functions expect onStatusChange to throw on API failure so the dialog remains open for retry. However, handleStatusChange (the implementation of onStatusChange) catches errors internally and shows a toast but doesn't re-throw. This causes await onStatusChange(...) to always resolve successfully, so the dialog closes and the user's typed revision note is cleared even when the API call fails. The user sees an error toast but loses their input.
Additional Locations (1)
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(2000) | ||
| revisionNote?: string | null; |
There was a problem hiding this comment.
Missing explicit type causes incorrect OpenAPI schema
Low Severity
The @ApiProperty decorator for revisionNote is missing an explicit type: String specification. Combined with nullable: true and TypeScript type string | null, this causes NestJS Swagger to generate "type": "object" in the OpenAPI spec instead of "type": "string". Add type: String to the decorator options.
* feat(api): add policy versioning with create, update, delete, and fetch operations * fix(api): update approver handling and current version assignment in policy changes * feat(api): enhance deleteById to clean up PDFs from S3 before deletion * feat(api): update policy version creation to handle S3 copy after transaction * feat(api): clear pending approval state when publishing or activating versions * feat(api): include organizationId check to prevent cross-org access in PDF URL retrieval * feat(api): sync draft content to prevent unpublished changes UI bug * feat(api): prevent activating a different version when another is pending approval * feat(api): add validation for deactivated members as approvers * feat(api): clear signatures when publishing or activating policy versions * feat(api): sync draft content to prevent false unpublished changes indicator * feat(api): use transaction for atomic policy updates and sync draft content --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
apps/app/src/app/(app)/[orgId]/policies/[policyId]/components/PolicyPageTabs.tsx
Show resolved
Hide resolved
| } | ||
|
|
||
| return processed; | ||
| } |
There was a problem hiding this comment.
Duplicated processContent function and ContentNode interface
Medium Severity
The ContentNode interface and processContent function are duplicated in both update-draft.ts and update-version-content.ts. These are nearly identical implementations that sanitize TipTap editor content. Extract to a shared utility like apps/app/src/actions/policies/lib/content-utils.ts.
| console.error('Error copying policy PDF:', error); | ||
| return null; | ||
| } | ||
| } |
There was a problem hiding this comment.
* fix(trust-portal): improve error handling for custom domain updates * fix(trust-portal): enhance error handling for domain ownership checks --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
apps/app/src/app/(app)/[orgId]/policies/[policyId]/editor/components/PolicyDetails.tsx
Show resolved
Hide resolved
| console.error('Error copying policy PDF:', error); | ||
| return null; | ||
| } | ||
| } |
There was a problem hiding this comment.
Duplicate S3 helper functions across packages
Low Severity
copyPolicyVersionPdf in create-version.ts and deletePolicyVersionPdf in delete-version.ts duplicate functionality that already exists in AttachmentsService (attachments.service.ts lines 341-374). Consider creating a shared S3 utility in the app package or calling the API endpoints.
| const content = policy.currentVersion?.content ?? policy.content; | ||
| const pdfUrl = policy.currentVersion?.pdfUrl ?? policy.pdfUrl; | ||
| return { content, pdfUrl }; | ||
| }; |
There was a problem hiding this comment.
Duplicated getEffectiveData helper in two services
Low Severity
The getEffectiveData helper function is identically defined in both policies.service.ts (lines 946-951) and trust-access.service.ts (lines 2005-2009). Both extract content and pdfUrl from a policy's currentVersion with fallback to policy-level values.
* feat(policies): enhance policy versioning and status handling * refactor(policies): simplify policy header layout and actions * refactor(policies): update publish action to handle empty content and add pdfUrl * refactor(policies): clear approval fields in publish action * refactor(policies): sync draft content with published version in publish action * refactor(policies): optimize initialVersionId change detection in PolicyDetails * refactor(policies): add draft badge to policy details for better status indication * refactor(policies): add lastPublishedAt to policy details and tabs for status display * refactor(policies): implement transaction in publish action to prevent orphaned versions * refactor(cloud-tests): update legacy integration filtering for cloud providers --------- Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
* feat(vendor): add isSubProcessor field to vendor DTOs and forms * refactor(vendor): update isSubProcessor field layout and tooltip * feat(vendor): add onUpdate callback to SecondaryFields component --------- Co-authored-by: Lewis Carhart <lewis@trycomp.ai>
* feat(vendor): add isSubProcessor field to vendor DTOs and forms * refactor(vendor): update isSubProcessor field layout and tooltip * feat(vendor): add onUpdate callback to SecondaryFields component * feat(trust): move Trust Portal to dedicated sidebar navigation and settings --------- Co-authored-by: Lewis Carhart <lewis@trycomp.ai>
* feat(settings): moved AddSecretDialog to settings header for secrets page to conform with UI pattern * feat(trust): ensure friendlyUrl defaults to organizationId and update status to published --------- Co-authored-by: Lewis Carhart <lewis@trycomp.ai>
…page to conform with UI pattern (#2098) Co-authored-by: Lewis Carhart <lewis@trycomp.ai>
#2100) * feat(cloud-tests): enhance legacy integration filtering and add support for multiple connections * refactor(cloud-tests): improve filtering logic for recent scan results * refactor(cloud-tests): enhance filtering logic for legacy results * refactor(policies): simplify policy header layout and remove PageHeader component
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| status: PolicyStatus.needs_review, | ||
| approverId: dto.approverId, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
API missing check for existing pending version
Medium Severity
The API's submitForApproval method doesn't check if another version is already pending approval before overwriting pendingVersionId. The corresponding app action at submit-version-for-approval.ts lines 42-45 has this validation: if (policy.pendingVersionId && policy.pendingVersionId !== versionId). Without this check in the API, an approver could be reviewing one version while it silently changes to a different version, leading to incorrect approvals.
…creation (#2101) Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
| const response = await fetch(`${apiUrl}/v1/cloud-security/scan/${connectionId}`, { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| 'x-organization-id': orgId, | ||
| }, | ||
| }); |
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix this kind of issue you should validate and constrain any user-controlled values before incorporating them into an outbound request URL. The hostname and protocol should never be derived from user input, and any user-provided path components should be validated against an allow-list of expected patterns and rejected if they do not match.
For this specific case, the best fix with minimal behavioral change is to enforce that connectionId conforms to the expected IntegrationConnection ID format before using it in the URL, and to reject the request if it does not. The JSDoc comment states that the parameter is an "icn_..." ID, so we can validate it against a strict regular expression (for example, ^icn_[A-Za-z0-9]+$). If the value fails validation, we return an error response instead of calling fetch. This keeps existing functionality for legitimate IDs while preventing arbitrary strings from flowing into the URL. The change is localized to runPlatformScan in apps/app/src/app/(app)/[orgId]/cloud-tests/actions/run-platform-scan.ts and does not require new imports; we just add a small validation block near the top of the function, after the existing session/org checks and before constructing or using apiUrl.
Concretely:
- Inside
runPlatformScan, after verifyingorgId(just after line 32 and before thetryblock), add a validation step forconnectionIdusing a regular expression for allowed IDs. - If
connectionIdfails validation, immediately return a structured error object (success: false, error: 'Invalid connection ID') without performing the outboundfetch. - No change is needed to the
fetchcall itself or any imports.
| @@ -31,6 +31,15 @@ | ||
| }; | ||
| } | ||
|
|
||
| // Validate the IntegrationConnection ID format before using it in the request URL | ||
| const isValidConnectionId = /^icn_[A-Za-z0-9]+$/.test(connectionId); | ||
| if (!isValidConnectionId) { | ||
| return { | ||
| success: false, | ||
| error: 'Invalid connection ID', | ||
| }; | ||
| } | ||
|
|
||
| try { | ||
| // Call the cloud security scan API | ||
| const apiUrl = process.env.NEXT_PUBLIC_API_URL || process.env.API_URL; |
|
🎉 This PR is included in version 1.82.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |


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.