AI Slop Code Risk Monitor

NodeBB/NodeBB

SlopCodeMonitor badge for NodeBB/NodeBB Adjusted legacy signal; badge bands: 25 / 50 / 75 (different from dashboard bands).

Node.js based forum software built for the modern web

0.6 Low pattern signal View on GitHub

Open-Source Code Quality, Security and Technical Debt Review

This report summarizes scanner evidence for NodeBB/NodeBB, a JavaScript project with 15,245 GitHub stars. SynthScan examined 398,458 lines of code across 5449 source files, recording 154 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 0.6 (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.

0.6
Adjusted Signal
0.6
Raw Pattern Score
100%
Time Factor
2026-10-31
Last Push
15.2K
Stars
JavaScript
Language
398.5K
Lines of Code
5.4K
Files
154
Pattern Hits
2026-10-31
Scan Date
0.00
HC Hit Rate

Risk Review · Payload v1

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.

Cognitive Ownership Risk 1.0/100 · LOW

Can maintainers explain intent, assumptions, and trade-offs? 71 finding(s).

Hallucinated Dependency & Supply Chain Risk 1.6/100 · LOW

Are imports declared and package/API names verified? 75 finding(s).

Agent Over-Engineering Ratio 1.1/100 · LOW

Are wrappers, guards, and repeated structures necessary? 68 finding(s).

PR Review Velocity Impact 2.7/100 · LOW

Which changes need focused human review? 154 finding(s).

What These Metrics Mean

Adjusted Signal
Legacy pattern score normalized per 1,000 scanned lines and multiplied by the repository-level time factor. It is not an estimate of AI authorship.
Raw Pattern Score
Sum of severity- and context-weighted pattern findings before applying the time factor.
Time Factor
A coarse multiplier based on repository last-push metadata. It does not identify when individual code was written.
Pattern Hits
Count of configured pattern findings. Review each location and surrounding code before acting.
HC Hit Rate
High- and critical-severity findings per scanned file. Severity is a configured detector weight, not proof of a vulnerability or authorship.
Lines / Files
Scan coverage denominators used by the legacy normalized score.

Pattern-Signal History

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.

Severity Breakdown

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.

CRITICAL 5HIGH 0MEDIUM 9LOW 140

Directory Score Breakdown

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.

Pattern Findings

The scanner identified 154 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.

Fake / Example Data70 hits · 75 pts
SeverityFileLineSnippetContext
LOW⚡test/flags.js1201 note: 'lorem ipsum dolor sit amet',CODE
LOW⚡test/flags.js1201 note: 'lorem ipsum dolor sit amet',CODE
LOW⚡test/flags.js1208 assert.strictEqual('lorem ipsum dolor sit amet', response.notes[0].content);CODE
LOW⚡test/flags.js1208 assert.strictEqual('lorem ipsum dolor sit amet', response.notes[0].content);CODE
LOWtest/user.js198 username: 'Jane Doe',CODE
LOWtest/user.js208 username: 'Jane Doe',CODE
LOWtest/user.js281 content: 'lorem ipsum',CODE
LOWtest/user.js298 content: 'lorem ipsum',CODE
LOWtest/user.js315 content: 'lorem ipsum',CODE
LOWtest/user.js2366 User.deleteInvitation('doesnotexist', 'test@test.com', (err) => {CODE
LOWtest/user.js2743 content: 'lorem ipsum',CODE
LOWtest/translator.js686 Translator.removePatterns('Lorem ipsum dolor [[sit:amet]], consectetur adipiscing elit. [[sed:vitae, [[semper:dolor]CODE
LOWtest/translator.js687 'Lorem ipsum dolor , consectetur adipiscing elit. lorem'CODE
LOWtest/activitypub.js451 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub.js451 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/emailer.js20 const email = 'test@example.org';CODE
LOWtest/emailer.js129 const from = 'admin@example.org';CODE
LOWtest/emailer.js181 recipientUid = await user.create({ username: 'recipient', email: 'test@example.org' }, {CODE
LOW⚡test/user/emails.js48 const email = 'test@example.org';CODE
LOW⚡test/user/emails.js55 const email = 'test@example.org';CODE
LOW⚡test/user/emails.js65 const email = 'test@example.org';CODE
LOWtest/user/emails.js83 const email = 'test@example.org';CODE
LOWtest/user/emails.js97 const email = 'test@example.org';CODE
LOWtest/user/emails.js132 const email = 'test@example.org';CODE
LOWtest/user/emails.js142 const email = 'test@example.org';CODE
LOWtest/user/emails.js160 username: 'fake-user',CODE
LOWtest/user/emails.js210 const { response } = await helpers.request('post', `/api/v3/users/${userObj.uid}/emails/${encodeURIComponent('fake@exaCODE
LOWtest/user/emails.js290 const { response } = await helpers.request('get', `/api/v3/users/${attackerUid}/emails/${encodeURIComponent('nonexisteCODE
LOWtest/user/blocks.js16 email: 'blockee@example.org',CODE
LOWtest/user/blocks.js21 email: 'blocker@example.org',CODE
LOW⚡test/api/schema.js195 const adminUid = await user.create({ username: 'admin', password: '123456', email: 'test@example.org' }, { emailVerificCODE
LOW⚡test/api/schema.js196 const unprivUid = await user.create({ username: 'unpriv', password: '123456', email: 'unpriv@example.org' }, { emailVerCODE
LOW⚡test/api/schema.js197 const emailConfirmationUid = await user.create({ username: 'emailConf', email: 'emailConf@example.org' });CODE
LOWtest/api/schema.js438 activitypub.helpers._webfingerCache.set('foobar@example.org', { actorUri: 'https://example.org/foobar' });CODE
LOWtest/activitypub/notes.js380 content: 'Guaranteed to be more than 500 characters.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. ICODE
LOWtest/activitypub/notes.js380 content: 'Guaranteed to be more than 500 characters.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. ICODE
LOWtest/activitypub/actors.js58 activitypub.helpers._webfingerCache.set('example@example.org', { actorUri });CODE
LOWtest/activitypub/actors.js179 activitypub.helpers._webfingerCache.set('foobar@example.org', {CODE
LOWtest/activitypub/actors.js185 const { actorUri: confirm } = await activitypub.helpers.query('foobar@example.org');CODE
LOWtest/activitypub/actors.js703 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js703 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js736 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js736 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js763 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js763 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js801 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js801 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js832 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/actors.js832 content: 'Lorem ipsum dolor sit amet',CODE
LOWtest/activitypub/mocks.js37 content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js37 content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js53 content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js53 content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js78 assert.strictEqual(this.withBreak.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js78 assert.strictEqual(this.withBreak.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js101 assert.strictEqual(mocked.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js101 assert.strictEqual(mocked.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\CODE
LOWtest/activitypub/mocks.js123 assert.strictEqual(mocked.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. [...]');CODE
LOWtest/activitypub/mocks.js123 assert.strictEqual(mocked.summary, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. [...]');CODE
LOWtest/activitypub/mocks.js148 content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' +CODE
10 more matches not shown…
Hyper-Verbose Identifiers60 hits · 62 pts
SeverityFileLineSnippetContext
LOWpublic/src/admin/federation/analytics.js76async function renderActivitiesByTypeLegend() {CODE
LOWpublic/src/modules/helpers.common.js202 function generateCategoryBackground(category) {CODE
LOWpublic/src/modules/helpers.common.js231 function generateChildrenCategories(category) {CODE
LOWpublic/src/modules/navigator.js183 async function updateThumbTimestampToIndex(thumb, index) {CODE
LOWpublic/src/modules/chat.js495 function makeModalResizeableDraggable(chatModal, uuid) {CODE
LOWpublic/src/modules/notifications.js162 function scrollToPostIndexIfOnPage(notifEl) {CODE
LOWpublic/src/modules/messages.js30 function hideAlertAndGotoEditEmail() {CODE
LOWpublic/src/client/post-queue.js33 function replaceRelativeUploadPath(url) {CODE
LOWpublic/src/client/category.js99 function handleLoadMoreSubcategories() {CODE
LOWpublic/src/client/chats.js343 function getTopVisibleMessageIndex(el) {CODE
LOWpublic/src/client/chats.js358 function updateUrlWithMessageIndex(roomId, el) {CODE
LOWpublic/src/client/groups/memberlist.js119 function handleMemberInfiniteScroll() {CODE
LOWpublic/src/client/groups/details.js336 function updatePendingAlertVisibility() {CODE
LOWpublic/src/client/groups/details.js343 function updateInviteAlertVisibility() {CODE
LOWpublic/src/client/topic/events.js67 function updatePostVotesAndUserReputation(data) {CODE
LOWpublic/src/client/topic/posts.js57 function updateNavigatorLastPostTimestamp(post) {CODE
LOWpublic/src/client/topic/posts.js429 function hidePostToolsForDeletedPosts(posts) {CODE
LOWpublic/src/client/account/settings.js229 function handleNotificationToggles() {CODE
LOWsrc/flags.js1123async function mergeUsernameEmailChanges(history, targetUid, uids) {CODE
LOWsrc/install.js417async function createGlobalModeratorsGroup() {CODE
LOWsrc/notifications.js28function getOrCreateCache() {CODE
LOWsrc/middleware/user.js320 async function requiresEmailConfirmation(req) {CODE
LOWsrc/middleware/render.js148 async function loadClientHeaderFooterData(req, res, options) {CODE
LOWsrc/middleware/render.js252 async function loadAdminHeaderFooterData(req, res, options) {CODE
LOWsrc/middleware/uploads.js94function normalizeUploadRequestPath(requestPath) {CODE
LOWsrc/database/index.js40function promisifySessionStoreMethod(method, sid) {CODE
LOWsrc/database/mongo/sorted.js404 async function getSortedSetsMembersWithScores(keys, withScores) {CODE
LOWsrc/posts/delete.js97 async function deleteFromTopicUserNotification(postData) {CODE
LOWsrc/posts/delete.js169 async function deleteFromCategoryRecentPosts(postData) {CODE
LOWsrc/posts/uploads.js89 function getUploadsFromPostContent(content) {CODE
LOWsrc/user/posts.js152 async function incrementUserFieldAndSetBy(uid, field, set, value) {CODE
LOWsrc/user/auth.js135 async function revokeSessionsAboveThreshold(activeSids, uid) {CODE
LOW⚡src/user/delete.js186 async function deleteUserFromFollowedTopics(uid) {CODE
LOW⚡src/user/delete.js191 async function deleteUserFromIgnoredTopics(uid) {CODE
LOW⚡src/user/delete.js196 async function deleteUserFromFollowedTags(uid) {CODE
LOWsrc/user/picture.js198 function generateProfileImageFilename(uid, extension) {CODE
LOWsrc/user/picture.js247 async function getPicturePathFromUserField(uid, field) {CODE
LOWsrc/user/approval.js151 async function getRegistrationQueuedMessage() {CODE
LOWsrc/groups/invite.js84 async function inviteOrRequestMembership(groupName, uids, type) {CODE
LOWsrc/groups/delete.js58 async function removeGroupsFromPublicRooms(groupNames) {CODE
LOWsrc/groups/delete.js74 async function removeGroupsFromPostEditors(groupNames) {CODE
LOWsrc/groups/delete.js82 async function removeGroupsFromPrivilegeGroups(groupNames) {CODE
LOWsrc/cli/package-install.js96function getPackageManagerByLockfile() {CODE
LOWsrc/privileges/helpers.js136async function isSystemGroupAllowedToCids(privilege, uid, cids) {CODE
LOWsrc/privileges/helpers.js141async function isSystemGroupAllowedToPrivileges(privileges, uid, cid) {CODE
LOWsrc/socket.io/admin/categories.js21async function copyPrivilegesToChildrenRecursive(parentCid, category, group, filter) {CODE
LOWsrc/api/users.js532async function isPrivilegedOrSelfAndPasswordMatch(caller, data) {CODE
LOWsrc/controllers/search.js209async function buildSelectedCategoryLabel(selectedCids) {CODE
LOWsrc/controllers/authentication.js82async function validateRegistrationPolicy(userData) {CODE
LOWsrc/controllers/admin/admins-mods.js47async function getModeratorsOfCategories(categoryData) {CODE
LOWsrc/categories/create.js129 async function duplicateCategoriesChildren(parentCid, cid, uid) {CODE
LOWsrc/routes/feeds.js332async function generateForCategoryRecentPosts(req, res, next) {CODE
LOWsrc/topics/unread.js241 async function filterTidsThatHaveBlockedPosts(params) {CODE
LOWsrc/topics/unread.js258 async function doesTidHaveUnblockedUnreadPosts(tid, params) {CODE
LOWsrc/topics/posts.js320 async function incrementFieldAndUpdateSortedSet(tid, field, by, set) {CODE
LOWsrc/topics/delete.js155 async function deleteFromFollowersIgnorers(tids) {CODE
LOWsrc/topics/delete.js196 async function deleteTopicsFromCategoryAndUser(topicsData) {CODE
LOWsrc/topics/index.js238function mergeConsecutiveShareEvents(arr) {CODE
LOWsrc/topics/sorted.js135 async function getTidsWithMostPostsInTerm({ cids, uid, term, includeRemote }) {CODE
LOWsrc/topics/teaser.js115 async function getPreviousNonBlockedPost(postData, blockedUids) {CODE
Hallucination Indicators5 hits · 50 pts
SeverityFileLineSnippetContext
CRITICALpublic/src/ajaxify.js319 ajaxify.data._header.tags.meta.forEach(async (tagObj) => {CODE
CRITICALpublic/src/ajaxify.js339 ajaxify.data._header.tags.link.forEach(async (tagObj) => {CODE
CRITICALpublic/src/admin/manage/privileges.js469 const privilegeSet = ajaxify.data.privileges.keys.groups.reduce(function (memo, cur, index) {CODE
CRITICALpublic/src/admin/manage/privileges.js507 const privilegeSet = ajaxify.data.privileges.keys.users.reduce(function (memo, cur, index) {CODE
CRITICALsrc/socket.io/index.js308 const roomMap = Sockets.server.sockets.adapter.rooms.get(room);CODE
Decorative Section Separators8 hits · 24 pts
SeverityFileLineSnippetContext
MEDIUMtest/activitypub/blocklists.js50 // ─── blocklists.list() ───────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js105 // ─── blocklists.get() ────────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js143 // ─── blocklists.add() ────────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js173 // ─── blocklists.remove() ─────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js215 // ─── blocklists.refresh() ────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js297 // ─── blocklists.check() ──────────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js378 // ─── blocklists.getSeverity() ────────────────────────────────────────COMMENT
MEDIUMtest/activitypub/blocklists.js414 // ─── Full lifecycle integration ──────────────────────────────────────COMMENT
Verbosity Indicators4 hits · 8 pts
SeverityFileLineSnippetContext
LOWtest/activitypub/notes.js861 // Step 1: Assert a note addressed to the remote category in ccCOMMENT
LOW⚡test/activitypub/notes.js876 // Step 2: Announce from the same remote categoryCOMMENT
LOW⚡test/activitypub/notes.js886 // Step 3: Verify the topic was moved to the remote categoryCOMMENT
LOWsrc/activitypub/helpers.js284 // Step 1: Backreference — non-strict query on domain B (the actor's id host).COMMENT
Structural Annotation Overuse4 hits · 8 pts
SeverityFileLineSnippetContext
LOWtest/activitypub/notes.js861 // Step 1: Assert a note addressed to the remote category in ccCOMMENT
LOW⚡test/activitypub/notes.js876 // Step 2: Announce from the same remote categoryCOMMENT
LOW⚡test/activitypub/notes.js886 // Step 3: Verify the topic was moved to the remote categoryCOMMENT
LOWsrc/activitypub/helpers.js284 // Step 1: Backreference — non-strict query on domain B (the actor's id host).COMMENT
Self-Referential Comments1 hit · 3 pts
SeverityFileLineSnippetContext
MEDIUMinstall/docker/entrypoint.sh180 # Create a local array to work withCOMMENT
Over-Commented Block1 hit · 1 pts
SeverityFileLineSnippetContext
LOWpublic/scss/overrides.scss1// global bs5 overrides if necessaryCOMMENT
Overly Generic Function Names1 hit · 1 pts
SeverityFileLineSnippetContext
LOWpublic/src/client/topic/postTools.js374 function getData(button, data) {CODE