An organizer for your porn, written in Go. Documentation: https://docs.stashapp.cc
This report summarizes scanner evidence for stashapp/stash, a Go project with 13,330 GitHub stars. SynthScan examined 410,462 lines of code across 1447 source files, recording 453 pattern matches distributed across 7 syntactic categories. The legacy adjusted pattern signal is 1.0 (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? 443 finding(s).
Are imports declared and package/API names verified? 8 finding(s).
Are wrappers, guards, and repeated structures necessary? 366 finding(s).
Which changes need focused human review? 453 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 453 distinct pattern matches across 7 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⚡ | ui/v2.5/src/pluginApi.d.ts | 251 | function refetchAvailablePluginPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 252 | function refetchAvailableScraperPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 253 | function refetchConfigurationQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 256 | function refetchFindDuplicateScenesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 257 | function refetchFindGalleriesForSelectQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 258 | function refetchFindGalleriesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 264 | function refetchFindGroupsForSelectQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 266 | function refetchFindPerformerQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 267 | function refetchFindPerformersForSelectQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 268 | function refetchFindPerformersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 269 | function refetchFindSavedFilterQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 270 | function refetchFindSavedFiltersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 271 | function refetchFindSceneMarkerTagsQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 272 | function refetchFindSceneMarkersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 274 | function refetchFindScenesByPathRegexQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 277 | function refetchFindStudiosForSelectQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 280 | function refetchFindTagsForSelectQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 282 | function refetchInstalledPluginPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 283 | function refetchInstalledPluginPackagesStatusQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 284 | function refetchInstalledScraperPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 285 | function refetchInstalledScraperPackagesStatusQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 287 | function refetchLatestVersionQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 288 | function refetchListGalleryScrapersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 289 | function refetchListGroupScrapersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 290 | function refetchListPerformerScrapersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 291 | function refetchListSceneScrapersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 293 | function refetchMarkerStringsQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 295 | function refetchParseSceneFilenamesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 300 | function refetchScrapeGalleryUrlQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 301 | function refetchScrapeGroupUrlQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 302 | function refetchScrapeMultiPerformersQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 303 | function refetchScrapeMultiScenesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 304 | function refetchScrapePerformerUrlQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 305 | function refetchScrapeSceneUrlQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 306 | function refetchScrapeSingleGalleryQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 307 | function refetchScrapeSinglePerformerQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 308 | function refetchScrapeSingleSceneQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 309 | function refetchScrapeSingleStudioQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 312 | function refetchValidateStashBoxQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 314 | function useAddGalleryImagesMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 316 | function useAnonymiseDatabaseMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 317 | function useAvailablePluginPackagesLazyQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 318 | function useAvailablePluginPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 319 | function useAvailablePluginPackagesSuspenseQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 320 | function useAvailableScraperPackagesLazyQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 321 | function useAvailableScraperPackagesQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 322 | function useAvailableScraperPackagesSuspenseQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 323 | function useBackupDatabaseMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 324 | function useBulkGalleryUpdateMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 325 | function useBulkImageUpdateMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 326 | function useBulkGroupUpdateMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 327 | function useBulkPerformerUpdateMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 328 | function useBulkSceneUpdateMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 329 | function useConfigurationLazyQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 331 | function useConfigurationSuspenseQuery(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 332 | function useConfigureDefaultsMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 334 | function useConfigureGeneralMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 335 | function useConfigureInterfaceMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 336 | function useConfigurePluginMutation(...args: any[]): any; | CODE |
| LOW⚡ | ui/v2.5/src/pluginApi.d.ts | 337 | function useConfigureScrapingMutation(...args: any[]): any; | CODE |
| 304 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | ui/v2.5/src/serviceWorker.ts | 1 | /* XXbiome-ignore no-console */ | COMMENT |
| LOW | ui/v2.5/src/models/list-filter/criteria/stash-ids.ts | 101 | // const asStashIDValue = criterion as StashIdCriterionInput; | COMMENT |
| LOW | ui/v2.5/src/components/List/util.ts | 341 | // of keeping selected items that are no longer in the list, since its not | COMMENT |
| LOW | ui/v2.5/src/hooks/Lightbox/Lightbox.tsx | 141 | const [showOptions, setShowOptions] = useState(false); | COMMENT |
| LOW | ui/v2.5/src/hooks/Interactive/interactive.ts | 61 | // Permission is hereby granted, free of charge, to any person obtaining a copy | COMMENT |
| LOW | docker/production/docker-compose.yml | 21 | - STASH_METADATA=/metadata/ | COMMENT |
| LOW | internal/dlna/dms.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/dms.go | 481 | // XMLName: xml.Name{ | COMMENT |
| LOW | internal/dlna/dms.go | 521 | } | COMMENT |
| LOW | internal/dlna/service.go | 181 | return conn | COMMENT |
| LOW | internal/dlna/service.go | 201 | // }, | COMMENT |
| LOW | internal/dlna/service.go | 221 | // if err != nil { | COMMENT |
| LOW | internal/dlna/cd-service-desc.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/html.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/cm-service-desc.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/cds.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/cds.go | 261 | // for _, playlist := range savedPlaylists { | COMMENT |
| LOW | internal/dlna/xmsr-service-desc.go | 1 | package dlna | COMMENT |
| LOW | internal/dlna/cds_test.go | 1 | package dlna | COMMENT |
| LOW | internal/autotag/performer.go | 41 | // TODO - disabled until we can have finer control over alias matching | COMMENT |
| LOW | internal/autotag/doc.go | 1 | // Package autotag provides the autotagging functionality for the application. | COMMENT |
| LOW | internal/autotag/tagger.go | 1 | // Package autotag provides methods to auto-tag scenes with performers, | COMMENT |
| LOW | internal/manager/generator_sprite.go | 41 | // SpriteInterval will be adjusted accordingly to ensure no more than this many sprites are generated | COMMENT |
| LOW | internal/api/loaders/dataloaders.go | 1 | // Package loaders contains the dataloaders used by the resolver in [api]. | COMMENT |
| LOW | pkg/fsutil/symwalk.go | 1 | // Modified from github.com/facebookgo/symwalk | COMMENT |
| LOW | pkg/fsutil/symwalk.go | 21 | // prior written permission. | COMMENT |
| LOW | pkg/stashbox/draft.go | 101 | // return | COMMENT |
| LOW | pkg/stashbox/draft.go | 121 | // if _, err := io.Copy(part, image); err != nil { | COMMENT |
| LOW | pkg/file/scan.go | 21 | // The scan process works using two goroutines. The first walks through the provided paths | COMMENT |
| LOW | pkg/file/walk.go | 21 | // Redistribution and use in source and binary forms, with or without modification, | COMMENT |
| LOW | pkg/file/walk.go | 41 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | COMMENT |
| LOW | pkg/file/stashignore.go | 41 | // NewStashIgnoreFilter creates a new StashIgnoreFilter. | COMMENT |
| LOW | pkg/match/path.go | 161 | // if !matches { | COMMENT |
| LOW | pkg/plugin/config.go | 41 | // The command to execute for the operations in this plugin. The first | COMMENT |
| LOW | pkg/plugin/config.go | 81 | COMMENT | |
| LOW | pkg/plugin/config.go | 381 | // provided by a plugin. | COMMENT |
| LOW | pkg/plugin/plugins.go | 61 | COMMENT | |
| LOW | pkg/plugin/common/log/log.go | 1 | // Package log provides a number of logging utility functions for encoding and | COMMENT |
| LOW | pkg/utils/strings.go | 1 | package utils | COMMENT |
| LOW | pkg/sqlite/saved_filter_test.go | 101 | // TODO Find | COMMENT |
| LOW | pkg/sqlite/performer_test.go | 2841 | // TODO Update | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 21 | // loops = 100 | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 41 | // } | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 81 | // with a read-only transaction. | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 101 | // // wait for other thread to start | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 121 | // defer wg.Done() | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 141 | // // this takes time to fail, so we need to wait for it | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 221 | COMMENT | |
| LOW | pkg/sqlite/transaction_test.go | 241 | // Title: "test", | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 261 | // }(k) | COMMENT |
| LOW | pkg/sqlite/transaction_test.go | 281 | COMMENT | |
| LOW | pkg/sqlite/gallery_chapter_test.go | 41 | // TODO Update | COMMENT |
| LOW | pkg/sqlite/database.go | 21 | // Number of database read connections to use | COMMENT |
| LOW | pkg/sqlite/scene_marker_test.go | 221 | strconv.Itoa(tagIDs[tagIdxWithMarkers]), | COMMENT |
| LOW | pkg/image/export.go | 81 | // } | COMMENT |
| LOW | pkg/scene/marker_import_test.go | 1 | package scene | COMMENT |
| LOW | pkg/scene/marker_import_test.go | 21 | // func TestMarkerImporterName(t *testing.T) { | COMMENT |
| LOW | pkg/scene/marker_import_test.go | 41 | // }, | COMMENT |
| LOW | pkg/scene/marker_import_test.go | 61 | // i.Input.Tags = []string{ | COMMENT |
| LOW | pkg/scene/marker_import_test.go | 81 | // tags: []*models.Tag{ | COMMENT |
| 17 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | ui/v2.5/src/docs/en/Manual/Tagger.md | 11 | An important thing to note is that it only returns a match *if all query terms are a match*. As an example, if a scene i | CODE |
| LOW | ui/v2.5/src/docs/en/Manual/AutoTagging.md | 15 | ### Examples (performer "Jane Doe") | COMMENT |
| LOW | ui/v2.5/src/components/Shared/FilterSelect.tsx | 40 | | "placeholder" | CODE |
| LOW | pkg/scraper/mapped_result_test.go | 414 | "Name": "Jane Doe", | CODE |
| LOW | pkg/scraper/mapped_result_test.go | 442 | assert.Equal(t, "Jane Doe", *p.Name) | CODE |
| LOW⚡ | pkg/scraper/mapped_result_test.go | 487 | mappedResult{"Name": "Jane Doe"}, | CODE |
| LOW⚡ | pkg/scraper/mapped_result_test.go | 494 | mappedResult{"Name": "Jane Doe"}, | CODE |
| LOW⚡ | pkg/scraper/mapped_result_test.go | 495 | mappedResult{"Name": "John Doe"}, | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | pkg/plugin/examples/python/pyplugin.py | 99 | except ValueError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | docker/production/docker-compose.yml | 30 | ## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pkg/plugin/examples/python/pyplugin.py | 57 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pkg/plugin/examples/python/pyplugin.py | 43 | CODE |