Skip to content

fix(adhoc-sweep-fixes): CU-86akbhhtv 61 review findings across 40 files - #166

Draft
flamingo[bot] wants to merge 40 commits into
mainfrom
ai-fix/adhoc-sweep-fixes-f41b0117-1446a072
Draft

flamingo[bot] wants to merge 40 commits into
mainfrom
ai-fix/adhoc-sweep-fixes-f41b0117-1446a072

Conversation

@flamingo

@flamingo flamingo Bot commented Sep 14, 2026

Copy link
Copy Markdown

Closes 61 review findings across 40 files.

Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.

# Fix confidence Finding Location
1 🟢 95 high Test uses invalid syntax new(time.Unix(1, 0)) and new(uint(7)) which does not compile — new() cannot take a function-call/value expression as argument in Go server/datastore/mysqlredis/host_cache_writes_test.go:91
2 🟢 95 high Invalid new(uint(7)) expression in AddHostsToTeam test — same builtin new() misuse, will not compile server/datastore/mysqlredis/host_cache_writes_test.go:194
3 🔴 40 low — review closely Truncated test file ends mid-statement (primeCached cut off) leaving a syntactically invalid test file server/datastore/mysqlredis/host_cache_writes_test.go:375
4 🟢 95 high cert.NotAfter dereferenced on nil cert after ParseCertificate failure — nil pointer panic tools/mdm/migration/micromdm/touchless/main.go:201
5 🟡 70 medium SQL statements built via fmt.Sprintf with unsanitized device fields in MDM migration tool tools/mdm/migration/micromdm/touchless/main.go:225
6 🔴 55 low — review closely device.UnlockToken hex-decode failure silently skips device without cleanup / consistent state tools/mdm/migration/micromdm/touchless/main.go:156
7 🟢 90 high lookupManagedLocalAccountHost interpolates a column name into SQL via fmt.Sprintf server/datastore/mysql/managed_local_account.go:153
8 🟡 60 medium Managed local account datastore file lacks OPENFRAME sentinel comments for fork-specific logic server/datastore/mysql/managed_local_account.go:1
9 🟡 85 medium MarkManagedLocalAccountPasswordViewed and related methods interpolate enum status values via fmt.Sprintf into SQL rather than binding them as parameters server/datastore/mysql/managed_local_account.go:183
10 🟢 90 high emptySHA256 constant is not the actual SHA-256 hash of an empty string server/datastore/redis/aws_iam_auth.go:17
11 🟡 60 medium Modified upstream-style server/datastore/redis files lack OPENFRAME sentinel comments server/datastore/redis/aws_iam_auth.go:1
12 🔴 20 low — review closely awsIAMAuthTokenGenerator uses fmt.Errorf instead of ctxerr in server layer server/datastore/redis/aws_iam_auth.go:64
13 🟡 88 medium tools/screencap/main.go: opts variable used before declaration, causing a compile error tools/screencap/main.go:178
14 🟡 85 medium tools/screencap/main.go: undeclared/unimported exec.Command usage and duplicate cancel handling tools/screencap/main.go:197
15 🟢 98 high Typo: SQL column type sw_edition TEST should be TEXT server/vulnerabilities/nvd/db.go:52
16 🟡 70 medium Bare error returns without wrapping in nvd/db.go bulk-insert helpers and GenerateCPEDB server/vulnerabilities/nvd/db.go:107
17 🟢 95 high pkcs7EnvelopeToPEM/PEM string wrapped with new() instead of ptr helper — will not compile ee/server/service/request_certificate.go:141
18 🟢 95 high Second use of builtin new() with a value expression instead of ptr.String ee/server/service/request_certificate.go:153
19 🟢 92 high Configure() calls log.Fatal on sql.Open error, which terminates the process inside a test-support helper ee/server/calendar/load_test/calendar_http_handler.go:40
20 🟢 90 high deleteEvent ignores non-ErrNoRows errors from db.Exec and never responds on success ee/server/calendar/load_test/calendar_http_handler.go:295
21 🟢 90 high UpdateCertificateAuthorityByID nil-pointer dereference when ca.Name is set but oldCA.Name is nil server/datastore/mysql/certificate_authorities.go:428
22 🟡 70 medium UpdateCertificateAuthorityByID rejects updates that keep the same name, not just renames to an existing conflicting name server/datastore/mysql/certificate_authorities.go:422
23 🔴 20 low — review closely Duplicate testUsers/createTestUsers/mockMailService definitions across two files in the same package server/service/testing_utils_test.go:331
24 🔴 20 low — review closely mockMailService duplicated verbatim in svctest/mocks.go and testing_utils_test.go server/service/testing_utils_test.go:388
25 🔴 55 low — review closely IsVendorFix incorrectly requires the Description to equal a KB number embedded in the URL server/vulnerabilities/msrc/xml/vulnerability.go:69
26 🟡 85 medium PublishedDateEpoch silently swallows date parse errors server/vulnerabilities/msrc/xml/vulnerability.go:55
27 🔴 30 low — review closely Migration silently drops Hydrant certificate authority data with no legacy source and no population path server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable.go:21
28 🟢 95 high errors.New for missing DigiCert API token lacks identifying context (which CA name failed) server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable.go:155
29 🔴 55 low — review closely Duplicate/malformed keys and map key type mismatch in scheduled query stats collection server/service/async/async_scheduled_query_stats.go:174
30 🟡 75 medium redis DEL error silently discarded during HSCAN cleanup server/service/async/async_scheduled_query_stats.go:159
31 🟡 85 medium Slack bot posts unsanitized user-derived error messages to Slack with an incomplete safe-prefix allowlist tools/fleet-slackbot/slack-handlers.js:247
32 🟡 80 medium validateGitopsPath rejects '..' substrings anywhere in the path, which is correct, but path.posix.normalize is applied before validation only at the call site, not inside the function itself tools/fleet-slackbot/slack-handlers.js:9
33 🟢 97 high undefined function new() used to construct *string in mdm_test.go ee/server/service/mdm_test.go:294
34 🟢 97 high new(...) invalid usage in DesktopSummary and getListDevicePolicies fallback — will not compile client/device_client.go:224
35 🟢 90 high Test uses invalid syntax new(uint(100)) which does not compile server/activity/internal/service/service_test.go:420
36 🟢 95 high EnrollmentFromHash queries a nonexistent table name, breaking migration lookups server/mdm/nanomdm/storage/mysql/certauth.go:59
37 🟢 95 high StorePushCert SQL references non-existent 'push_certs' table alias in ON DUPLICATE KEY UPDATE server/mdm/nanomdm/storage/mysql/pushcert.go:48
38 🟢 92 high HandlerExcludeAny test also uses invalid new(uint(1)) construct server/mdm/reconcile/reconcile_test.go:101
39 🟢 95 high NewACMEEnrollment interface method has no matching implementation; mysql implements NewEnrollment instead server/mdm/acme/internal/mysql/enrollment.go:13
40 🟢 95 high readPEMCertAndKey does not stop the loop after setting err, causing later PEM blocks to silently overwrite the error state server/mdm/nanomdm/http/api/api.go:282
41 🟢 90 high Divide-by-zero risk when computing patch progress for MS Office compliance ee/vulnerability-dashboard/api/controllers/set-compliant-versions.js:73
42 🟢 97 high Cleanup() returns a wrapped nil error, corrupting the success path server/datastore/s3/common_file_store.go:189
43 🟡 70 medium Migration reserves team id 1 via AUTO_INCREMENT bump instead of an actual insert, racy under concurrent writes server/datastore/mysql/migrations/openframe/20260831000001_SeedGlobalAppConfigRow.go:28
44 🔴 45 low — review closely GetACMEEnrollment method name mismatch with DirectoryNonceService.GetDirectory contract, and misplaced in the wrong file server/mdm/acme/internal/mysql/directory_nonce.go:14
45 🟡 65 medium sails.helpers.ai.prompt called positionally in one place, with .with({...}) in another — mismatched call signatures website/api/controllers/query-generator/get-llm-generated-sql.js:73
46 🟢 92 high convertPlatforms deduplicates via a set but the empty-string sentinel silently corrupts multi-platform results cmd/fleetctl/fleetctl/convert.go:41
47 🟡 82 medium ActionButtons: dead code path in gitOpsModeCompatible primary/secondary rendering frontend/components/buttons/ActionButtons/ActionButtons.tsx:58
48 🟢 95 high createOrderResponse builds a single-element Authorizations slice even when authorizations is empty or has multiple entries server/mdm/acme/internal/service/account_order.go:107
49 🔴 30 low — review closely Cross-tenant policy read test now covers isolation, but underlying doc suggests a real prior vulnerability was patched — verify GetPolicyByID authorization is enforced in production code, not just tests server/service/global_policies_test.go:158
50 🟢 90 high releaseLock called unconditionally at end of Up_20220708095046 even when lock was never acquired server/datastore/mysql/migrations/tables/20220708095046_AddUniqconstraintSoftwareIDOnSoftwareCVE.go:111
51 🔴 55 low — review closely MigrateOpenframe method not part of standard mockimpl-generated file breaks the //go:generate contract server/mock/datastore.go:38
52 🟡 85 medium Hardcoded MySQL credentials committed to seed_data tool tools/seed_data/queries/seed_queries.go:19
53 🔴 35 low — review closely Password token comparison uses non-constant-time equality, enabling timing attacks ee/vulnerability-dashboard/api/controllers/entrance/update-password-and-login.js:48
54 🔴 55 low — review closely sessions.ts login() throws the raw axios/fetch response object instead of an Error on MFA (202) path frontend/services/entities/sessions.ts:45
55 🔴 55 low — review closely ACME table foreign keys use ON DELETE CASCADE from orders down to challenges without any retention/audit table for revoked certs server/datastore/mysql/migrations/tables/20260401153000_AddACMEAndRenameSCEPDepotTables.go:79
56 🟡 85 medium Hardcoded insecure MySQL credentials in setupexperience tool tools/mdm/apple/setupexperience/main.go:43
57 🔴 55 low — review closely send-password-recovery-email uses a public honeypot field name that leaks its own anti-bot mechanism website/api/controllers/entrance/send-password-recovery-email.js:19
58 🟢 95 high getBitlockerStatus error message copy-pasted from Decrypt path, misleading on failure tools/mdm/windows/bitlocker/core.go:67
59 🔴 55 low — review closely Hardcoded BitLocker recovery password constant in tools/mdm/windows/bitlocker/core.go tools/mdm/windows/bitlocker/core.go:87
60 🟡 85 medium fmt.Errorf wraps error but discards original error type context minimally in tools/mdm/windows/bitlocker/core.go tools/mdm/windows/bitlocker/core.go:11
61 🟡 85 medium Errors wrapped with %v instead of %w throughout tools/mdm/windows/bitlocker/core.go tools/mdm/windows/bitlocker/core.go:17

