refactor(all-services): resolve sonarcloud reliability and security issues - #2604
Merged
Conversation
…ssues - use node: protocol for core module imports in packages, services and tests - use Number.parseInt, Number.isNaN, new Error and new Array over global forms - use Boolean predicate in Array.find and Array.includes over Array.indexOf - use String.raw for regex literals in audit-service construct-where - pin pip versions and add --only-binary :all: in docs workflow - pin lerna to 9.0.7 in release workflow and scaffold template - use npm ci --ignore-scripts in sandbox Dockerfiles and add their lockfiles - rebuild bcrypt after ignore-scripts install in auth-multitenant example - refresh root package-lock.json GH-2603
Sourav-kashyap
force-pushed
the
GH-2603
branch
from
September 1, 2026 07:37
fe8f2e3 to
6094362
Compare
fix trivy GH-2603
|
Sourav-kashyap
marked this pull request as ready for review
September 1, 2026 12:33
Sourav-kashyap
requested review from
a team,
samarpan-b and
yeshamavani
as code owners
September 1, 2026 12:33
rohit-wadhwa
approved these changes
Sep 4, 2026
rohit-sourcefuse
removed their request for review
September 4, 2026 08:08
yeshamavani
approved these changes
Sep 4, 2026
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.



Summary
Fixes the 47 open/confirmed SonarCloud issues on the current leak period for
sourcefuse_loopback4-microservice-catalog. Each issue was fixed at the exact file and linereported. No unrelated code was touched.
The bulk of this is mechanical and semantics-preserving. Two changes that looked mechanical turned
out to alter behaviour and were caught and corrected during review — both are called out below,
because neither was detectable by
build/lint/test.What changed
A.
node:import protocol — 24 issues, 22 filesCore-module specifiers switched to the
node:form (crypto→node:crypto,path→node:path,stream→node:stream,fs→node:fs,import('http')→import('node:http')), preserving theexisting import style on each line (default / named /
* as/require/ type-onlyimport()).B. Modern JS built-ins — 6 issues
parseInt→Number.parseInt(packages/file-utils/src/constant.ts)Error(...)→new Error(...)(file-metadata.service.ts)results.find(r => r)→results.find(Boolean)(multer-storage.provider.ts)Array(n)→new Array(n)(idp-login.service.ts)isNaN(...)→Number.isNaN(Number(...))(chat-session.service.ts) — see the section belowarr.indexOf(x) === -1→!arr.includes(x)(custom-sf-changelog/writer-opts.js)C.
String.rawfor backslash escapes — 2 issuesservices/audit-service/src/utils/construct-where.tslines 76 and 84. The resulting string isbyte-identical (verified) — it is passed to the Postgres connector as a
regexpoperand, so anydrift would have silently changed audit-log filtering.
D. CI / dependency security hotspots — 15 issues
docs.yml:pip install --only-binary :all:with pinned versions (mkdocs-material==9.7.7,mkdocs-include-markdown-plugin==7.3.0). The previouspip install ... --ignore-scriptswasnot a valid pip option — that flag is npm-only, and pip exits
2on it. Verified againstpip 26.0.1: zero occurrences of
ignore-scriptsin its source; the only--ignore*options are--ignore-installedand--ignore-requires-python.release.yml: lerna pinned to9.0.7(matching rootpackage.json+ lockfile) in all threeplaces, plus
npx --ignore-scripts.npx --ignore-scripts lerna@9.0.7, andpackage.json.tplbumped^7.3.0→^9.0.7so the pin and the declared dependency agree.npm install→npm ci --ignore-scripts, with lockfiles added (below).Number(...)was added inchat-session.service.tsThis is the one change in this PR that deserves a careful read. Sonar asked for
isNaN→Number.isNaN, but the naive swap is not equivalent and would have silently disabled aREST validation.
These are two different functions, not aliases.
"abc"isNaN(x)xnot convertible to a valid number?" — coerces firstNumber("abc")isNaN→ trueNumber.isNaN(x)xexactly theNaNvalue?" — never coerces"abc"is a string → falseNumber.isNaNis effectivelytypeof x === 'number' && x !== x. Any string short-circuits tofalse— even the string"NaN".There is a second subtlety:
.valueOf()does not produce a number here.String.prototype.valueOf()returns the primitive string back ("abc".valueOf() === "abc"). OnlyDate.prototype.valueOf()yields a number, which is why the line reads as though it were alreadynumeric.
And
expireTimereally is a string at runtime. The controller declares:SessionOptionsis aninterface(src/types.ts:170), so TypeScript emitsObjectas thedesign:typeand LoopBack generates a loose{type: 'object'}schema with no per-propertycoercion. JSON has no Date type, so the value arrives as a string — the declared
expireTime?: Dateis a compile-time fiction.
Impact had the naive version shipped: a garbage
expireTimestring would have passed validation,then passed
moment().isAfter()(which returnsfalsefor unparseable input, so no "in past" erroreither), and reached
vonage.service.ts:106—moment("abc").unix()→NaNsent to the Vonage SDK.A clean
400would have become a provider-side error or 500.Why
Number(...)is the right fix and not redundant: globalisNaN(x)is specified as "coercexto Number, then test for NaN" — it literally isNumber.isNaN(Number(x)). Writing theconversion explicitly restores exactly what the global was doing internally, while still satisfying
the Sonar rule (no bare global
isNaN). If the value genuinely is aDate,Number()is a freeno-op.
Verified identical to the original across 21 input classes, 0 divergences: valid/past/invalid
Date; ISO full and date-only strings; garbage, numeric, float, whitespace,"NaN","Infinity"and hex strings; timestamps,
1,-1,Infinity;true;[1],[1,2];{}; and an object with acustom
valueOf(). Falsy inputs never reach the line — the enclosingif (expireTime)guard isunchanged.
Second regression caught:
--ignore-scriptsvsbcryptsandbox/auth-multitenant-exampledepends onbcrypt, a native addon whose binding is built byan install script. Adding
--ignore-scriptsmeant the image would build fine and then crash atrequire()withCould not locate the bindings file. This repo already records that these packagesneed scripts, in root
package.json:Fixed by rebuilding the one vetted native module:
RUN npm ci --ignore-scripts && npm rebuild bcrypt && npm run buildThis adds no new build requirement — the original
npm installran bcrypt's install script too.workflow-ms-examplehas no native deps, so it needs no rebuild step;oauth-examplestill usesplain
npm ci(it was not in the 47-issue list), so its scripts still run.Lockfiles for
npm cinpm cifails without apackage-lock.json, and these sandbox directories had none — they are npmworkspaces, so their deps only ever resolved into the root lockfile. Standalone lockfiles were
generated for every directory that needs one:
sandbox/auth-multitenant-example/npm ciintroduced heresandbox/workflow-ms-example/npm ciintroduced heresandbox/oauth-example/npm cithat never had a lockfileGenerated in an isolated temp directory (so npm could not walk up and rewrite the root lockfile),
via
npm install --package-lock-only --ignore-scripts --no-audit. All three declare only registryranges — no
file:/link:/workspace:deps — so standalone resolution is valid. Verified: rootlockfile SHA-256 unchanged by the generation; root
npm install --package-lock-onlyre-resolve isbyte-identical, proving npm ignores nested workspace lockfiles.
Other intentional behaviour changes (CI/Docker only, no runtime code)
lerna@latest→lerna@9.0.7inrelease.yml.latestcurrently resolves to 10.0.1, amajor ahead of what the repo declares. Practical impact is near-zero:
npxalready preferred thelocal
9.0.7.lerna run/changed/version/clean(all still present in v9), there is nolerna bootstrapanywhere in the templates (removed in v8 — would have been the breakage), andthe generated workflow already runs Node 24. Affects newly scaffolded projects only.
docs.ymlpip step now actually runs instead of exiting2. That workflow is currentlydisabled_manuallyon GitHub with 0 recorded runs, so this was a latent failure, not an outage.Verification
npm run build --workspaces --if-presentnpm run lint --workspaces --if-presentnpm run test --workspaces --if-presentpre-commithook (lerna run test && lerna run lint).ts/.jspip download --only-binary :all:on pinned versionsnpx --ignore-scripts lerna@9.0.7 --version9.0.7, resolved locally, no network fetchnpm ci --ignore-scripts --dry-runper new lockfile