Realtime MVC Framework for Node.js
This report summarizes scanner evidence for balderdashy/sails, a JavaScript project with 22,779 GitHub stars. SynthScan examined 66,145 lines of code across 672 source files, recording 136 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 3.8 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 92 finding(s).
Are imports declared and package/API names verified? 8 finding(s).
Are wrappers, guards, and repeated structures necessary? 43 finding(s).
Which changes need focused human review? 136 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 136 distinct pattern matches across 9 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/unit/virtual-request-interpreter.test.js | 27 | // ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ | COMMENT |
| MEDIUM | test/unit/virtual-request-interpreter.test.js | 106 | // ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚══════╝╚══════╝╚═╝ ╚═══╝╚═════╝ ╚═╝╚═╝ ╚═════╝ | COMMENT |
| MEDIUM | test/unit/virtual-request-interpreter.test.js | 113 | // ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ | COMMENT |
| MEDIUM | test/integration/hook.i18n.test.js | 19 | // ╚═╝ ╚═╝ ╚════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ | COMMENT |
| MEDIUM | test/integration/hook.i18n.test.js | 26 | // ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ | COMMENT |
| MEDIUM | test/integration/hook.i18n.test.js | 149 | // ╚═╝ ╚═╝ ╚════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 106 | // ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 329 | // ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 458 | // ╚═╝ ╚═╝╚═════╝ ╚═════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 592 | // ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 677 | // ╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝ | COMMENT |
| MEDIUM | …ntegration/hook.pubsub.modelEvents.subscribers.test.js | 808 | // ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ | COMMENT |
| MEDIUM | test/integration/hook.blueprints.restful.routes.test.js | 521 | // ╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ | COMMENT |
| MEDIUM | lib/app/load.js | 154 | // ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚══════╝ ╚ | COMMENT |
| MEDIUM | lib/app/load.js | 288 | // ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═════ | COMMENT |
| MEDIUM | lib/app/private/loadHooks.js | 45 | // ╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/app/private/loadHooks.js | 250 | // ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚═╝ ╚═══ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 42 | // ╚══════╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 98 | // ╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 105 | // ╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 250 | // ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 290 | // ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 333 | // ╚═════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 356 | // ╚═╝ ╚═╝╚═════╝ ╚═════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 375 | // ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 394 | // ╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/blueprints/parse-blueprint-options.js | 434 | // ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/security/index.js | 51 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/security/index.js | 58 | // ╚═════╝╚══════╝╚═╝ ╚═╝╚═╝ | COMMENT |
| MEDIUM | lib/hooks/security/index.js | 116 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/security/index.js | 123 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/pubsub/index.js | 185 | // ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ | COMMENT |
| MEDIUM | lib/hooks/pubsub/index.js | 355 | // ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/views/html-scriptify.js | 57 | // ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/views/html-scriptify.js | 135 | // ╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ | COMMENT |
| MEDIUM | lib/hooks/views/html-scriptify.js | 142 | // ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | appveyor.yml | 1 | # # # # # # # # # # # # # # # # # # # # # # # # # # | COMMENT |
| LOW | appveyor.yml | 41 | # (Not sure what this is for, it's just in Appveyor's example. | COMMENT |
| LOW | test/init.js | 1 | // Initialization script that runs once before any tests. | COMMENT |
| LOW | test/unit/virtual-request-interpreter.test.js | 101 | // ██████╗ ███████╗███████╗ ███████╗███████╗███╗ ██╗██████╗ ██╗██╗ ██╗ | COMMENT |
| LOW | test/unit/virtual-request-interpreter.test.js | 121 | // return res.send(false); // 215b (sends down the string `false`, content len ==> 5) | COMMENT |
| LOW | …st/helpers/test-spawning-sails-child-process-in-cwd.js | 41 | * Also if it is set AND `httpRequestInstructions` are set, then the HTTP request | COMMENT |
| LOW | test/helpers/router.js | 121 | // var helper = { | COMMENT |
| LOW | test/helpers/router.js | 141 | // // Emit a request event (will be intercepted by the Router) | COMMENT |
| LOW | test/helpers/router.js | 161 | // return function () { | COMMENT |
| LOW | test/helpers/router.js | 181 | // url: '/', | COMMENT |
| LOW | test/helpers/router.js | 201 | // var _enhancedRes = util.defaults(res || {}, { | COMMENT |
| LOW | test/helpers/router.js | 221 | COMMENT | |
| LOW | test/helpers/router.js | 241 | // * | COMMENT |
| LOW | test/helpers/router.js | 261 | // return { | COMMENT |
| LOW | test/helpers/router.js | 281 | // var expectedResponse = { status: 200 }; | COMMENT |
| LOW | test/helpers/router.js | 301 | // __it('should have sent the proper response', expect.equal('response', expectedResponse)); | COMMENT |
| LOW | bin/sails.js | 161 | // FUTURE: ^^ Consider simplifying this into a script. | COMMENT |
| LOW | bin/sails-run.js | 261 | // Maybe as an option at least. | COMMENT |
| LOW | bin/sails-run.js | 281 | // ``` | COMMENT |
| LOW | bin/sails-console.js | 41 | COMMENT | |
| LOW | bin/sails-console.js | 141 | // Return the new writable stream. | COMMENT |
| LOW | bin/sails-console.js | 161 | preview: false, | COMMENT |
| LOW | docs/concepts/Security/XSS.md | 41 | // }, | COMMENT |
| LOW | docs/concepts/Realtime/Realtime.md | 101 | // are _listening_. In other words, to actually handle the socket message, | COMMENT |
| LOW | docs/concepts/ORM/Associations/OneWayAssociation.md | 41 | } | COMMENT |
| LOW | docs/concepts/ORM/Associations/OnetoMany.md | 81 | // lastName: 'Bar', | COMMENT |
| LOW | lib/index.js | 1 | /** | COMMENT |
| LOW | lib/app/load.js | 101 | controller: ['hooks', function(results, cb) { | COMMENT |
| LOW | lib/app/load.js | 141 | COMMENT | |
| LOW | lib/app/load.js | 281 | } | COMMENT |
| LOW | lib/app/lower.js | 121 | // Allow process to exit once this server is closed | COMMENT |
| LOW | lib/app/configuration/rc.js | 21 | COMMENT | |
| LOW | lib/app/private/bootstrap.js | 21 | module.exports = function runBootstrap(done) { | COMMENT |
| LOW | lib/app/private/loadHooks.js | 81 | // // If so, something is wrong. | COMMENT |
| LOW | lib/app/private/loadHooks.js | 241 | process.nextTick(function(){ cb(); }); | COMMENT |
| LOW | lib/app/private/isLocalSailsValid.js | 81 | log.debug(requiredSailsVersion); | COMMENT |
| LOW | lib/hooks/moduleloader/index.js | 21 | // • 'js' (.js) | COMMENT |
| LOW | lib/hooks/moduleloader/index.js | 61 | // Paths for application modules and key files | COMMENT |
| LOW | lib/hooks/moduleloader/index.js | 121 | // Configuration | COMMENT |
| LOW | lib/hooks/moduleloader/index.js | 421 | // Look inside namespaced folders e.g. node_modules/@sailsjs/sails-hook-foo | COMMENT |
| LOW | lib/hooks/blueprints/index.js | 61 | // Blueprint/Shadow-Routes Enabled | COMMENT |
| LOW | lib/hooks/blueprints/actions/create.js | 81 | // e.g. | COMMENT |
| LOW | lib/hooks/blueprints/actions/add.js | 41 | COMMENT | |
| LOW | lib/hooks/blueprints/actions/replace.js | 141 | return res.serverError(err); | COMMENT |
| LOW | lib/hooks/blueprints/actions/replace.js | 161 | // blueprint action would have been rolled back along with the transaction | COMMENT |
| LOW | lib/hooks/security/index.js | 41 | }, | COMMENT |
| LOW | lib/hooks/http/initialize.js | 21 | // or if it is disabled, then go ahead and proceed | COMMENT |
| LOW | lib/hooks/http/initialize.js | 201 | // (see https://github.com/balderdashy/sails/pull/3599#issuecomment-195665040) | COMMENT |
| LOW | lib/hooks/http/initialize.js | 321 | } | COMMENT |
| LOW | lib/hooks/http/initialize.js | 341 | COMMENT | |
| LOW | lib/hooks/http/index.js | 61 | // and `./get-configured-http-middleware-fns.js` in this hook for details. | COMMENT |
| LOW | lib/hooks/http/index.js | 121 | // If no _explicit_ middleware order is specified, make sure the implicit default order | COMMENT |
| LOW | lib/hooks/http/get-configured-http-middleware-fns.js | 21 | * @property {Function} * | COMMENT |
| LOW | lib/hooks/request/params.all.js | 41 | } | COMMENT |
| LOW | lib/hooks/request/params.all.js | 61 | // value: function (){ | COMMENT |
| LOW | lib/hooks/request/metadata.js | 21 | module.exports = function _mixinServerMetadata(req) { | COMMENT |
| LOW | lib/hooks/views/default-view-rendering-fn.js | 201 | COMMENT | |
| LOW | lib/hooks/views/res.view.js | 261 | // Note: | COMMENT |
| LOW | lib/hooks/views/res.view.js | 381 | if (err) { | COMMENT |
| LOW | …s/views/unescape-html-entities-deep-lite.min.string.js | 1 | // This module exports the `toString()`-ed, minified version of the function defined below (`unescapeHtmlEntitiesDeepLit | COMMENT |
| 17 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | lib/hooks/security/index.js | 159 | sails.config.security.cors.allowOrigins = _.map(sails.config.security.cors.allowOrigins.split(','), function(ori | CODE |
| CRITICAL | lib/hooks/security/index.js | 207 | sails.config.security.cors.allowOrigins = _.map(sails.config.security.cors.allowOrigins.split(','), function(ori | CODE |
| CRITICAL | lib/hooks/http/index.js | 233 | if (!_.contains(sails.config.http.middleware.order.concat(['404', '500', 'startRequestTimer']), middlewareName)) | CODE |
| CRITICAL | lib/hooks/http/index.js | 249 | _.each(_.difference(sails.config.http.middleware.order, sails.hooks.http.defaults.http.middleware.order.concat(['4 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | docs/upgrading/To1.0.md | 34 | ##### Step 0: Check your Node version! | COMMENT |
| LOW⚡ | docs/upgrading/To1.0.md | 38 | ##### Step 1: Install hooks & update dependencies | COMMENT |
| LOW⚡ | docs/upgrading/To1.0.md | 48 | ##### Step 2: Update configuration | COMMENT |
| LOW | docs/upgrading/To1.0.md | 61 | ##### Step 3: Modify client-side code for the new blueprint API | COMMENT |
| LOW | docs/upgrading/To1.0.md | 72 | ##### Step 4: Adopt the new release of Waterline ORM | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …st/helpers/test-spawning-sails-child-process-in-cwd.js | 44 | module.exports = function testSpawningSailsLiftChildProcessInCwd (opts){ | CODE |
| LOW | …lpers/test-spawning-sails-lift-child-process-in-cwd.js | 45 | module.exports = function testSpawningSailsLiftChildProcessInCwd (_opts){ | CODE |
| LOW | bin/private/read-repl-history-and-start-transcribing.js | 23 | module.exports = function readReplHistoryAndBeginTranscribing(repl, file) { | CODE |
| LOW | lib/hooks/responses/index.js | 74 | sails.modules.loadResponses(function loadedRuntimeErrorModules(err, responseDefs) { | CODE |
| LOW | …s/views/unescape-html-entities-deep-lite.min.string.js | 9 | module.exports = 'function unescapeHtmlEntitiesDeepLite(r){if("function"!=typeof Array.isArray||"function"!=typeof Array | CODE |
| LOW | …s/views/unescape-html-entities-deep-lite.min.string.js | 67 | function unescapeHtmlEntitiesDeepLite(data){ | CODE |
| LOW | lib/router/index.js | 395 | Router.prototype.getActionIdentityForTarget = function getActionIdentityForTarget(target) { | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/integration/middleware.compression.test.js | 19 | var lipsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras fringilla mollis sapien sed consequat. C | CODE |
| LOW | test/integration/middleware.compression.test.js | 19 | var lipsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras fringilla mollis sapien sed consequat. C | CODE |
| LOW | docs/concepts/Configuration/Configuration.md | 108 | // Set a custom "email" value to "foo@bar.com": | COMMENT |
| LOW | docs/concepts/Configuration/Configuration.md | 109 | sails lift --custom.email='foo@bar.com' | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | lib/hooks/request/metadata.js | 40 | // But Express only delivers the host devoid of a port, so we have to delve into | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | lib/hooks/views/res.view.js | 434 | // While unlikely this will change, it's worth noting that this implementation | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …s/concepts/extending-sails/Generators/generatorList.md | 63 | + [sails-generate-scaffold](https://github.com/irlnathan/sails-generate-scaffold) | CODE |