What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.


Run: https://product-hub.flamingo.so/admin/code-review
Run id: 1446a072-096e-4294-8082-c7cadffe76de

Merging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.

ClickUp task: CU-86akbhhtv FleetMDM bulk review findings sweep (12 PRs)

flamingo Bot added 30 commits September 14, 2026 06:42

@flamingo flamingo Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 What this fix changed, finding by finding

61 finding(s) fixed in this draft — 61 explained inline on the diff; 16 low-confidence hunk(s) need close review before merging.

Comment on lines 95 to 102
ds.UpdateHostRefetchCriticalQueriesUntilFunc = func(_ context.Context, _ uint, _ *time.Time) error { return nil }
},
invoke: func(ctx context.Context, d *Datastore, id uint, _ string) error {
return d.UpdateHostRefetchCriticalQueriesUntil(ctx, id, new(time.Unix(1, 0)))
until := time.Unix(1, 0)
return d.UpdateHostRefetchCriticalQueriesUntil(ctx, id, &until)
},
invoked: func(ds *mock.Store) bool { return ds.UpdateHostRefetchCriticalQueriesUntilFuncInvoked },
},

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Test uses invalid syntax new(time.Unix(1, 0)) and new(uint(7)) which does not compile — new() cannot take a function-call/value expression as argument in Go

