Leaderboard github.com
Anuken/Mindustry
The automation tower defense RTS
AI provenance
0%
possible
- Confidence
- 65%
- Coverage
- 100%
Estimated share of AI-generated code. Explicit attribution is a lower bound.
Code quality
64/100
weak
- Confidence
- 90%
- Coverage
- 100%
Complexity, duplication, lint density, tests, CI, docs and review process.
Security
54/100
weak
- Confidence
- 85%
- Coverage
- 100%
Secrets, static analysis, vulnerable dependencies, CI and supply-chain posture.
AI provenance
0% possible
Weak signals consistent with AI-assisted development. 2 commit(s) carry explicit AI attribution, too few to characterize the codebase.
How the score is built
- Explicitly attributed share0%
- Unattributed share in AI-pace bursts0%
- Estimated AI-generated share0%
- AI tool configuration files0
- Work sessions at AI pace1
- Releases at AI pace0
- Coding-style index (1.0+ means possible)0.02
Attributed AI tools
| Tool | Commits | Lines added | First seen | Last seen |
|---|---|---|---|---|
| GitHub Copilot coding agent | 2 | 45 | 2026-04-12 | 2026-07-18 |
Lines added per month all AI-attributed share
- 2017-043,505 · 0% AI
- 2017-053,202 · 0% AI
- 2017-06637 · 0% AI
- 2017-07593 · 0% AI
- 2017-081,275 · 0% AI
- 2017-092,907 · 0% AI
- 2017-103,397 · 0% AI
- 2017-115,988 · 0% AI
- 2017-1212,549 · 0% AI
- 2018-0117,361 · 0% AI
- 2018-024,951 · 0% AI
- 2018-0313,966 · 0% AI
- 2018-0411,882 · 0% AI
- 2018-0514,144 · 0% AI
- 2018-0620,461 · 0% AI
- 2018-0728,615 · 0% AI
- 2018-086,544 · 0% AI
- 2018-096,765 · 0% AI
- 2018-104,838 · 0% AI
- 2018-116,132 · 0% AI
- 2018-128,033 · 0% AI
- 2019-0112,969 · 0% AI
- 2019-026,640 · 0% AI
- 2019-037,712 · 0% AI
- 2019-046,358 · 0% AI
- 2019-054,089 · 0% AI
- 2019-065,254 · 0% AI
- 2019-073,652 · 0% AI
- 2019-089,558 · 0% AI
- 2019-098,796 · 0% AI
- 2019-108,300 · 0% AI
- 2019-114,912 · 0% AI
- 2019-1211,305 · 0% AI
- 2020-017,537 · 0% AI
- 2020-0220,245 · 0% AI
- 2020-039,960 · 0% AI
- 2020-044,118 · 0% AI
- 2020-0517,508 · 0% AI
- 2020-0610,239 · 0% AI
- 2020-077,703 · 0% AI
- 2020-0810,418 · 0% AI
- 2020-097,557 · 0% AI
- 2020-109,245 · 0% AI
- 2020-116,024 · 0% AI
- 2020-122,418 · 0% AI
- 2021-011,231 · 0% AI
- 2021-022,844 · 0% AI
- 2021-031,092 · 0% AI
- 2021-04185 · 0% AI
- 2021-05178 · 0% AI
- 2021-0617,125 · 0% AI
- 2021-072,962 · 0% AI
- 2021-082,960 · 0% AI
- 2021-091,945 · 0% AI
- 2021-103,766 · 0% AI
- 2021-117,303 · 0% AI
- 2021-126,627 · 0% AI
- 2022-013,428 · 0% AI
- 2022-0215,245 · 0% AI
- 2022-032,133 · 0% AI
- 2022-044,848 · 0% AI
- 2022-053,811 · 0% AI
- 2022-063,142 · 0% AI
- 2022-074,249 · 0% AI
- 2022-081,415 · 0% AI
- 2022-091,065 · 0% AI
- 2022-102,065 · 0% AI
- 2022-11513 · 0% AI
- 2022-1291 · 0% AI
- 2023-01718 · 0% AI
- 2023-02645 · 0% AI
- 2023-03891 · 0% AI
- 2023-04814 · 0% AI
- 2023-051,965 · 0% AI
- 2023-06951 · 0% AI
- 2023-07283 · 0% AI
- 2023-081,018 · 0% AI
- 2023-092,789 · 0% AI
- 2023-10526 · 0% AI
- 2023-113,175 · 0% AI
- 2023-121,722 · 0% AI
- 2024-01878 · 0% AI
- 2024-02576 · 0% AI
- 2024-03895 · 0% AI
- 2024-042,909 · 0% AI
- 2024-05761 · 0% AI
- 2024-061,513 · 0% AI
- 2024-07349 · 0% AI
- 2024-08514 · 0% AI
- 2024-091,171 · 0% AI
- 2024-101,543 · 0% AI
- 2024-11332 · 0% AI
- 2024-12106 · 0% AI
- 2025-012,337 · 0% AI
- 2025-022,787 · 0% AI
- 2025-033 · 0% AI
- 2025-044,746 · 0% AI
- 2025-052,273 · 0% AI
- 2025-06846 · 0% AI
- 2025-073,428 · 0% AI
- 2025-08667 · 0% AI
- 2025-091,504 · 0% AI
- 2025-102,296 · 0% AI
- 2025-111,157 · 0% AI
- 2025-122,427 · 0% AI
- 2026-01794 · 0% AI
- 2026-021,854 · 0% AI
- 2026-032,552 · 0% AI
- 2026-041,514 · 0% AI
- 2026-053,258 · 0% AI
- 2026-065,804 · 0% AI
- 2026-073,510 · 1% AI
- 2026-085,333 · 0% AI
- 2026-092,965 · 0% AI
- 2026-10127 · 0% AI
- 2026-111 · 0% AI
Findings in AI-attributed lines vs the rest
From git blame: 4 lines trace to AI-attributed commits, 183,223 to others. Too few lines in one group for a fair comparison. Reported, not scored.
| Findings per 1,000 lines | AI-attributed | Other | Ratio |
|---|---|---|---|
| Code quality | 0.00 | 0.21 | — |
| Security | 0.00 | 0.03 | — |
Evidence by analyzer
Explicit AI attributionok3 items
- GitHub Copilot coding agent: 2 attributed commits, 45 lines added
- GitHub Copilot coding agent: trailer 'Co-authored-by: Copilot'
- GitHub Copilot coding agent: trailer 'Co-authored-by: Copilot'
- attributed_commit_share
- 0.0%
- attributed_commits
- 2
- attributed_loc
- 45
- attributed_loc_share
- 0.0%
- commits
- 18,350
- effective_loc
- 549,712
- tools_detected
- 1
AI tool configurationok
- artifacts
- 0
- tools_configured
- 0
- workflow_agents
- 0
Commit velocityok1 item
- excluded_import_loc
- 42,934
- flagged_loc
- 1,283
- flagged_loc_share
- 0.3%
- flagged_units
- 1
- max_loc_per_hour
- 2,308.42
- measured_loc
- 506,778
- median_loc_per_hour
- 54.16
- pr_timed_units
- 783
- pre_ai_era_burst_loc
- 24,693
- pre_ai_era_bursts
- 12
- pre_ai_era_measured_loc
- 359,926
- work_units
- 8,975
Release velocityok
- flagged_releases
- 0
- max_loc_per_day
- 519.70
- releases
- 99
Coding styleok2 items
- step-by-step narration comment: //then, if it's shown and the current block 'agrees' to hide, hide it.
- step-by-step narration comment: //first, find a planets associated with the current tech tree
- count:assistant_voice
- 0
- count:emoji_in_code
- 2
- count:narrated_steps
- 2
- count:placeholder
- 0
- files:assistant_voice
- 0
- files:emoji_in_code
- 2
- files:narrated_steps
- 2
- files:placeholder
- 0
- index
- 0.02
- lines_scanned
- 183,227
- per_kloc:assistant_voice
- 0
- per_kloc:emoji_in_code
- 0.01
- per_kloc:narrated_steps
- 0.01
- per_kloc:placeholder
- 0
Findings in AI-written linesok
- ai_lines
- 4
- blame_failures
- 0
- files_blamed
- 865
- other_lines
- 183,223
- quality:ai_findings
- 0
- quality:ai_per_kloc
- 0
- quality:other_findings
- 39
- quality:other_per_kloc
- 0.21
- security:ai_findings
- 0
- security:ai_per_kloc
- 0
- security:other_findings
- 5
- security:other_per_kloc
- 0.03
Code quality
64 weak
Code quality is weak: test-to-source ratio 0.02, CI runs tests; 34% of function code in complex or long functions; 4% duplicated lines. Weakest area: complexity.
How the score is built
- Complexity36
- Duplication78
- Lint and smells86
- Tests and CI57
- Documentation80
- Type safetynot measured
- Review process65
Evidence by analyzer
Complexity (lizard)ok10 items
- EntityProcess::process in annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java: complexity 196, 542 lines
- Generators::run in tools/src/mindustry/tools/Generators.java: complexity 190, 624 lines
- GameService::registerEvents in core/src/mindustry/service/GameService.java: complexity 175, 367 lines
- ServerControl::registerCommands in server/src/mindustry/server/ServerControl.java: complexity 159, 731 lines
- DesktopInput::pollInputPlayer in core/src/mindustry/input/DesktopInput.java: complexity 156, 263 lines
- DesktopInput::update in core/src/mindustry/input/DesktopInput.java: complexity 146, 244 lines
- SerpuloPlanetGenerator::generate in core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java: complexity 138, 328 lines
- CommandAI::defaultBehavior in core/src/mindustry/ai/types/CommandAI.java: complexity 125, 167 lines
- HudFragment::build in core/src/mindustry/ui/fragments/HudFragment.java: complexity 114, 381 lines
- ErekirPlanetGenerator::generate in core/src/mindustry/maps/planet/ErekirPlanetGenerator.java: complexity 107, 219 lines
- complex_functions
- 331
- function_nloc
- 112,611
- functions
- 10,022
- long_functions
- 81
- many_param_functions
- 94
- mean_ccn
- 3.44
- p90_ccn
- 7
- risky_nloc_share
- 34.3%
Duplication (jscpd)ok10 items
- 6+ duplicated lines: core/assets/scripts/base.js:1 and core/assets/scripts/global.js:3
- 6+ duplicated lines: core/src/mindustry/ai/BlockIndexer.java:347 and core/src/mindustry/ai/BlockIndexer.java:373
- 6+ duplicated lines: core/src/mindustry/ai/ControlPathfinder.java:405 and core/src/mindustry/ai/Pathfinder.java:289
- 6+ duplicated lines: core/src/mindustry/ai/ControlPathfinder.java:1391 and core/src/mindustry/ai/ControlPathfinder.java:1456
- 6+ duplicated lines: core/src/mindustry/ai/UnitCommand.java:56 and core/src/mindustry/ai/UnitStance.java:65
- 6+ duplicated lines: core/src/mindustry/ai/types/BuilderAI.java:46 and core/src/mindustry/ai/types/PrebuildAI.java:100
- 6+ duplicated lines: core/src/mindustry/ai/types/BuilderAI.java:113 and core/src/mindustry/world/blocks/defense/BuildTurret.java:199
- 6+ duplicated lines: core/src/mindustry/ai/types/CommandAI.java:219 and core/src/mindustry/input/InputHandler.java:579
- 6+ duplicated lines: core/src/mindustry/ai/types/MinerAI.java:45 and core/src/mindustry/ai/types/PrebuildAI.java:197
- 6+ duplicated lines: core/src/mindustry/audio/SoundControl.java:444 and core/src/mindustry/audio/SoundControl.java:554
- compared_lines
- 116,227
- duplicated_lines
- 4,752
- duplicated_share
- 4.1%
- files
- 865
Lintok
- category:correctness
- 39
- findings
- 39
- scanned_lines
- 183,227
- weighted_findings
- 107.50
Tests and CIok5 items
- CI config: .github/workflows/deployment.yml
.github/workflows/deployment.yml - CI config: .github/workflows/gradle-wrapper-validation.yml
.github/workflows/gradle-wrapper-validation.yml - CI config: .github/workflows/pr.yml
.github/workflows/pr.yml - CI config: .github/workflows/push.yml
.github/workflows/push.yml - CI runs tests (gradlew test)
- check:ci_present
- yes
- check:ci_runs_lint
- no
- check:ci_runs_tests
- yes
- check:has_tests
- yes
- check:test_ratio
- no
- check:tests_cochange
- no
- ci_files
- 4
- cochange_commits
- 194
- cochange_share
- 2.6%
- source_lines
- 183,227
- test_lines
- 2,835
- test_ratio
- 0.02
Documentationok3 items
- README.md
README.md - LICENSE
LICENSE - CONTRIBUTING.md
CONTRIBUTING.md
- check:changelog
- no
- check:contributing
- yes
- check:license
- yes
- check:readme
- yes
- readme_lines
- 49
Type safetyskipped
Security
54 weak
Security posture is weak: 0 possible secret(s) in the tree, 1 only in history; 15 high-severity workflow issues. Weakest area: posture.
How the score is built
- Secrets82
- Static analysis (SAST)100
- Vulnerable dependenciesnot measured
- CI workflows5
- Security posture0
- OpenSSF Scorecard25
Evidence by analyzer
OpenSSF Scorecardok13 items
- Scorecard Dangerous-Workflow: 10/10 (no dangerous workflow patterns detected)
- Scorecard Maintained: 10/10 (30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10)
- Scorecard Code-Review: 3/10 (Found 11/30 approved changesets -- score normalized to 3)
- Scorecard Token-Permissions: 0/10 (detected GitHub workflow tokens with excessive permissions)
- Scorecard CII-Best-Practices: 0/10 (no effort to earn an OpenSSF best practices badge detected)
- Scorecard Security-Policy: 0/10 (security policy file not detected)
- Scorecard Pinned-Dependencies: 0/10 (dependency not pinned by hash detected -- score normalized to 0)
- Scorecard License: 10/10 (license file detected)
- Scorecard Fuzzing: 0/10 (project is not fuzzed)
- Scorecard Signed-Releases: 0/10 (Project has not signed or included provenance with any releases.)
- Scorecard Branch-Protection: 0/10 (branch protection not enabled on development/release branches)
- Scorecard SAST: 0/10 (SAST tool is not run on all commits -- score normalized to 0)
- Scorecard Binary-Artifacts: 10/10 (no binaries found in the repo)
- aggregate
- 3.70
- check:Binary-Artifacts
- yes
- check:Branch-Protection
- no
- check:CII-Best-Practices
- no
- check:Code-Review
- yes
- check:Dangerous-Workflow
- yes
- check:Fuzzing
- no
- check:License
- yes
- check:Maintained
- yes
- check:Pinned-Dependencies
- no
- check:SAST
- no
- check:Security-Policy
- no
- check:Signed-Releases
- no
- check:Token-Permissions
- no
Package registriesskipped
no registry dependencies declared
Secrets (gitleaks)ok
- secrets_current
- 0
- secrets_history
- 1
- secrets_low_confidence
- 1
- secrets_nonprod
- 0
Static analysis (opengrep)ok
- findings
- 6
- findings_high
- 0
- findings_low
- 0
- findings_medium
- 6
- parse_errors
- 1
- scanned_lines
- 183,227
- weighted_findings
- 2.60
Dependencies (osv-scanner)skipped
CI workflows (zizmor)ok
- findings
- 24
- findings_high
- 15
- findings_low
- 8
- findings_medium
- 1
- penalty
- 183.60
- workflows
- 4
Security postureok
- check:dependency_updates
- no
- check:lockfiles
- yes
- check:security_policy
- no
- check:signed_commits
- no
- signed_commit_share
- 31.5%
- unpinned_manifests
- 0
Release downloadsok5 items
- release v160.7 ships assets.jar (2156 downloads)
- release v160.7 ships dependencies.jar (3416 downloads)
- release v160.7 ships Mindustry.jar (19644 downloads)
- release v160.7 ships server-release.jar (7447 downloads)
- release v160.6 ships assets.jar (237 downloads)
- binary_assets
- 40
- signals
- 1
- suspicious
- 0
Findings
50 high10 medium7 low4 info
| Severity | Rule | Location | Message | Tool |
|---|---|---|---|---|
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/ai/types/BuilderAI.java:153 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/core/NetServer.java:501 | `sign == sign` or `sign != sign` is always true. (Unless the value compared is a float or double). To test if `sign` is not-a-number, use `Double.isNaN(sign)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Damage.java:408 | `tmpUnit == tmpUnit` or `tmpUnit != tmpUnit` is always true. (Unless the value compared is a float or double). To test if `tmpUnit` is not-a-number, use `Double.isNaN(tmpUnit)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/EntityCollisions.java:38 | `deltax == deltax` or `deltax != deltax` is always true. (Unless the value compared is a float or double). To test if `deltax` is not-a-number, use `Double.isNaN(deltax)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/EntityCollisions.java:38 | `deltay == deltay` or `deltay != deltay` is always true. (Unless the value compared is a float or double). To test if `deltay` is not-a-number, use `Double.isNaN(deltay)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:238 | `buildResult == buildResult` or `buildResult != buildResult` is always true. (Unless the value compared is a float or double). To test if `buildResult` is not-a-number, use `Double.isNaN(buildResult)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:307 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:329 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:366 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:384 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/Units.java:403 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/entities/bullet/PointBulletType.java:51 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/game/Schematics.java:350 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/BlockRenderer.java:709 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/BlockRenderer.java:763 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/BlockRenderer.java:770 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/BlockRenderer.java:861 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/FloorRenderer.java:375 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/LoadRenderer.java:132 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/graphics/LoadRenderer.java:83 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/logic/LCanvas.java:264 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/maps/Maps.java:471 | `result == result` or `result != result` is always true. (Unless the value compared is a float or double). To test if `result` is not-a-number, use `Double.isNaN(result)`. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/maps/generators/BaseGenerator.java:216 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/maps/generators/BaseGenerator.java:90 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/mod/ContentParser.java:1278 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/net/ArcNetProvider.java:497 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/net/ArcNetProvider.java:544 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/net/ArcNetProvider.java:583 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/ui/builder/UiDslWriter.java:87 | `f == f` or `f != f` is always true. (Unless the value compared is a float or double). To test if `f` is not-a-number, use `Double.isNaN(f)`. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/ui/fragments/HudFragment.java:676 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/world/blocks/defense/BuildTurret.java:177 | `following == following` or `following != following` is always true. (Unless the value compared is a float or double). To test if `following` is not-a-number, use `Double.isNaN(following)`. | Lint |
| high | opengrep/java.lang.correctness.eqeq |
core/src/mindustry/world/blocks/distribution/DirectionBridge.java:79 | `otherPlan == otherPlan` or `otherPlan != otherPlan` is always true. (Unless the value compared is a float or double). To test if `otherPlan` is not-a-number, use `Double.isNaN(otherPlan)`. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/world/blocks/units/UnitFactory.java:59 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
core/src/mindustry/world/blocks/units/UnitFactory.java:70 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | opengrep/java.lang.correctness.hardcoded-conditional |
tools/src/mindustry/tools/Generators.java:535 | This if statement will always have the same behavior and is therefore unnecessary. | Lint |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:17 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:19 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:64 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:70 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:77 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/deployment.yml:85 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/gradle-wrapper-validation.yml:10 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/gradle-wrapper-validation.yml:9 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/pr.yml:13 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/pr.yml:15 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/pr.yml:22 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/pr.yml:28 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/push.yml:14 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/push.yml:25 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| high | zizmor/unpinned-uses |
.github/workflows/push.yml:32 | unpinned action reference [confidence high] | CI workflows (zizmor) |
| medium | opengrep/java.lang.correctness.no-string-eqeq |
core/src/mindustry/game/Team.java:180 | Strings should not be compared with '=='. This is a reference comparison operator. Use '.equals()' instead. | Lint |
| medium | opengrep/java.lang.correctness.no-string-eqeq |
core/src/mindustry/logic/LStatements.java:1334 | Strings should not be compared with '=='. This is a reference comparison operator. Use '.equals()' instead. | Lint |
| medium | zizmor/excessive-permissions |
.github/workflows/gradle-wrapper-validation.yml:5 | overly broad permissions [confidence medium] | CI workflows (zizmor) |
| medium | opengrep/java.android.security.exported_activity |
android/AndroidManifest.xml:23 | The application exports an activity. Any application on the device can launch the exported activity which may compromise the integrity of your application or its data. Ensure that any exported activities do not have privileged access... | Static analysis (opengrep) |
| medium | opengrep/java.lang.security.audit.unsafe-reflection |
core/src/mindustry/maps/MapPreviewLoader.java:67 | If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not... | Static analysis (opengrep) |
| medium | opengrep/java.lang.security.audit.unsafe-reflection |
core/src/mindustry/mod/ContentParser.java:1444 | If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not... | Static analysis (opengrep) |
| medium | opengrep/java.lang.security.audit.unsafe-reflection |
core/src/mindustry/mod/ContentParser.java:1448 | If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not... | Static analysis (opengrep) |
| medium | opengrep/java.lang.security.audit.unsafe-reflection |
core/src/mindustry/mod/Mods.java:1191 | If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not... | Static analysis (opengrep) |
| medium | gitleaks/discord-client-id |
desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java:33 | Possible discord-client-id secret in history (commit c9f0a59339); removed from the current tree but still retrievable | Secrets (gitleaks) |
| medium | opengrep/java.lang.security.audit.crypto.unencrypted-socket |
server/src/mindustry/server/ServerControl.java:1434 | Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead. [confidence high] | Static analysis (opengrep) |
| low | opengrep/bash.lang.correctness.unquoted-variable-expansion-in-command |
ios/convert_audio.sh:3 | Variable expansions must be double-quoted so as to prevent being split into multiple pieces according to whitespace or whichever separator is specified by the IFS variable. If you really wish to split the variable's contents, you may... | Lint |
| low | opengrep/bash.lang.correctness.unquoted-variable-expansion-in-command |
ios/convert_audio.sh:7 | Variable expansions must be double-quoted so as to prevent being split into multiple pieces according to whitespace or whichever separator is specified by the IFS variable. If you really wish to split the variable's contents, you may... | Lint |
| low | zizmor/artipacked |
.github/workflows/deployment.yml:17 | credential persistence through GitHub Actions artifacts [confidence low] | CI workflows (zizmor) |
| low | zizmor/artipacked |
.github/workflows/gradle-wrapper-validation.yml:9 | credential persistence through GitHub Actions artifacts [confidence low] | CI workflows (zizmor) |
| low | zizmor/artipacked |
.github/workflows/pr.yml:13 | credential persistence through GitHub Actions artifacts [confidence low] | CI workflows (zizmor) |
| low | zizmor/artipacked |
.github/workflows/push.yml:14 | credential persistence through GitHub Actions artifacts [confidence low] | CI workflows (zizmor) |
| low | gitleaks/generic-api-key |
core/assets/bundles/bundle_sr.properties:1615 | Possible generic-api-key secret in the current tree | Secrets (gitleaks) |
| info | zizmor/superfluous-actions |
.github/workflows/deployment.yml:64 | action functionality is already included by the runner [confidence high] | CI workflows (zizmor) |
| info | zizmor/superfluous-actions |
.github/workflows/deployment.yml:70 | action functionality is already included by the runner [confidence high] | CI workflows (zizmor) |
| info | zizmor/superfluous-actions |
.github/workflows/deployment.yml:77 | action functionality is already included by the runner [confidence high] | CI workflows (zizmor) |
| info | zizmor/superfluous-actions |
.github/workflows/deployment.yml:85 | action functionality is already included by the runner [confidence high] | CI workflows (zizmor) |
Tools and coverage
Every analyzer that ran on this commit. A failed or skipped tool is a coverage gap: its share of the score is left out and the coverage figure drops.
| Analyzer | Pillar | Status | Version | Findings | Note |
|---|---|---|---|---|---|
| AI tool configuration | AI provenance | ok | signatures-v1 | 0 | |
| Explicit AI attribution | AI provenance | ok | signatures-v1 | 0 | |
| Release velocity | AI provenance | ok | prov-5 | 0 | |
| Coding style | AI provenance | ok | — | 0 | |
| Commit velocity | AI provenance | ok | prov-5 | 0 | |
| Findings in AI-written lines | AI provenance | ok | git-blame | 0 | |
| Complexity (lizard) | Code quality | ok | lizard 1.25.1 | 0 | |
| Documentation | Code quality | ok | — | 0 | |
| Duplication (jscpd) | Code quality | ok | repotrust-dup-w6 | 0 | |
| Lint | Code quality | ok | opengrep 1.33.1; rules f1d2b562b414 | 39 | |
| Tests and CI | Code quality | ok | — | 0 | |
| Type safety | Code quality | skipped | — | 0 | |
| CI workflows (zizmor) | Security | ok | zizmor 1.32.0 | 24 | |
| Dependencies (osv-scanner) | Security | skipped | — | 0 | |
| Release downloads | Security | ok | — | 0 | |
| Security posture | Security | ok | — | 0 | |
| Package registries | Security | skipped | — | 0 | no registry dependencies declared |
| Static analysis (opengrep) | Security | ok | opengrep 1.33.1; rules f1d2b562b414 | 6 | |
| OpenSSF Scorecard | Security | ok | scorecard v5.6.0 | 0 | |
| Secrets (gitleaks) | Security | ok | gitleaks 8.30.1 | 2 |
Score history
| Scored | Commit | Scoring | AI provenance | Quality | Security |
|---|---|---|---|---|---|
| 2026-11-14 | 1a22b880576d | prov-5+qual-2+sec-2 | 0% | 64 | 54 |
Full text report
- Repository: https://github.com/Anuken/Mindustry
- Commit:
1a22b880576d2f8f97550280f76bfdd0d0069543 - Generated: 2026-11-14T15:13:42+00:00
- Scorer 0.1.0, scoring prov-5+qual-2+sec-2, report schema v2
Scores
| Pillar | Score | Signal | Confidence | Coverage |
|---|---|---|---|---|
| AI provenance (estimated AI-generated share) | 0 | possible | 65% | 100% |
| Code quality | 64 | weak | 90% | 100% |
| Security | 54 | weak | 85% | 100% |
AI provenance
Weak signals consistent with AI-assisted development. 2 commit(s) carry explicit AI attribution, too few to characterize the codebase.
- Explicitly attributed share (lower bound): 0.0%
- Unattributed share in AI-consistent velocity bursts: 0.2%
- Estimated AI-generated share: 0.0%
| AI tool | Attributed commits | Lines added |
|---|---|---|
| GitHub Copilot coding agent | 2 | 45 |
Current source lines last changed by AI-attributed commits: 4 of 183,227.
Too few lines in one group to compare finding densities.
- Stylometry index: 0.02 per 1,000 lines (narrated steps 2, placeholders 0, assistant phrasing 0, emoji 2). Reported as a signal, not scored.
| Month | Lines added | Attributed to AI |
|---|---|---|
| 2025-12 | 2,427 | 0% |
| 2026-01 | 794 | 0% |
| 2026-02 | 1,854 | 0% |
| 2026-03 | 2,552 | 0% |
| 2026-04 | 1,514 | 0% |
| 2026-05 | 3,258 | 0% |
| 2026-06 | 5,804 | 0% |
| 2026-07 | 3,510 | 1% |
| 2026-08 | 5,333 | 0% |
| 2026-09 | 2,965 | 0% |
| 2026-10 | 127 | 0% |
| 2026-11 | 1 | 0% |
Evidence
- GitHub Copilot coding agent: trailer 'Co-authored-by: Copilot' (8713c4174166)
- GitHub Copilot coding agent: trailer 'Co-authored-by: Copilot' (67c06d167d28)
- 1,283 lines of first-party code in ~1.5h (829 lines/hour, 2 commit session) (3a7d7647d98e)
- step-by-step narration comment: //then, if it's shown and the current block 'agrees' to hide, hide it. (core/src/min)
- step-by-step narration comment: //first, find a planets associated with the current tech tree (core/src/min)
AI provenance describes how code was produced; it is not a quality judgment. Unless attribution is explicit, these are signals consistent with AI generation, not proof. Squash/rebase workflows, imported code, and rewritten history reduce accuracy.
Code quality
Code quality is weak: test-to-source ratio 0.02, CI runs tests; 34% of function code in complex or long functions; 4% duplicated lines. Weakest area: complexity.
| Area | Score |
|---|---|
| Complexity (lizard) | 36 |
| Duplication | 78 |
| Code smells (Opengrep) | 86 |
| Tests and CI | 57 |
| Documentation | 80 |
| Type safety | n/a |
| Process (Scorecard review/maintenance) | 65 |
- Functions: 10,022; mean complexity 3.4, 90th percentile 7; 331 complex and 81 long functions
- Duplicated lines: 4.1% of 116,227 compared
- Tests: 2,835 test lines for 183,227 source lines (ratio 0.02); CI test commands: gradlew test; 3% of recent source commits also change tests
- Docs missing or thin: changelog
Most complex functions:
- EntityProcess::process in annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java: complexity 196, 542 lines
- Generators::run in tools/src/mindustry/tools/Generators.java: complexity 190, 624 lines
- GameService::registerEvents in core/src/mindustry/service/GameService.java: complexity 175, 367 lines
- ServerControl::registerCommands in server/src/mindustry/server/ServerControl.java: complexity 159, 731 lines
- DesktopInput::pollInputPlayer in core/src/mindustry/input/DesktopInput.java: complexity 156, 263 lines
Security
Security posture is weak: 0 possible secret(s) in the tree, 1 only in history; 15 high-severity workflow issues. Weakest area: posture.
| Area | Score |
|---|---|
| Secrets (gitleaks, tree + history) | 82 |
| Static analysis (Opengrep) | 100 |
| Vulnerable dependencies (OSV) | n/a |
| CI workflows (zizmor) | 5 |
| Posture (policy, updates, signing, lockfiles) | 0 |
| OpenSSF Scorecard | 25 |
- Posture checks passed: lockfiles; missing: security policy, dependency updates, signed commits
- OpenSSF Scorecard aggregate: 3.7/10 (published 2026-11-09)
Top findings
| Severity | Finding | Location |
|---|---|---|
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:17 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:19 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:64 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:70 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:77 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/deployment.yml:85 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/gradle-wrapper-validation.yml:9 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/gradle-wrapper-validation.yml:10 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/pr.yml:13 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/pr.yml:15 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/pr.yml:22 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/pr.yml:28 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/push.yml:14 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/push.yml:25 |
| high | zizmor/unpinned-uses: unpinned action reference [confidence high] |
.github/workflows/push.yml:32 |
| medium | gitleaks/discord-client-id: Possible discord-client-id secret in history (commit c9f0a59339); removed from the current tree but still retrievable |
desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java:33 |
| medium | opengrep/java.android.security.exported_activity: The application exports an activity. Any application on the device can launch the exported activity which may compromise the integrity of your application or its data. Ensure that any exported activities do not have privileged access to your application's control plane. [confidence medium] |
android/AndroidManifest.xml:23 |
| medium | opengrep/java.lang.security.audit.unsafe-reflection: If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may a [confidence low] |
core/src/mindustry/maps/MapPreviewLoader.java:67 |
| medium | opengrep/java.lang.security.audit.unsafe-reflection: If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may a [confidence low] |
core/src/mindustry/mod/ContentParser.java:1444 |
| medium | opengrep/java.lang.security.audit.unsafe-reflection: If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may a [confidence low] |
core/src/mindustry/mod/ContentParser.java:1448 |
| medium | opengrep/java.lang.security.audit.unsafe-reflection: If an attacker can supply values that the application then uses to determine which class to instantiate or which method to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may a [confidence low] |
core/src/mindustry/mod/Mods.java:1191 |
| medium | opengrep/java.lang.security.audit.crypto.unencrypted-socket: Detected use of a Java socket that is not encrypted. As a result, the traffic could be read by an attacker intercepting the network traffic. Use an SSLSocket created by 'SSLSocketFactory' or 'SSLServerSocketFactory' instead. [confidence high] |
server/src/mindustry/server/ServerControl.java:1434 |
| medium | zizmor/excessive-permissions: overly broad permissions [confidence medium] |
.github/workflows/gradle-wrapper-validation.yml:5 |
| low | gitleaks/generic-api-key: Possible generic-api-key secret in the current tree |
core/assets/bundles/bundle_sr.properties:1615 |
| low | zizmor/artipacked: credential persistence through GitHub Actions artifacts [confidence low] |
.github/workflows/deployment.yml:17 |
Static signals only: the scorer never runs the project's code. Secret findings are pattern matches that were not verified, and secret values are never stored.
Distribution signals
- binary-release-asset: release v160.7 ships assets.jar (2156 downloads)
- binary-release-asset: release v160.7 ships dependencies.jar (3416 downloads)
- binary-release-asset: release v160.7 ships Mindustry.jar (19644 downloads)
- binary-release-asset: release v160.7 ships server-release.jar (7447 downloads)
- binary-release-asset: release v160.6 ships assets.jar (237 downloads)
Signals consistent with a repository that exists to distribute a download. They are heuristics, not a verdict; release files were not downloaded or inspected.
Repository profile
- Source lines: 183,227; test lines: 2,835
| Language | Lines |
|---|---|
| Java | 185,760 |
| JavaScript | 285 |
| Shell | 17 |