fix: add defensive array check for GitLab sync variables response#5902
fix: add defensive array check for GitLab sync variables response#5902devin-ai-integration[bot] wants to merge 2 commits intomainfrom
Conversation
The gitbeaker library's get() helper may return a non-array object when GitLab's API returns an unexpected response (e.g., error object with 200 status, rate-limit response, or self-hosted GitLab variation). The code then calls .filter() on that object, causing the error: 'variables.filter is not a function'. This adds an explicit Array.isArray() check with a descriptive error message before attempting to filter the variables. Co-Authored-By: ashwin <ashwin@infisical.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Greptile SummaryThis PR adds a defensive However, there is one meaningful defect: the new
Confidence Score: 4/5Safe to merge after fixing the double-wrapping defect in the catch block — without the fix, the improved error message is silently swallowed. The change is small and well-intentioned, but the single P1 finding means the primary goal of the PR (surfacing a clear error message) does not work as implemented. The double-wrapping needs to be resolved before merging. backend/src/services/secret-sync/gitlab/gitlab-sync-fns.ts — specifically the catch block of Important Files Changed
Reviews (1): Last reviewed commit: "fix: add defensive array check for GitLa..." | Re-trigger Greptile |
| if (!Array.isArray(variables)) { | ||
| throw new SecretSyncError({ | ||
| error: new Error( | ||
| `Unexpected response from GitLab API when fetching variables: expected an array but received ${typeof variables}` | ||
| ) | ||
| }); | ||
| } |
There was a problem hiding this comment.
New
SecretSyncError gets silently double-wrapped
The Array.isArray() guard is placed inside the try block (lines 75–102). When the check fails and throws a SecretSyncError, it is immediately caught by the catch block at line 103. Since SecretSyncError is not a GitbeakerRequestError, execution falls through to the generic re-wrap on line 111:
throw new SecretSyncError({ error }); // error here is already a SecretSyncErrorThis means the outer SecretSyncError carries an inner SecretSyncError as its error property rather than a plain Error. The descriptive message "expected an array but received …" ends up nested and is unlikely to surface in the final syncMessage, defeating the primary purpose of this fix.
The simplest fix is to re-throw SecretSyncError instances unchanged at the top of the catch block, consistent with what syncSecrets already does:
| if (!Array.isArray(variables)) { | |
| throw new SecretSyncError({ | |
| error: new Error( | |
| `Unexpected response from GitLab API when fetching variables: expected an array but received ${typeof variables}` | |
| ) | |
| }); | |
| } | |
| if (!Array.isArray(variables)) { | |
| throw new SecretSyncError({ | |
| error: new Error( | |
| `Unexpected response from GitLab API when fetching variables: expected an array but received ${typeof variables}` | |
| ) | |
| }); | |
| } |
And in the catch block (around line 103), add:
} catch (error) {
if (error instanceof SecretSyncError) {
throw error;
}
if (error instanceof GitbeakerRequestError) {
// existing handling …
}
throw new SecretSyncError({ error });
}Re-throw SecretSyncError instances unchanged in getGitLabVariables catch block, consistent with the pattern used in syncSecrets. Without this, the descriptive error message from the Array.isArray check gets buried inside a nested SecretSyncError. Co-Authored-By: ashwin <ashwin@infisical.com>
Context
Customers using GitLab secret syncs (created via Terraform) are hitting the error:
The gitbeaker library's
get()helper checksArray.isArray(response.body)internally — when GitLab's API returns a non-array response (e.g., an error object with 200 status, a rate-limit response, or a self-hosted GitLab variation), gitbeaker'sgetSingle()path returns the raw object instead of an array. The code then calls.filter()on that object, producing the cryptic TypeError.This adds an explicit
Array.isArray()guard ingetGitLabVariablesbefore the.filter()call, converting the cryptic TypeError into a descriptiveSecretSyncError.Note: This is a defensive fix that improves the error message. The underlying cause of GitLab returning a non-array response for these specific customers still needs investigation (could be auth/token issues, self-hosted GitLab API differences, or rate limiting).
Important review considerations
disableSecretDeletionis false).SecretSyncErrorinstances unchanged (matching the pattern insyncSecrets) to prevent double-wrapping the descriptive error message..all()+ array methods (e.g.,listGitLabProjects,listGitLabGroupsingitlab-connection-fns.ts) may have the same vulnerability but are not addressed here since they weren't reported as failing.Human review checklist
Array.isArraycheck correctly surfaces a useful error message to the customer (trace throughSecretSyncError→syncMessageserialization path)SecretSyncError→GitbeakerRequestError→ generic) doesn't inadvertently swallow other error typesSteps to verify the change
Array.isArraycheck is placed after the.all()call and before the.filter()calltypeof variables)SecretSyncErrorre-throw in the catch block prevents double-wrappingsyncSecretsType
Checklist
type(scope): short descriptionLink to Devin session: https://app.devin.ai/sessions/e2cd8017aa62491fa2cfa065245d5637