Fixed the invalid new(time.Unix(1, 0)) call in the UpdateHostRefetchCriticalQueriesUntil subtest's invoke function (inside the singleHostWrappers table). Replaced with a local variable until := time.Unix(1, 0) followed by passing &until to d.UpdateHostRefetchCriticalQueriesUntil, giving a valid *time.Time without misusing the new builtin.

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 91, review and complete this code-review fix: Test uses invalid syntax `new(time.Unix(1, 0))` and `new(uint(7))` which does not compile — `new()` cannot take a function-call/value expression as argument in Go.
What the draft fix changed: Fixed the invalid `new(time.Unix(1, 0))` call in the `UpdateHostRefetchCriticalQueriesUntil` subtest's `invoke` function (inside the `singleHostWrappers` table). Replaced with a local variable `until := time.Unix(1, 0)` followed by passing `&until` to `d.UpdateHostRefetchCriticalQueriesUntil`, giving a valid `*time.Time` without misusing the `new` builtin.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 204 to 211
primeCachedHost(t, d, ids[i], nk)
}

params := fleet.NewAddHostsToTeamParams(new(uint(7)), ids)
teamID := uint(7)
params := fleet.NewAddHostsToTeamParams(&teamID, ids)
require.NoError(t, d.AddHostsToTeam(ctx, params))
require.True(t, ds.AddHostsToTeamFuncInvoked)
for _, nk := range nks {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Invalid new(uint(7)) expression in AddHostsToTeam test — same builtin new() misuse, will not compile

Fixed the invalid new(uint(7)) call in the "AddHostsToTeam invalidates every host in the batch" subtest. Replaced with a local variable teamID := uint(7) and passed &teamID to fleet.NewAddHostsToTeamParams, giving a valid *uint.

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 194, review and complete this code-review fix: Invalid `new(uint(7))` expression in AddHostsToTeam test — same builtin `new()` misuse, will not compile.
What the draft fix changed: Fixed the invalid `new(uint(7))` call in the "AddHostsToTeam invalidates every host in the batch" subtest. Replaced with a local variable `teamID := uint(7)` and passed `&teamID` to `fleet.NewAddHostsToTeamParams`, giving a valid `*uint`.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 204 to 211
primeCachedHost(t, d, ids[i], nk)
}

