Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
This report summarizes scanner evidence for tinode/chat, a Go project with 13,546 GitHub stars. SynthScan examined 76,816 lines of code across 177 source files, recording 141 pattern matches distributed across 11 syntactic categories. The legacy adjusted pattern signal is 2.3 (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? 76 finding(s).
Are imports declared and package/API names verified? 45 finding(s).
Are wrappers, guards, and repeated structures necessary? 34 finding(s).
Which changes need focused human review? 141 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 141 distinct pattern matches across 11 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 |
|---|---|---|---|---|
| LOW | rest-auth/auth.py | 18 | # here so authentication data can be compared with dummy_data values. | COMMENT |
| LOW⚡ | rest-auth/auth.py | 49 | if uname in dummy_data: | CODE |
| LOW⚡ | rest-auth/auth.py | 50 | if dummy_data[uname]['password'] != password: | CODE |
| LOW⚡ | rest-auth/auth.py | 53 | if 'uid' in dummy_data[uname]: | CODE |
| LOW⚡ | rest-auth/auth.py | 57 | 'uid': dummy_data[uname]['uid'], | CODE |
| LOW⚡ | rest-auth/auth.py | 58 | 'authlvl': dummy_data[uname]['authlvl'], | CODE |
| LOW⚡ | rest-auth/auth.py | 59 | 'features': dummy_data[uname]['features'] | CODE |
| LOW⚡ | rest-auth/auth.py | 66 | 'authlvl': dummy_data[uname]['authlvl'], | CODE |
| LOW⚡ | rest-auth/auth.py | 67 | 'tags': dummy_data[uname]['tags'], | CODE |
| LOW⚡ | rest-auth/auth.py | 68 | 'features': dummy_data[uname]['features'] | CODE |
| LOW⚡ | rest-auth/auth.py | 71 | 'auth': dummy_data[uname]['auth'], | CODE |
| LOW⚡ | rest-auth/auth.py | 72 | 'anon': dummy_data[uname]['anon'], | CODE |
| LOW⚡ | rest-auth/auth.py | 73 | 'public': dummy_data[uname]['public'], | CODE |
| LOW⚡ | rest-auth/auth.py | 74 | 'private': dummy_data[uname]['private'] | CODE |
| LOW⚡ | rest-auth/auth.py | 112 | if uname not in dummy_data: | CODE |
| LOW⚡ | rest-auth/auth.py | 115 | if dummy_data[uname]['password'] != password: | CODE |
| LOW⚡ | rest-auth/auth.py | 117 | if 'uid' in dummy_data[uname]: | CODE |
| LOW⚡ | rest-auth/auth.py | 122 | dummy_data[uname]['uid'] = rec['uid'] | CODE |
| LOW⚡ | rest-auth/auth.py | 123 | with open('dummy_data.json', 'w') as outfile: | CODE |
| LOW⚡ | rest-auth/auth.py | 124 | json.dump(dummy_data, outfile, indent=2, sort_keys=True) | CODE |
| LOW | rest-auth/auth.py | 11 | dummy_data = {} | CODE |
| LOW | rest-auth/auth.py | 151 | with open('dummy_data.json') as infile: | CODE |
| LOW | rest-auth/auth.py | 152 | dummy_data = json.load(infile) | CODE |
| LOW | rest-auth/test_auth.py | 13 | self.original_dummy_data = auth.dummy_data | CODE |
| LOW | rest-auth/test_auth.py | 16 | auth.dummy_data = { | CODE |
| LOW⚡ | rest-auth/test_auth.py | 31 | auth.dummy_data = self.original_dummy_data | CODE |
| LOW⚡ | rest-auth/test_auth.py | 47 | auth.dummy_data['alice']['uid'] = 'usrAlice' | CODE |
| LOW⚡ | rest-auth/test_auth.py | 101 | self.assertNotIn('uid', auth.dummy_data['alice']) | CODE |
| LOW⚡ | rest-auth/test_auth.py | 111 | self.assertEqual(auth.dummy_data['alice']['uid'], 'usrAlice') | CODE |
| LOW⚡ | rest-auth/test_auth.py | 112 | open_file.assert_called_once_with('dummy_data.json', 'w') | CODE |
| LOW | docker/README.md | 218 | | `SMTP_SENDER` | string | | [RFC 5322](https://tools.ietf.org/html/rfc5322) email address to use in the `FROM` field o | CODE |
| LOW | server/db/common/common_test.go | 295 | "Name": "John Doe", | CODE |
| LOW | docs/API.md | 616 | content: "Lorem ipsum dolor sit amet, consectetur adipisci", // The first 80 characters of the message content as plai | CODE |
| LOW | docs/API.md | 616 | content: "Lorem ipsum dolor sit amet, consectetur adipisci", // The first 80 characters of the message content as plai | CODE |
| LOW | docs/thecard.md | 11 | fn: "John Doe", // string, formatted name of the person or topic. | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker/docker-compose/single-instance.yml | 21 | # "EXT_CONFIG": "/etc/tinode/tinode.conf" | COMMENT |
| LOW | docker/docker-compose/cluster.yml | 21 | COMMENT | |
| LOW | tn-cli/sample-script.txt | 1 | # This script shows what can be done with tn-cli. Run it as | COMMENT |
| LOW | tn-cli/sample-macro-script.txt | 1 | # This script shows what can be done with tn-cli macros. Run it as | COMMENT |
| LOW | pbx/model_grpc.pb.go | 361 | // PluginServer is the server API for Plugin service. | COMMENT |
| LOW | server/hub.go | 161 | return h | COMMENT |
| LOW | server/hub.go | 381 | return true | COMMENT |
| LOW | server/pres.go | 81 | // This topic got a request from a 'me' topic to start/stop sending presence updates. | COMMENT |
| LOW | server/pres.go | 301 | RcptTo: subs[i].Topic, | COMMENT |
| LOW | server/session.go | 121 | // Synchronizes access to session store in cluster mode: | COMMENT |
| LOW | server/topic.go | 121 | proxy chan *ClusterResp | COMMENT |
| LOW | server/topic.go | 1601 | // asChan - true if the user is subscribing to a channel topic | COMMENT |
| LOW | server/init_topic.go | 221 | // 'fnd' has no owner, t.owner = nil | COMMENT |
| LOW | server/api_key.go | 21 | // | COMMENT |
| LOW | server/main.go | 101 | // Mount point where static content is served, http://host-name<defaultStaticMount> | COMMENT |
| LOW | server/main.go | 121 | // flag to compiler command line: | COMMENT |
| LOW | server/main.go | 261 | type configType struct { | COMMENT |
| LOW | server/main.go | 301 | // URL path for exposing runtime stats. Disabled if the path is blank. | COMMENT |
| LOW | server/validate/validator.go | 21 | // IsInitialized returns true if the validator is initialized. | COMMENT |
| LOW | server/auth/auth.go | 241 | AddRecord(rec *Rec, secret []byte, remoteAddr string) (*Rec, error) | COMMENT |
| LOW | server/push/common/typedef.go | 181 | COMMENT | |
| LOW | server/push/common/typedef.go | 201 | // to redeliver it. | COMMENT |
| LOW | server/push/common/typedef.go | 241 | ApnsPushTypeAlert ApnsPushTypeType = "alert" | COMMENT |
| LOW | server/push/common/typedef.go | 301 | ErrorUnspecified = "UNSPECIFIED_ERROR" | COMMENT |
| LOW | server/push/common/typedef.go | 321 | // App instance was unregistered from FCM (HTTP error code = 404). This usually means that the token used is no | COMMENT |
| LOW | server/push/common/typedef.go | 341 | // Sending limit exceeded for the message target (HTTP error code = 429). An extension of type google.rpc.QuotaFailure | COMMENT |
| LOW | server/db/adapter.go | 41 | COMMENT | |
| LOW | server/db/adapter.go | 101 | // TopicGet loads a single topic by name, if it exists. If the topic does not exist the call returns (nil, nil) | COMMENT |
| LOW | server/db/adapter.go | 141 | SubsUpdate(topic string, user t.Uid, update map[string]any) error | COMMENT |
| LOW | server/db/adapter.go | 181 | // FileStartUpload initializes a file upload. | COMMENT |
| LOW | server/db/rethinkdb/blank.go | 1 | //go:build !rethinkdb | COMMENT |
| LOW | server/db/mongodb/blank.go | 1 | //go:build !mongodb | COMMENT |
| LOW | server/db/postgres/schema.sql | 1 | # The MySQL and PostrgreSQL schemas are identical save for differences in SQL flavors. | COMMENT |
| LOW | server/db/postgres/blank.go | 1 | //go:build !postgres | COMMENT |
| LOW | server/db/mysql/blank.go | 1 | //go:build !mysql | COMMENT |
| LOW | server/ringhash/ringhash_test.go | 21 | // B2 = 880502322 -> B | COMMENT |
| LOW | server/ringhash/ringhash_test.go | 81 | // Collision test: these strings generate CRC32 collisions | COMMENT |
| LOW | docs/API.md | 1281 | // of a deleted message, optional. | COMMENT |
| LOW | monitoring/exporter/main.go | 41 | } | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tn-cli/client.py | 67 | except Exception as err: | CODE |
| LOW | tn-cli/client.py | 79 | except Exception as err: | CODE |
| LOW | tn-cli/client.py | 193 | except Exception as err: | CODE |
| LOW | tn-cli/client.py | 273 | except Exception as ex: | CODE |
| MEDIUM | tn-cli/client.py | 72 | def read_cookie(): | CODE |
| LOW | tn-cli/tn_globals.py | 100 | except Exception as err: | CODE |
| LOW | tn-cli/input_handler.py | 62 | except Exception as ex: | CODE |
| LOW | tn-cli/commands.py | 426 | except Exception as ex: | CODE |
| LOW⚡ | tn-cli/commands.py | 446 | except Exception as ex: | CODE |
| LOW⚡ | tn-cli/commands.py | 456 | except Exception as ex: | CODE |
| LOW | tn-cli/commands.py | 595 | except Exception: | CODE |
| LOW | tn-cli/commands.py | 606 | except Exception as err: | CODE |
| LOW | tn-cli/commands.py | 790 | except Exception as err: | CODE |
| MEDIUM | tn-cli/commands.py | 405 | def upload(id, cmd, args): | CODE |
| LOW | chatbot/python/chatbot.py | 91 | except Exception as err: | CODE |
| LOW | chatbot/python/chatbot.py | 331 | except Exception as err: | CODE |
| LOW | chatbot/python/chatbot.py | 362 | except Exception as err: | CODE |
| MEDIUM | chatbot/python/chatbot.py | 252 | def client_message_loop(stream): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tn-cli/client.py | 93 | CODE | |
| LOW | tn-cli/client.py | 198 | CODE | |
| LOW | tn-cli/utils.py | 44 | CODE | |
| LOW | tn-cli/input_handler.py | 28 | CODE | |
| LOW | tn-cli/commands.py | 50 | CODE | |
| LOW | tn-cli/commands.py | 258 | CODE | |
| LOW | tn-cli/commands.py | 366 | CODE | |
| LOW | tn-cli/commands.py | 432 | CODE | |
| LOW | tn-cli/commands.py | 485 | CODE | |
| LOW | tn-cli/commands.py | 602 | CODE | |
| LOW | tn-cli/commands.py | 702 | CODE | |
| LOW | tn-cli/commands.py | 433 | CODE | |
| LOW | chatbot/python/chatbot.py | 78 | CODE | |
| LOW | chatbot/python/chatbot.py | 252 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | docker/tinode/entrypoint.sh | 84 | # Create an empty firebase-init.js | COMMENT |
| MEDIUM | tn-cli/utils.py | 126 | # Create a drafty message with an *in-band* attachment. | COMMENT |
| MEDIUM | py_grpc/tinode_grpc/model_pb2_grpc.py | 84 | # This class is part of an EXPERIMENTAL API. | COMMENT |
| MEDIUM | py_grpc/tinode_grpc/model_pb2_grpc.py | 273 | # This class is part of an EXPERIMENTAL API. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tn-cli/client.py | 3 | CODE | |
| LOW | tn-cli/client.py | 15 | CODE | |
| LOW | tn-cli/tn_globals.py | 3 | CODE | |
| LOW | tn-cli/tn-cli.py | 6 | CODE | |
| LOW | tn-cli/utils.py | 3 | CODE | |
| LOW | tn-cli/input_handler.py | 3 | CODE | |
| LOW | tn-cli/commands.py | 3 | CODE | |
| LOW | chatbot/python/chatbot.py | 4 | CODE | |
| LOW | py_grpc/tinode_grpc/__init__.py | 1 | CODE | |
| LOW | py_grpc/tinode_grpc/__init__.py | 2 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tn-cli/commands.py | 595 | except Exception: | CODE |
| HIGH | chatbot/python/chatbot.py | 175 | except queue.Empty: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 90 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 107 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 124 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 279 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 296 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 313 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 330 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 347 | CODE | |
| LOW | py_grpc/tinode_grpc/model_pb2_grpc.py | 364 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | rest-auth/test_auth.py | 39 | def test_parse_secret_preserves_colons_in_password(self): | CODE |
| LOW⚡ | rest-auth/test_auth.py | 46 | def test_auth_returns_existing_account(self): | CODE |
| LOW | rest-auth/test_auth.py | 62 | def test_malformed_requests_return_api_errors(self): | CODE |
| LOW⚡ | rest-auth/test_auth.py | 94 | def test_link_rejects_wrong_password_without_mutation(self): | CODE |
| LOW⚡ | rest-auth/test_auth.py | 103 | def test_link_persists_uid_after_valid_password(self): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docker/exporter/entrypoint.sh | 3 | # Check if environment variables (provided as argument list) are set. | COMMENT |
| LOW | tn-cli/tn-cli.py | 111 | # Check if background session is specified explicitly. If not set it to | COMMENT |
| LOW | tn-cli/input_handler.py | 48 | # Check if we have cached input from a previous multiline command. | COMMENT |
| LOW⚡ | tn-cli/commands.py | 466 | # Read file chunks | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | server/main.go | 781 | // TODO: implement serving large files over gRPC, then remove globals.servingAt. | COMMENT |