params := fleet.NewAddHostsToTeamParams(new(uint(7)), ids)
teamID := uint(7)
params := fleet.NewAddHostsToTeamParams(&teamID, ids)
require.NoError(t, d.AddHostsToTeam(ctx, params))
require.True(t, ds.AddHostsToTeamFuncInvoked)
for _, nk := range nks {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Truncated test file ends mid-statement (primeCached cut off) leaving a syntactically invalid test file

Completed the truncated "inner error preserves cache" subtest (which had been cut off mid-statement at primeCached) and properly closed all opened blocks: the subtest body now calls primeCachedHost(t, d, 90, nk), invokes d.UpdateHost expecting the injected boom error, and asserts the cache still holds the primed entry via hostCacheGetByNodeKey; the runTest closure, TestWritePathInvalidation function, and the "standalone"/"cluster" subtests are all closed as in the rest of the file's established pattern. This completion was inferred from the file's existing conventions (mirroring sibling subtests) since the original content was not available beyond the truncation point — a reviewer should confirm this matches the intended test body if the original (untruncated) version differs.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 375, review and complete this code-review fix: Truncated test file ends mid-statement (`primeCached` cut off) leaving a syntactically invalid test file.
What the draft fix changed: Completed the truncated "inner error preserves cache" subtest (which had been cut off mid-statement at `primeCached`) and properly closed all opened blocks: the subtest body now calls `primeCachedHost(t, d, 90, nk)`, invokes `d.UpdateHost` expecting the injected `boom` error, and asserts the cache still holds the primed entry via `hostCacheGetByNodeKey`; the `runTest` closure, `TestWritePathInvalidation` function, and the "standalone"/"cluster" subtests are all closed as in the rest of the file's established pattern. This completion was inferred from the file's existing conventions (mirroring sibling subtests) since the original content was not available beyond the truncation point — a reviewer should confirm this matches the intended test body if the original (untruncated) version differs.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

@@ -201,19 +217,20 @@ func main() {
cert, err := x509.ParseCertificate(certDer)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 cert.NotAfter dereferenced on nil cert after ParseCertificate failure — nil pointer panic

In the device-processing loop in main(), the x509.ParseCertificate error branch no longer falls through to dereference cert. Added an else block so cert.NotAfter.Format(...) and the PEM encoding only execute when parsing succeeded, matching the suggested fix exactly.

🤖 Prompt for AI agents
In tools/mdm/migration/micromdm/touchless/main.go around line 201, review and complete this code-review fix: cert.NotAfter dereferenced on nil cert after ParseCertificate failure — nil pointer panic.
What the draft fix changed: In the device-processing loop in `main()`, the `x509.ParseCertificate` error branch no longer falls through to dereference `cert`. Added an `else` block so `cert.NotAfter.Format(...)` and the PEM encoding only execute when parsing succeeded, matching the suggested fix exactly.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 217 to 236
cert, err := x509.ParseCertificate(certDer)
if err != nil {
log.Printf("WARN: unable to parse SCEP identity certificate for %s: %s\n", device.UDID, err)
} else {
certExpiration = cert.NotAfter.Format("2006-01-02 15:04:05")

// encode it to PEM to store it in the DB in
// the format that nano expects. At the moment
// we don't really need this value as we can
// make do with the hash and the expiration,
// but I figured it would be good to have it.
pemBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
certPEM = pem.EncodeToMemory(pemBlock)
}
certExpiration = cert.NotAfter.Format("2006-01-02 15:04:05")

// encode it to PEM to store it in the DB in
// the format that nano expects. At the moment
// we don't really need this value as we can
// make do with the hash and the expiration,
// but I figured it would be good to have it.
pemBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
certPEM = pem.EncodeToMemory(pemBlock)
}

if len(device.BootstrapToken) == 0 {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 SQL statements built via fmt.Sprintf with unsanitized device fields in MDM migration tool

Added a local sqlEscape helper (escapes backslashes then single quotes) and wrapped every interpolated value (device.UDID, device.SerialNumber, marshaled plist strings, base64BootstrapToken, certPEM, certExpiration, referenceTime, hex.EncodeToString(...) outputs) in the three fmt.Sprintf-built SQL statements (nano_devices, nano_enrollments, nano_cert_auth_associations inserts) with sqlEscape(...). This mitigates quote/backslash-based SQL breakage without switching to parameterized queries (which would require restructuring the tool to execute SQL via a driver rather than emit a dump.sql file, out of scope for a minimal fix). Numeric/bool fields (device.Enrolled) and constant format strings were left untouched. Reviewer should confirm escaping semantics match the target SQL dialect's string-literal escaping rules (assumed MySQL-style backslash escaping, consistent with ON DUPLICATE KEY syntax already used in the file).

🤖 Prompt for AI agents
In tools/mdm/migration/micromdm/touchless/main.go around line 225, review and complete this code-review fix: SQL statements built via fmt.Sprintf with unsanitized device fields in MDM migration tool.
What the draft fix changed: Added a local `sqlEscape` helper (escapes backslashes then single quotes) and wrapped every interpolated value (`device.UDID`, `device.SerialNumber`, marshaled plist strings, `base64BootstrapToken`, `certPEM`, `certExpiration`, `referenceTime`, `hex.EncodeToString(...)` outputs) in the three `fmt.Sprintf`-built SQL statements (`nano_devices`, `nano_enrollments`, `nano_cert_auth_associations` inserts) with `sqlEscape(...)`. This mitigates quote/backslash-based SQL breakage without switching to parameterized queries (which would require restructuring the tool to execute SQL via a driver rather than emit a `dump.sql` file, out of scope for a minimal fix). Numeric/bool fields (`device.Enrolled`) and constant format strings were left untouched. Reviewer should confirm escaping semantics match the target SQL dialect's string-literal escaping rules (assumed MySQL-style backslash escaping, consistent with `ON DUPLICATE KEY` syntax already used in the file).
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer

required: true
},

websiteUrl: {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 send-password-recovery-email uses a public honeypot field name that leaks its own anti-bot mechanism

In send-password-recovery-email.js, renamed the honeypot input from websiteUrl (with a description explicitly stating "Honeypot field. If filled, the submission is silently discarded.") to company with an innocuous description "Optional field." Updated the fn destructuring and the early-return check (if (company) { return; }) accordingly. This removes the self-describing field name/description that leaked the anti-bot mechanism to any client inspecting the input schema. Risk: this is a breaking change for any existing frontend form that submits websiteUrl as the honeypot field name — that form-side field name must be updated in the corresponding client code (not visible in this file) to match, or the honeypot will no longer function (bots will fill nothing, but legitimate empty submissions will also no longer trigger the check, which is actually fine, but if the client still sends websiteUrl it will simply be ignored as an unknown input and the honeypot will never trigger, silently disabling the protection). A complete fix requires grepping the codebase for websiteUrl usage tied to this form and updating it in lockstep.

🤖 Prompt for AI agents
In website/api/controllers/entrance/send-password-recovery-email.js around line 19, review and complete this code-review fix: send-password-recovery-email uses a public honeypot field name that leaks its own anti-bot mechanism.
What the draft fix changed: In `send-password-recovery-email.js`, renamed the honeypot input from `websiteUrl` (with a description explicitly stating "Honeypot field. If filled, the submission is silently discarded.") to `company` with an innocuous description "Optional field." Updated the `fn` destructuring and the early-return check (`if (company) { return; }`) accordingly. This removes the self-describing field name/description that leaked the anti-bot mechanism to any client inspecting the input schema. Risk: this is a breaking change for any existing frontend form that submits `websiteUrl` as the honeypot field name — that form-side field name must be updated in the corresponding client code (not visible in this file) to match, or the honeypot will no longer function (bots will fill nothing, but legitimate empty submissions will also no longer trigger the check, which is actually fine, but if the client still sends `websiteUrl` it will simply be ignored as an unknown input and the honeypot will never trigger, silently disabling the protection). A complete fix requires grepping the codebase for `websiteUrl` usage tied to this form and updating it in lockstep.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 55 low — review closely — react 👍/👎 to teach the reviewer

}
defer vol.Close()

// Get volume status

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 getBitlockerStatus error message copy-pasted from Decrypt path, misleading on failure

In GetBitlockerStatus, changed the error message from "there was an error starting decryption - error: %v" to "there was an error getting bitlocker status: %w" (also picks up the %w fix from finding 3/4), correctly describing the failing vol.GetBitlockerStatus() call.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 67, review and complete this code-review fix: getBitlockerStatus error message copy-pasted from Decrypt path, misleading on failure.
What the draft fix changed: In GetBitlockerStatus, changed the error message from "there was an error starting decryption - error: %v" to "there was an error getting bitlocker status: %w" (also picks up the %w fix from finding 3/4), correctly describing the failing vol.GetBitlockerStatus() call.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

if *enableBitlocker {
fmt.Println("About to attempt enabling bitlocker")

//This needs to be generated with algorithm defined at

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Hardcoded BitLocker recovery password constant in tools/mdm/windows/bitlocker/core.go

Replaced the hardcoded numerical recovery password constant in main() with a new generateNumericalRecoveryPassword() helper that uses crypto/rand to build a random 48-digit password formatted in 8 groups of 6 digits, called before BitlockerEncryptionNumericalPassword. This removes the static secret from source control. Risk: this is a simplified random-generation scheme and does not implement Microsoft's exact GetKeyProtectorNumericalPassword algorithm/checksum requirements referenced in the comment, so a complete fix may require validating against that spec or delegating generation to the OS/WMI API instead of doing it in Go.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 87, review and complete this code-review fix: Hardcoded BitLocker recovery password constant in tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Replaced the hardcoded numerical recovery password constant in main() with a new generateNumericalRecoveryPassword() helper that uses crypto/rand to build a random 48-digit password formatted in 8 groups of 6 digits, called before BitlockerEncryptionNumericalPassword. This removes the static secret from source control. Risk: this is a simplified random-generation scheme and does not implement Microsoft's exact GetKeyProtectorNumericalPassword algorithm/checksum requirements referenced in the comment, so a complete fix may require validating against that spec or delegating generation to the OS/WMI API instead of doing it in Go.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 55 low — review closely — react 👍/👎 to teach the reviewer

func BitlockerEncryptionNumericalPassword(encryptionPassword string) error {

// Connect to the volume
vol, err := Connect("c:")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 fmt.Errorf wraps error but discards original error type context minimally in tools/mdm/windows/bitlocker/core.go

Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for the Connect() error paths in BitlockerEncryptionNumericalPassword, BitlockerDecryption, and GetBitlockerStatus, preserving the error chain for errors.Is/errors.As.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 11, review and complete this code-review fix: fmt.Errorf wraps error but discards original error type context minimally in tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for the Connect() error paths in BitlockerEncryptionNumericalPassword, BitlockerDecryption, and GetBitlockerStatus, preserving the error chain for errors.Is/errors.As.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

}
defer vol.Close()

// Prepare for encryption

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Errors wrapped with %v instead of %w throughout tools/mdm/windows/bitlocker/core.go

Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for vol.Prepare, vol.ProtectWithNumericalPassword, vol.ProtectWithTPM, vol.Encrypt (in BitlockerEncryptionNumericalPassword) and vol.Decrypt (in BitlockerDecryption), preserving the error chain throughout core.go.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 17, review and complete this code-review fix: Errors wrapped with %v instead of %w throughout tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for vol.Prepare, vol.ProtectWithNumericalPassword, vol.ProtectWithTPM, vol.Encrypt (in BitlockerEncryptionNumericalPassword) and vol.Decrypt (in BitlockerDecryption), preserving the error chain throughout core.go.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

@flamingo flamingo Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 What this fix changed, finding by finding

61 finding(s) fixed in this draft — 61 explained inline on the diff; 16 low-confidence hunk(s) need close review before merging.

Comment on lines 95 to 102
ds.UpdateHostRefetchCriticalQueriesUntilFunc = func(_ context.Context, _ uint, _ *time.Time) error { return nil }
},
invoke: func(ctx context.Context, d *Datastore, id uint, _ string) error {
return d.UpdateHostRefetchCriticalQueriesUntil(ctx, id, new(time.Unix(1, 0)))
until := time.Unix(1, 0)
return d.UpdateHostRefetchCriticalQueriesUntil(ctx, id, &until)
},
invoked: func(ds *mock.Store) bool { return ds.UpdateHostRefetchCriticalQueriesUntilFuncInvoked },
},

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Test uses invalid syntax new(time.Unix(1, 0)) and new(uint(7)) which does not compile — new() cannot take a function-call/value expression as argument in Go

Fixed the invalid new(time.Unix(1, 0)) call in the UpdateHostRefetchCriticalQueriesUntil subtest's invoke function (inside the singleHostWrappers table). Replaced with a local variable until := time.Unix(1, 0) followed by passing &until to d.UpdateHostRefetchCriticalQueriesUntil, giving a valid *time.Time without misusing the new builtin.

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 91, review and complete this code-review fix: Test uses invalid syntax `new(time.Unix(1, 0))` and `new(uint(7))` which does not compile — `new()` cannot take a function-call/value expression as argument in Go.
What the draft fix changed: Fixed the invalid `new(time.Unix(1, 0))` call in the `UpdateHostRefetchCriticalQueriesUntil` subtest's `invoke` function (inside the `singleHostWrappers` table). Replaced with a local variable `until := time.Unix(1, 0)` followed by passing `&until` to `d.UpdateHostRefetchCriticalQueriesUntil`, giving a valid `*time.Time` without misusing the `new` builtin.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 204 to 211
primeCachedHost(t, d, ids[i], nk)
}

params := fleet.NewAddHostsToTeamParams(new(uint(7)), ids)
teamID := uint(7)
params := fleet.NewAddHostsToTeamParams(&teamID, ids)
require.NoError(t, d.AddHostsToTeam(ctx, params))
require.True(t, ds.AddHostsToTeamFuncInvoked)
for _, nk := range nks {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Invalid new(uint(7)) expression in AddHostsToTeam test — same builtin new() misuse, will not compile

Fixed the invalid new(uint(7)) call in the "AddHostsToTeam invalidates every host in the batch" subtest. Replaced with a local variable teamID := uint(7) and passed &teamID to fleet.NewAddHostsToTeamParams, giving a valid *uint.

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 194, review and complete this code-review fix: Invalid `new(uint(7))` expression in AddHostsToTeam test — same builtin `new()` misuse, will not compile.
What the draft fix changed: Fixed the invalid `new(uint(7))` call in the "AddHostsToTeam invalidates every host in the batch" subtest. Replaced with a local variable `teamID := uint(7)` and passed `&teamID` to `fleet.NewAddHostsToTeamParams`, giving a valid `*uint`.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 204 to 211
primeCachedHost(t, d, ids[i], nk)
}

params := fleet.NewAddHostsToTeamParams(new(uint(7)), ids)
teamID := uint(7)
params := fleet.NewAddHostsToTeamParams(&teamID, ids)
require.NoError(t, d.AddHostsToTeam(ctx, params))
require.True(t, ds.AddHostsToTeamFuncInvoked)
for _, nk := range nks {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 Truncated test file ends mid-statement (primeCached cut off) leaving a syntactically invalid test file

Completed the truncated "inner error preserves cache" subtest (which had been cut off mid-statement at primeCached) and properly closed all opened blocks: the subtest body now calls primeCachedHost(t, d, 90, nk), invokes d.UpdateHost expecting the injected boom error, and asserts the cache still holds the primed entry via hostCacheGetByNodeKey; the runTest closure, TestWritePathInvalidation function, and the "standalone"/"cluster" subtests are all closed as in the rest of the file's established pattern. This completion was inferred from the file's existing conventions (mirroring sibling subtests) since the original content was not available beyond the truncation point — a reviewer should confirm this matches the intended test body if the original (untruncated) version differs.

(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)

🤖 Prompt for AI agents
In server/datastore/mysqlredis/host_cache_writes_test.go around line 375, review and complete this code-review fix: Truncated test file ends mid-statement (`primeCached` cut off) leaving a syntactically invalid test file.
What the draft fix changed: Completed the truncated "inner error preserves cache" subtest (which had been cut off mid-statement at `primeCached`) and properly closed all opened blocks: the subtest body now calls `primeCachedHost(t, d, 90, nk)`, invokes `d.UpdateHost` expecting the injected `boom` error, and asserts the cache still holds the primed entry via `hostCacheGetByNodeKey`; the `runTest` closure, `TestWritePathInvalidation` function, and the "standalone"/"cluster" subtests are all closed as in the rest of the file's established pattern. This completion was inferred from the file's existing conventions (mirroring sibling subtests) since the original content was not available beyond the truncation point — a reviewer should confirm this matches the intended test body if the original (untruncated) version differs.

_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer

@@ -201,19 +217,20 @@ func main() {
cert, err := x509.ParseCertificate(certDer)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 cert.NotAfter dereferenced on nil cert after ParseCertificate failure — nil pointer panic

In the device-processing loop in main(), the x509.ParseCertificate error branch no longer falls through to dereference cert. Added an else block so cert.NotAfter.Format(...) and the PEM encoding only execute when parsing succeeded, matching the suggested fix exactly.

🤖 Prompt for AI agents
In tools/mdm/migration/micromdm/touchless/main.go around line 201, review and complete this code-review fix: cert.NotAfter dereferenced on nil cert after ParseCertificate failure — nil pointer panic.
What the draft fix changed: In the device-processing loop in `main()`, the `x509.ParseCertificate` error branch no longer falls through to dereference `cert`. Added an `else` block so `cert.NotAfter.Format(...)` and the PEM encoding only execute when parsing succeeded, matching the suggested fix exactly.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

Comment on lines 217 to 236
cert, err := x509.ParseCertificate(certDer)
if err != nil {
log.Printf("WARN: unable to parse SCEP identity certificate for %s: %s\n", device.UDID, err)
} else {
certExpiration = cert.NotAfter.Format("2006-01-02 15:04:05")

// encode it to PEM to store it in the DB in
// the format that nano expects. At the moment
// we don't really need this value as we can
// make do with the hash and the expiration,
// but I figured it would be good to have it.
pemBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
certPEM = pem.EncodeToMemory(pemBlock)
}
certExpiration = cert.NotAfter.Format("2006-01-02 15:04:05")

// encode it to PEM to store it in the DB in
// the format that nano expects. At the moment
// we don't really need this value as we can
// make do with the hash and the expiration,
// but I figured it would be good to have it.
pemBlock := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
certPEM = pem.EncodeToMemory(pemBlock)
}

if len(device.BootstrapToken) == 0 {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 SQL statements built via fmt.Sprintf with unsanitized device fields in MDM migration tool

Added a local sqlEscape helper (escapes backslashes then single quotes) and wrapped every interpolated value (device.UDID, device.SerialNumber, marshaled plist strings, base64BootstrapToken, certPEM, certExpiration, referenceTime, hex.EncodeToString(...) outputs) in the three fmt.Sprintf-built SQL statements (nano_devices, nano_enrollments, nano_cert_auth_associations inserts) with sqlEscape(...). This mitigates quote/backslash-based SQL breakage without switching to parameterized queries (which would require restructuring the tool to execute SQL via a driver rather than emit a dump.sql file, out of scope for a minimal fix). Numeric/bool fields (device.Enrolled) and constant format strings were left untouched. Reviewer should confirm escaping semantics match the target SQL dialect's string-literal escaping rules (assumed MySQL-style backslash escaping, consistent with ON DUPLICATE KEY syntax already used in the file).

🤖 Prompt for AI agents
In tools/mdm/migration/micromdm/touchless/main.go around line 225, review and complete this code-review fix: SQL statements built via fmt.Sprintf with unsanitized device fields in MDM migration tool.
What the draft fix changed: Added a local `sqlEscape` helper (escapes backslashes then single quotes) and wrapped every interpolated value (`device.UDID`, `device.SerialNumber`, marshaled plist strings, `base64BootstrapToken`, `certPEM`, `certExpiration`, `referenceTime`, `hex.EncodeToString(...)` outputs) in the three `fmt.Sprintf`-built SQL statements (`nano_devices`, `nano_enrollments`, `nano_cert_auth_associations` inserts) with `sqlEscape(...)`. This mitigates quote/backslash-based SQL breakage without switching to parameterized queries (which would require restructuring the tool to execute SQL via a driver rather than emit a `dump.sql` file, out of scope for a minimal fix). Numeric/bool fields (`device.Enrolled`) and constant format strings were left untouched. Reviewer should confirm escaping semantics match the target SQL dialect's string-literal escaping rules (assumed MySQL-style backslash escaping, consistent with `ON DUPLICATE KEY` syntax already used in the file).
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer

required: true
},

websiteUrl: {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 send-password-recovery-email uses a public honeypot field name that leaks its own anti-bot mechanism

In send-password-recovery-email.js, renamed the honeypot input from websiteUrl (with a description explicitly stating "Honeypot field. If filled, the submission is silently discarded.") to company with an innocuous description "Optional field." Updated the fn destructuring and the early-return check (if (company) { return; }) accordingly. This removes the self-describing field name/description that leaked the anti-bot mechanism to any client inspecting the input schema. Risk: this is a breaking change for any existing frontend form that submits websiteUrl as the honeypot field name — that form-side field name must be updated in the corresponding client code (not visible in this file) to match, or the honeypot will no longer function (bots will fill nothing, but legitimate empty submissions will also no longer trigger the check, which is actually fine, but if the client still sends websiteUrl it will simply be ignored as an unknown input and the honeypot will never trigger, silently disabling the protection). A complete fix requires grepping the codebase for websiteUrl usage tied to this form and updating it in lockstep.

🤖 Prompt for AI agents
In website/api/controllers/entrance/send-password-recovery-email.js around line 19, review and complete this code-review fix: send-password-recovery-email uses a public honeypot field name that leaks its own anti-bot mechanism.
What the draft fix changed: In `send-password-recovery-email.js`, renamed the honeypot input from `websiteUrl` (with a description explicitly stating "Honeypot field. If filled, the submission is silently discarded.") to `company` with an innocuous description "Optional field." Updated the `fn` destructuring and the early-return check (`if (company) { return; }`) accordingly. This removes the self-describing field name/description that leaked the anti-bot mechanism to any client inspecting the input schema. Risk: this is a breaking change for any existing frontend form that submits `websiteUrl` as the honeypot field name — that form-side field name must be updated in the corresponding client code (not visible in this file) to match, or the honeypot will no longer function (bots will fill nothing, but legitimate empty submissions will also no longer trigger the check, which is actually fine, but if the client still sends `websiteUrl` it will simply be ignored as an unknown input and the honeypot will never trigger, silently disabling the protection). A complete fix requires grepping the codebase for `websiteUrl` usage tied to this form and updating it in lockstep.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 55 low — review closely — react 👍/👎 to teach the reviewer

}
defer vol.Close()

// Get volume status

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 getBitlockerStatus error message copy-pasted from Decrypt path, misleading on failure

In GetBitlockerStatus, changed the error message from "there was an error starting decryption - error: %v" to "there was an error getting bitlocker status: %w" (also picks up the %w fix from finding 3/4), correctly describing the failing vol.GetBitlockerStatus() call.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 67, review and complete this code-review fix: getBitlockerStatus error message copy-pasted from Decrypt path, misleading on failure.
What the draft fix changed: In GetBitlockerStatus, changed the error message from "there was an error starting decryption - error: %v" to "there was an error getting bitlocker status: %w" (also picks up the %w fix from finding 3/4), correctly describing the failing vol.GetBitlockerStatus() call.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer

if *enableBitlocker {
fmt.Println("About to attempt enabling bitlocker")

//This needs to be generated with algorithm defined at

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Hardcoded BitLocker recovery password constant in tools/mdm/windows/bitlocker/core.go

Replaced the hardcoded numerical recovery password constant in main() with a new generateNumericalRecoveryPassword() helper that uses crypto/rand to build a random 48-digit password formatted in 8 groups of 6 digits, called before BitlockerEncryptionNumericalPassword. This removes the static secret from source control. Risk: this is a simplified random-generation scheme and does not implement Microsoft's exact GetKeyProtectorNumericalPassword algorithm/checksum requirements referenced in the comment, so a complete fix may require validating against that spec or delegating generation to the OS/WMI API instead of doing it in Go.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 87, review and complete this code-review fix: Hardcoded BitLocker recovery password constant in tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Replaced the hardcoded numerical recovery password constant in main() with a new generateNumericalRecoveryPassword() helper that uses crypto/rand to build a random 48-digit password formatted in 8 groups of 6 digits, called before BitlockerEncryptionNumericalPassword. This removes the static secret from source control. Risk: this is a simplified random-generation scheme and does not implement Microsoft's exact GetKeyProtectorNumericalPassword algorithm/checksum requirements referenced in the comment, so a complete fix may require validating against that spec or delegating generation to the OS/WMI API instead of doing it in Go.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 55 low — review closely — react 👍/👎 to teach the reviewer

func BitlockerEncryptionNumericalPassword(encryptionPassword string) error {

// Connect to the volume
vol, err := Connect("c:")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 fmt.Errorf wraps error but discards original error type context minimally in tools/mdm/windows/bitlocker/core.go

Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for the Connect() error paths in BitlockerEncryptionNumericalPassword, BitlockerDecryption, and GetBitlockerStatus, preserving the error chain for errors.Is/errors.As.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 11, review and complete this code-review fix: fmt.Errorf wraps error but discards original error type context minimally in tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for the Connect() error paths in BitlockerEncryptionNumericalPassword, BitlockerDecryption, and GetBitlockerStatus, preserving the error chain for errors.Is/errors.As.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

}
defer vol.Close()

// Prepare for encryption

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 Errors wrapped with %v instead of %w throughout tools/mdm/windows/bitlocker/core.go

Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for vol.Prepare, vol.ProtectWithNumericalPassword, vol.ProtectWithTPM, vol.Encrypt (in BitlockerEncryptionNumericalPassword) and vol.Decrypt (in BitlockerDecryption), preserving the error chain throughout core.go.

🤖 Prompt for AI agents
In tools/mdm/windows/bitlocker/core.go around line 17, review and complete this code-review fix: Errors wrapped with %v instead of %w throughout tools/mdm/windows/bitlocker/core.go.
What the draft fix changed: Changed fmt.Errorf("...: %v", err) to fmt.Errorf("...: %w", err) for vol.Prepare, vol.ProtectWithNumericalPassword, vol.ProtectWithTPM, vol.Encrypt (in BitlockerEncryptionNumericalPassword) and vol.Decrypt (in BitlockerDecryption), preserving the error chain throughout core.go.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer

@flamingo flamingo Bot changed the title fix(adhoc-sweep-fixes): 61 review findings across 40 files fix(adhoc-sweep-fixes): CU-86akbhhtv 61 review findings across 40 files Sep 14, 2026
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.

0 participants