compose-lint 0.28.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. compose_lint-0.28.0/.githooks/pre-push +37 -0
  2. compose_lint-0.28.0/.github/CODEOWNERS +8 -0
  3. compose_lint-0.28.0/.github/CODE_OF_CONDUCT.md +83 -0
  4. compose_lint-0.28.0/.github/ISSUE_TEMPLATE/bug_report.yml +98 -0
  5. compose_lint-0.28.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  6. compose_lint-0.28.0/.github/ISSUE_TEMPLATE/feature_request.yml +45 -0
  7. compose_lint-0.28.0/.github/ISSUE_TEMPLATE/other.yml +27 -0
  8. compose_lint-0.28.0/.github/ISSUE_TEMPLATE/rule_proposal.yml +101 -0
  9. compose_lint-0.28.0/.github/SECURITY.md +49 -0
  10. compose_lint-0.28.0/.github/actions/update-dockerhub-description/action.yml +47 -0
  11. compose_lint-0.28.0/.github/allowed_signers +30 -0
  12. compose_lint-0.28.0/.github/pull_request_template.md +95 -0
  13. compose_lint-0.28.0/.github/renovate.json +91 -0
  14. compose_lint-0.28.0/.github/scripts/install-compose-plugin.sh +65 -0
  15. compose_lint-0.28.0/.github/scripts/patch-coverage.py +218 -0
  16. compose_lint-0.28.0/.github/workflows/cflite-batch.yml +60 -0
  17. compose_lint-0.28.0/.github/workflows/cflite-pr.yml +42 -0
  18. compose_lint-0.28.0/.github/workflows/ci.yml +1362 -0
  19. compose_lint-0.28.0/.github/workflows/codeql.yml +55 -0
  20. compose_lint-0.28.0/.github/workflows/dockerhub-description.yml +50 -0
  21. compose_lint-0.28.0/.github/workflows/docs.yml +71 -0
  22. compose_lint-0.28.0/.github/workflows/eol-watch.yml +102 -0
  23. compose_lint-0.28.0/.github/workflows/forgejo-smoke.yml +44 -0
  24. compose_lint-0.28.0/.github/workflows/marketplace-smoke.yml +276 -0
  25. compose_lint-0.28.0/.github/workflows/os-smoke.yml +163 -0
  26. compose_lint-0.28.0/.github/workflows/publish-channel.yml +307 -0
  27. compose_lint-0.28.0/.github/workflows/publish.yml +973 -0
  28. compose_lint-0.28.0/.github/workflows/release-docker-smoke.yml +131 -0
  29. compose_lint-0.28.0/.github/workflows/release-prep.yml +275 -0
  30. compose_lint-0.28.0/.github/workflows/sarif-ingestion.yml +174 -0
  31. compose_lint-0.28.0/.github/workflows/scorecard.yml +72 -0
  32. compose_lint-0.28.0/.github/workflows/scout-scan.yml +129 -0
  33. compose_lint-0.28.0/.github/workflows/verify-tag.yml +79 -0
  34. compose_lint-0.28.0/.github/workflows/vuln-report.yml +170 -0
  35. compose_lint-0.28.0/.gitignore +88 -0
  36. compose_lint-0.28.0/.pre-commit-hooks.yaml +20 -0
  37. compose_lint-0.28.0/.vex/compose-lint.openvex.json +103 -0
  38. compose_lint-0.28.0/CHANGELOG.md +3394 -0
  39. compose_lint-0.28.0/CONTRIBUTING.md +389 -0
  40. compose_lint-0.28.0/GOVERNANCE.md +112 -0
  41. compose_lint-0.28.0/LICENSE +21 -0
  42. compose_lint-0.28.0/LICENSE-corpus.md +45 -0
  43. compose_lint-0.28.0/MAINTAINERS.md +36 -0
  44. compose_lint-0.28.0/PKG-INFO +612 -0
  45. compose_lint-0.28.0/README.md +555 -0
  46. compose_lint-0.28.0/action.yml +280 -0
  47. compose_lint-0.28.0/docs/ASSURANCE.md +172 -0
  48. compose_lint-0.28.0/docs/CI.md +502 -0
  49. compose_lint-0.28.0/docs/CONTINUITY.md +127 -0
  50. compose_lint-0.28.0/docs/DISTRIBUTION.md +78 -0
  51. compose_lint-0.28.0/docs/MAINTAINING.md +152 -0
  52. compose_lint-0.28.0/docs/RELEASING.md +611 -0
  53. compose_lint-0.28.0/docs/ROADMAP.md +146 -0
  54. compose_lint-0.28.0/docs/SECURITY-EXPECTATIONS.md +144 -0
  55. compose_lint-0.28.0/docs/adr/001-python.md +14 -0
  56. compose_lint-0.28.0/docs/adr/002-rule-grounding.md +12 -0
  57. compose_lint-0.28.0/docs/adr/003-yaml-parsing.md +42 -0
  58. compose_lint-0.28.0/docs/adr/004-rule-architecture.md +13 -0
  59. compose_lint-0.28.0/docs/adr/005-rule-id-scheme.md +19 -0
  60. compose_lint-0.28.0/docs/adr/006-exit-codes.md +22 -0
  61. compose_lint-0.28.0/docs/adr/007-shellcheck-integration.md +23 -0
  62. compose_lint-0.28.0/docs/adr/008-linux-packages.md +35 -0
  63. compose_lint-0.28.0/docs/adr/009-runtime-base-image.md +22 -0
  64. compose_lint-0.28.0/docs/adr/010-per-service-rule-overrides.md +58 -0
  65. compose_lint-0.28.0/docs/adr/011-config-bootstrap-ux.md +164 -0
  66. compose_lint-0.28.0/docs/adr/012-vex-product-identifier.md +69 -0
  67. compose_lint-0.28.0/docs/adr/013-missing-services-key.md +346 -0
  68. compose_lint-0.28.0/docs/adr/014-fix-remediation.md +577 -0
  69. compose_lint-0.28.0/docs/adr/015-machine-readable-output-contract.md +112 -0
  70. compose_lint-0.28.0/docs/adr/016-runtime-rule-premise-validation.md +131 -0
  71. compose_lint-0.28.0/docs/adr/017-security-profile-catalog.md +385 -0
  72. compose_lint-0.28.0/docs/adr/018-confidence-as-multi-axis.md +145 -0
  73. compose_lint-0.28.0/docs/adr/019-withdraw-security-profile-catalog.md +78 -0
  74. compose_lint-0.28.0/docs/adr/020-severity-scoping-and-overrides.md +394 -0
  75. compose_lint-0.28.0/docs/adr/021-critical-tier-posture.md +129 -0
  76. compose_lint-0.28.0/docs/adr/022-threat-model-grounding.md +126 -0
  77. compose_lint-0.28.0/docs/adr/023-deploy-host-independent-claims.md +83 -0
  78. compose_lint-0.28.0/docs/adr/024-finding-identity-is-not-prose.md +106 -0
  79. compose_lint-0.28.0/docs/adr/025-lint-the-merged-configuration.md +135 -0
  80. compose_lint-0.28.0/docs/adr/026-read-the-sibling-env-file.md +313 -0
  81. compose_lint-0.28.0/docs/adr/027-grade-env-file-where-the-document-routes-it.md +298 -0
  82. compose_lint-0.28.0/docs/adr/028-pre-1.0-rule-id-sweep.md +281 -0
  83. compose_lint-0.28.0/docs/adr/029-scheduled-python-drops-are-minor.md +70 -0
  84. compose_lint-0.28.0/docs/adr/030-the-policy-is-part-of-the-contract.md +44 -0
  85. compose_lint-0.28.0/docs/adr/031-severity-upgrades-are-minor-with-runway.md +58 -0
  86. compose_lint-0.28.0/docs/adr/032-rule-retirement-is-minor-with-lifecycle.md +95 -0
  87. compose_lint-0.28.0/docs/adr/033-library-tree-is-root-equivalent-by-containment.md +114 -0
  88. compose_lint-0.28.0/docs/adr/034-explain-pages-on-a-tty.md +51 -0
  89. compose_lint-0.28.0/docs/adr/035-defer-the-agent-skill-channel.md +104 -0
  90. compose_lint-0.28.0/docs/adr/036-resolve-references-that-stay-inside-the-project.md +213 -0
  91. compose_lint-0.28.0/docs/assets/bigger-not-sloppier.svg +3290 -0
  92. compose_lint-0.28.0/docs/assets/demo-fix.gif +0 -0
  93. compose_lint-0.28.0/docs/assets/demo.gif +0 -0
  94. compose_lint-0.28.0/docs/assets/file-severity.svg +4043 -0
  95. compose_lint-0.28.0/docs/assets/never-linted.svg +3048 -0
  96. compose_lint-0.28.0/docs/assets/not-improving.svg +3257 -0
  97. compose_lint-0.28.0/docs/assets/overlay-credentials.svg +3506 -0
  98. compose_lint-0.28.0/docs/assets/social-preview.png +0 -0
  99. compose_lint-0.28.0/docs/assets/top-findings.svg +4093 -0
  100. compose_lint-0.28.0/docs/cli.md +153 -0
  101. compose_lint-0.28.0/docs/compatibility.md +221 -0
  102. compose_lint-0.28.0/docs/configuration.md +191 -0
  103. compose_lint-0.28.0/docs/dockerhub-overview.md +45 -0
  104. compose_lint-0.28.0/docs/dynamic-testing.md +66 -0
  105. compose_lint-0.28.0/docs/examples/ci-runner-suppression/.compose-lint.yml +62 -0
  106. compose_lint-0.28.0/docs/examples/ci-runner-suppression/docker-compose.yml +72 -0
  107. compose_lint-0.28.0/docs/examples/ci-runner-suppression/index.md +93 -0
  108. compose_lint-0.28.0/docs/examples/clean-edge-proxy/.compose-lint.yml +20 -0
  109. compose_lint-0.28.0/docs/examples/clean-edge-proxy/docker-compose.yml +95 -0
  110. compose_lint-0.28.0/docs/examples/clean-edge-proxy/index.md +87 -0
  111. compose_lint-0.28.0/docs/examples/index.md +63 -0
  112. compose_lint-0.28.0/docs/examples/logging-without-the-socket/.compose-lint.yml +15 -0
  113. compose_lint-0.28.0/docs/examples/logging-without-the-socket/docker-compose.yml +115 -0
  114. compose_lint-0.28.0/docs/examples/logging-without-the-socket/index.md +82 -0
  115. compose_lint-0.28.0/docs/examples/netdata-socket-proxy/.compose-lint.yml +76 -0
  116. compose_lint-0.28.0/docs/examples/netdata-socket-proxy/docker-compose.hardened.yml +96 -0
  117. compose_lint-0.28.0/docs/examples/netdata-socket-proxy/docker-compose.yml +41 -0
  118. compose_lint-0.28.0/docs/examples/netdata-socket-proxy/index.md +254 -0
  119. compose_lint-0.28.0/docs/examples/portainer-removed/.compose-lint.yml +16 -0
  120. compose_lint-0.28.0/docs/examples/portainer-removed/docker-compose.yml +37 -0
  121. compose_lint-0.28.0/docs/examples/portainer-removed/index.md +54 -0
  122. compose_lint-0.28.0/docs/examples/read-only-in-tension/.compose-lint.yml +24 -0
  123. compose_lint-0.28.0/docs/examples/read-only-in-tension/docker-compose.yml +54 -0
  124. compose_lint-0.28.0/docs/examples/read-only-in-tension/index.md +82 -0
  125. compose_lint-0.28.0/docs/examples/read-only-multi-service/.compose-lint.yml +28 -0
  126. compose_lint-0.28.0/docs/examples/read-only-multi-service/docker-compose.yml +132 -0
  127. compose_lint-0.28.0/docs/examples/read-only-multi-service/index.md +100 -0
  128. compose_lint-0.28.0/docs/fix.md +47 -0
  129. compose_lint-0.28.0/docs/forgejo.md +27 -0
  130. compose_lint-0.28.0/docs/google0319e25860b14c3a.html +1 -0
  131. compose_lint-0.28.0/docs/hardening.md +34 -0
  132. compose_lint-0.28.0/docs/index.md +61 -0
  133. compose_lint-0.28.0/docs/mutation-testing.md +109 -0
  134. compose_lint-0.28.0/docs/publishing/README.md +67 -0
  135. compose_lint-0.28.0/docs/publishing/assets/cover.png +0 -0
  136. compose_lint-0.28.0/docs/publishing/assets/findings-by-tier.png +0 -0
  137. compose_lint-0.28.0/docs/publishing/assets/parse-error-rate.png +0 -0
  138. compose_lint-0.28.0/docs/publishing/assets/severity-distribution.png +0 -0
  139. compose_lint-0.28.0/docs/publishing/assets/top-findings.png +0 -0
  140. compose_lint-0.28.0/docs/publishing/state-of-compose-devto.md +179 -0
  141. compose_lint-0.28.0/docs/publishing/state-of-compose-hashnode.md +32 -0
  142. compose_lint-0.28.0/docs/rules/CL-0001.md +115 -0
  143. compose_lint-0.28.0/docs/rules/CL-0002.md +78 -0
  144. compose_lint-0.28.0/docs/rules/CL-0003.md +98 -0
  145. compose_lint-0.28.0/docs/rules/CL-0004.md +75 -0
  146. compose_lint-0.28.0/docs/rules/CL-0005.md +65 -0
  147. compose_lint-0.28.0/docs/rules/CL-0006.md +137 -0
  148. compose_lint-0.28.0/docs/rules/CL-0007.md +117 -0
  149. compose_lint-0.28.0/docs/rules/CL-0008.md +74 -0
  150. compose_lint-0.28.0/docs/rules/CL-0009.md +82 -0
  151. compose_lint-0.28.0/docs/rules/CL-0010.md +96 -0
  152. compose_lint-0.28.0/docs/rules/CL-0011.md +113 -0
  153. compose_lint-0.28.0/docs/rules/CL-0013.md +184 -0
  154. compose_lint-0.28.0/docs/rules/CL-0014.md +60 -0
  155. compose_lint-0.28.0/docs/rules/CL-0016.md +120 -0
  156. compose_lint-0.28.0/docs/rules/CL-0017.md +95 -0
  157. compose_lint-0.28.0/docs/rules/CL-0018.md +100 -0
  158. compose_lint-0.28.0/docs/rules/CL-0019.md +87 -0
  159. compose_lint-0.28.0/docs/rules/CL-0020.md +150 -0
  160. compose_lint-0.28.0/docs/rules/CL-0021.md +121 -0
  161. compose_lint-0.28.0/docs/rules/CL-0022.md +83 -0
  162. compose_lint-0.28.0/docs/rules/CL-0024.md +103 -0
  163. compose_lint-0.28.0/docs/rules/CL-0025.md +157 -0
  164. compose_lint-0.28.0/docs/rules/CL-0026.md +155 -0
  165. compose_lint-0.28.0/docs/rules/CL-0027.md +95 -0
  166. compose_lint-0.28.0/docs/rules/CL-0028.md +92 -0
  167. compose_lint-0.28.0/docs/rules/CL-0029.md +110 -0
  168. compose_lint-0.28.0/docs/rules/CL-0030.md +96 -0
  169. compose_lint-0.28.0/docs/security-exceptions.md +20 -0
  170. compose_lint-0.28.0/docs/severity.md +404 -0
  171. compose_lint-0.28.0/docs/state-of-compose.md +282 -0
  172. compose_lint-0.28.0/pyproject.toml +261 -0
  173. compose_lint-0.28.0/requirements-build.lock +93 -0
  174. compose_lint-0.28.0/scripts/assert_golden_findings.py +241 -0
  175. compose_lint-0.28.0/scripts/bump-version.sh +40 -0
  176. compose_lint-0.28.0/scripts/check_changelog_unreleased.py +133 -0
  177. compose_lint-0.28.0/scripts/corpus/README.md +132 -0
  178. compose_lint-0.28.0/scripts/corpus/_common.py +181 -0
  179. compose_lint-0.28.0/scripts/corpus/assets/fonts/Inter-Bold.ttf +0 -0
  180. compose_lint-0.28.0/scripts/corpus/assets/fonts/Inter-Regular.ttf +0 -0
  181. compose_lint-0.28.0/scripts/corpus/assets/fonts/InterDisplay-Bold.ttf +0 -0
  182. compose_lint-0.28.0/scripts/corpus/assets/fonts/JetBrainsMono-Bold.ttf +0 -0
  183. compose_lint-0.28.0/scripts/corpus/assets/fonts/OFL-Inter.txt +92 -0
  184. compose_lint-0.28.0/scripts/corpus/assets/fonts/OFL-JetBrainsMono.txt +93 -0
  185. compose_lint-0.28.0/scripts/corpus/backfill_tier.py +46 -0
  186. compose_lint-0.28.0/scripts/corpus/charts.py +567 -0
  187. compose_lint-0.28.0/scripts/corpus/docker_config_gate.py +231 -0
  188. compose_lint-0.28.0/scripts/corpus/enrich_blob_dates.py +142 -0
  189. compose_lint-0.28.0/scripts/corpus/enrich_metadata.py +112 -0
  190. compose_lint-0.28.0/scripts/corpus/fetch.py +220 -0
  191. compose_lint-0.28.0/scripts/corpus/fetch_canonical.py +132 -0
  192. compose_lint-0.28.0/scripts/corpus/fetch_overlays.py +173 -0
  193. compose_lint-0.28.0/scripts/corpus/fetch_popular.py +156 -0
  194. compose_lint-0.28.0/scripts/corpus/fetch_selfhosted.py +135 -0
  195. compose_lint-0.28.0/scripts/corpus/fix_gate.py +162 -0
  196. compose_lint-0.28.0/scripts/corpus/make_tier_summary.py +56 -0
  197. compose_lint-0.28.0/scripts/corpus/retier.py +226 -0
  198. compose_lint-0.28.0/scripts/corpus/run.py +591 -0
  199. compose_lint-0.28.0/scripts/demo/README.md +112 -0
  200. compose_lint-0.28.0/scripts/demo/demo.tape +65 -0
  201. compose_lint-0.28.0/scripts/demo/docker-compose.yml +33 -0
  202. compose_lint-0.28.0/scripts/demo/fix-compose.yml +18 -0
  203. compose_lint-0.28.0/scripts/demo/fix.tape +79 -0
  204. compose_lint-0.28.0/scripts/demo/render.sh +45 -0
  205. compose_lint-0.28.0/scripts/demo/requirements.in +6 -0
  206. compose_lint-0.28.0/scripts/demo/retime.py +129 -0
  207. compose_lint-0.28.0/scripts/eol_watch.py +290 -0
  208. compose_lint-0.28.0/scripts/forgejo_smoke/compose-forgejo-smoke.yml +71 -0
  209. compose_lint-0.28.0/scripts/forgejo_smoke/runner-config.yml +6 -0
  210. compose_lint-0.28.0/scripts/forgejo_smoke.py +284 -0
  211. compose_lint-0.28.0/scripts/mkdocs_git_dates_hook.py +136 -0
  212. compose_lint-0.28.0/scripts/mkdocs_seo_hook.py +169 -0
  213. compose_lint-0.28.0/scripts/smoke_fix_roundtrip.py +270 -0
  214. compose_lint-0.28.0/scripts/snapshot.py +216 -0
  215. compose_lint-0.28.0/scripts/update-dockerhub-description.sh +79 -0
  216. compose_lint-0.28.0/scripts/validate_rule_premises.py +1503 -0
  217. compose_lint-0.28.0/scripts/verify-dockerfile-digests.sh +95 -0
  218. compose_lint-0.28.0/scripts/verify_sarif_ingestion.py +209 -0
  219. compose_lint-0.28.0/scripts/vuln_report.py +270 -0
  220. compose_lint-0.28.0/src/compose_lint/__init__.py +3 -0
  221. compose_lint-0.28.0/src/compose_lint/__main__.py +5 -0
  222. compose_lint-0.28.0/src/compose_lint/_env_file.py +681 -0
  223. compose_lint-0.28.0/src/compose_lint/_limits.py +35 -0
  224. compose_lint-0.28.0/src/compose_lint/_lines.py +150 -0
  225. compose_lint-0.28.0/src/compose_lint/_merge.py +769 -0
  226. compose_lint-0.28.0/src/compose_lint/_output.py +121 -0
  227. compose_lint-0.28.0/src/compose_lint/_safe_read.py +135 -0
  228. compose_lint-0.28.0/src/compose_lint/_scalar.py +41 -0
  229. compose_lint-0.28.0/src/compose_lint/_selection.py +343 -0
  230. compose_lint-0.28.0/src/compose_lint/_service_env.py +449 -0
  231. compose_lint-0.28.0/src/compose_lint/_yaml_edit.py +340 -0
  232. compose_lint-0.28.0/src/compose_lint/attack.py +154 -0
  233. compose_lint-0.28.0/src/compose_lint/cli.py +1500 -0
  234. compose_lint-0.28.0/src/compose_lint/config.py +335 -0
  235. compose_lint-0.28.0/src/compose_lint/config_emit.py +150 -0
  236. compose_lint-0.28.0/src/compose_lint/engine.py +139 -0
  237. compose_lint-0.28.0/src/compose_lint/explain.py +52 -0
  238. compose_lint-0.28.0/src/compose_lint/fix.py +721 -0
  239. compose_lint-0.28.0/src/compose_lint/formatters/__init__.py +1 -0
  240. compose_lint-0.28.0/src/compose_lint/formatters/json.py +97 -0
  241. compose_lint-0.28.0/src/compose_lint/formatters/sarif.py +569 -0
  242. compose_lint-0.28.0/src/compose_lint/formatters/text.py +593 -0
  243. compose_lint-0.28.0/src/compose_lint/models.py +119 -0
  244. compose_lint-0.28.0/src/compose_lint/parser.py +2184 -0
  245. compose_lint-0.28.0/src/compose_lint/py.typed +0 -0
  246. compose_lint-0.28.0/src/compose_lint/rules/CL0001_docker_socket.py +211 -0
  247. compose_lint-0.28.0/src/compose_lint/rules/CL0002_privileged_mode.py +71 -0
  248. compose_lint-0.28.0/src/compose_lint/rules/CL0003_no_new_privileges.py +214 -0
  249. compose_lint-0.28.0/src/compose_lint/rules/CL0004_image_not_pinned.py +92 -0
  250. compose_lint-0.28.0/src/compose_lint/rules/CL0005_unbound_ports.py +557 -0
  251. compose_lint-0.28.0/src/compose_lint/rules/CL0006_cap_drop.py +87 -0
  252. compose_lint-0.28.0/src/compose_lint/rules/CL0007_read_only.py +141 -0
  253. compose_lint-0.28.0/src/compose_lint/rules/CL0008_host_network.py +68 -0
  254. compose_lint-0.28.0/src/compose_lint/rules/CL0009_security_profile.py +217 -0
  255. compose_lint-0.28.0/src/compose_lint/rules/CL0010_host_namespace.py +103 -0
  256. compose_lint-0.28.0/src/compose_lint/rules/CL0011_dangerous_cap_add.py +84 -0
  257. compose_lint-0.28.0/src/compose_lint/rules/CL0013_sensitive_mount.py +277 -0
  258. compose_lint-0.28.0/src/compose_lint/rules/CL0014_logging_disabled.py +145 -0
  259. compose_lint-0.28.0/src/compose_lint/rules/CL0016_dangerous_devices.py +142 -0
  260. compose_lint-0.28.0/src/compose_lint/rules/CL0017_shared_mount.py +117 -0
  261. compose_lint-0.28.0/src/compose_lint/rules/CL0018_explicit_root.py +86 -0
  262. compose_lint-0.28.0/src/compose_lint/rules/CL0019_image_no_digest.py +89 -0
  263. compose_lint-0.28.0/src/compose_lint/rules/CL0020_credential_env_keys.py +379 -0
  264. compose_lint-0.28.0/src/compose_lint/rules/CL0021_connection_string_credentials.py +303 -0
  265. compose_lint-0.28.0/src/compose_lint/rules/CL0022_tmpfs_insecure_options.py +115 -0
  266. compose_lint-0.28.0/src/compose_lint/rules/CL0024_host_exec_cap_add.py +83 -0
  267. compose_lint-0.28.0/src/compose_lint/rules/CL0025_writable_host_root.py +279 -0
  268. compose_lint-0.28.0/src/compose_lint/rules/CL0026_resource_limits.py +182 -0
  269. compose_lint-0.28.0/src/compose_lint/rules/CL0027_lesser_cap_add.py +86 -0
  270. compose_lint-0.28.0/src/compose_lint/rules/CL0028_host_reach_cap_add.py +83 -0
  271. compose_lint-0.28.0/src/compose_lint/rules/CL0029_host_availability_cap_add.py +96 -0
  272. compose_lint-0.28.0/src/compose_lint/rules/CL0030_host_disclosure_cap_add.py +80 -0
  273. compose_lint-0.28.0/src/compose_lint/rules/__init__.py +123 -0
  274. compose_lint-0.28.0/src/compose_lint/rules/_bool.py +36 -0
  275. compose_lint-0.28.0/src/compose_lint/rules/_caps.py +96 -0
  276. compose_lint-0.28.0/src/compose_lint/rules/_image.py +44 -0
  277. compose_lint-0.28.0/src/compose_lint/rules/_interpolation.py +379 -0
  278. compose_lint-0.28.0/src/compose_lint/rules/_mounts.py +322 -0
  279. compose_lint-0.28.0/tests/__init__.py +0 -0
  280. compose_lint-0.28.0/tests/_cli_env.py +59 -0
  281. compose_lint-0.28.0/tests/compose_files/compose_lint_config.yml +13 -0
  282. compose_lint-0.28.0/tests/compose_files/fragment_volumes_only.yml +3 -0
  283. compose_lint-0.28.0/tests/compose_files/insecure_cap_add.yml +48 -0
  284. compose_lint-0.28.0/tests/compose_files/insecure_cap_drop.yml +17 -0
  285. compose_lint-0.28.0/tests/compose_files/insecure_connection_string_creds.yml +68 -0
  286. compose_lint-0.28.0/tests/compose_files/insecure_credential_env.yml +136 -0
  287. compose_lint-0.28.0/tests/compose_files/insecure_devices.yml +59 -0
  288. compose_lint-0.28.0/tests/compose_files/insecure_host_namespace.yml +23 -0
  289. compose_lint-0.28.0/tests/compose_files/insecure_host_network.yml +12 -0
  290. compose_lint-0.28.0/tests/compose_files/insecure_image_no_digest.yml +23 -0
  291. compose_lint-0.28.0/tests/compose_files/insecure_image_tags.yml +29 -0
  292. compose_lint-0.28.0/tests/compose_files/insecure_logging.yml +19 -0
  293. compose_lint-0.28.0/tests/compose_files/insecure_no_new_priv.yml +14 -0
  294. compose_lint-0.28.0/tests/compose_files/insecure_ports.yml +61 -0
  295. compose_lint-0.28.0/tests/compose_files/insecure_privileged.yml +6 -0
  296. compose_lint-0.28.0/tests/compose_files/insecure_read_only.yml +12 -0
  297. compose_lint-0.28.0/tests/compose_files/insecure_root_user.yml +36 -0
  298. compose_lint-0.28.0/tests/compose_files/insecure_security_profile.yml +38 -0
  299. compose_lint-0.28.0/tests/compose_files/insecure_sensitive_mount.yml +87 -0
  300. compose_lint-0.28.0/tests/compose_files/insecure_shared_mount.yml +35 -0
  301. compose_lint-0.28.0/tests/compose_files/insecure_socket.yml +11 -0
  302. compose_lint-0.28.0/tests/compose_files/invalid_complex_key.yml +4 -0
  303. compose_lint-0.28.0/tests/compose_files/invalid_empty.yml +0 -0
  304. compose_lint-0.28.0/tests/compose_files/invalid_no_services.yml +2 -0
  305. compose_lint-0.28.0/tests/compose_files/invalid_service_not_mapping.yml +2 -0
  306. compose_lint-0.28.0/tests/compose_files/invalid_services_not_mapping.yml +3 -0
  307. compose_lint-0.28.0/tests/compose_files/invalid_yaml.yml +7 -0
  308. compose_lint-0.28.0/tests/compose_files/kics_comparison.yml +121 -0
  309. compose_lint-0.28.0/tests/compose_files/legacy_v1_compose.yml +8 -0
  310. compose_lint-0.28.0/tests/compose_files/mixed.yml +19 -0
  311. compose_lint-0.28.0/tests/compose_files/ports_long_syntax_protocols.yml +19 -0
  312. compose_lint-0.28.0/tests/compose_files/safe_cap_hardened.yml +18 -0
  313. compose_lint-0.28.0/tests/compose_files/safe_named_volume_propagation.yml +20 -0
  314. compose_lint-0.28.0/tests/compose_files/safe_no_new_priv_short.yml +10 -0
  315. compose_lint-0.28.0/tests/compose_files/safe_self_hosted.yml +22 -0
  316. compose_lint-0.28.0/tests/compose_files/suppress_config.yml +6 -0
  317. compose_lint-0.28.0/tests/compose_files/valid_anchors.yml +12 -0
  318. compose_lint-0.28.0/tests/compose_files/valid_anchors_seq_merge.yml +18 -0
  319. compose_lint-0.28.0/tests/compose_files/valid_basic.yml +33 -0
  320. compose_lint-0.28.0/tests/compose_files/valid_env_interpolation.yml +5 -0
  321. compose_lint-0.28.0/tests/compose_files/valid_v2.yml +9 -0
  322. compose_lint-0.28.0/tests/compose_files/warnings_only.yml +9 -0
  323. compose_lint-0.28.0/tests/conftest.py +25 -0
  324. compose_lint-0.28.0/tests/corpus_snapshot.json.gz +0 -0
  325. compose_lint-0.28.0/tests/fixtures/sarif-schema-2.1.0.json +3389 -0
  326. compose_lint-0.28.0/tests/oracle_harness/__init__.py +61 -0
  327. compose_lint-0.28.0/tests/oracle_harness/__main__.py +78 -0
  328. compose_lint-0.28.0/tests/oracle_harness/_compare.py +166 -0
  329. compose_lint-0.28.0/tests/oracle_harness/_divergences.py +165 -0
  330. compose_lint-0.28.0/tests/oracle_harness/_oracle.py +137 -0
  331. compose_lint-0.28.0/tests/oracle_harness/_project.py +458 -0
  332. compose_lint-0.28.0/tests/oracle_harness/_shape.py +131 -0
  333. compose_lint-0.28.0/tests/smoke/clean.yml +17 -0
  334. compose_lint-0.28.0/tests/smoke/insecure.golden.json +48 -0
  335. compose_lint-0.28.0/tests/smoke/insecure.yml +8 -0
  336. compose_lint-0.28.0/tests/smoke/overlay/compose.yml +17 -0
  337. compose_lint-0.28.0/tests/smoke/overlay/override.yml.tmpl +11 -0
  338. compose_lint-0.28.0/tests/smoke/sarif-probe-config.yml +18 -0
  339. compose_lint-0.28.0/tests/smoke/sarif-shape.yml +7 -0
  340. compose_lint-0.28.0/tests/test_CL0001.py +459 -0
  341. compose_lint-0.28.0/tests/test_CL0002.py +81 -0
  342. compose_lint-0.28.0/tests/test_CL0003.py +283 -0
  343. compose_lint-0.28.0/tests/test_CL0004.py +94 -0
  344. compose_lint-0.28.0/tests/test_CL0005.py +425 -0
  345. compose_lint-0.28.0/tests/test_CL0006.py +136 -0
  346. compose_lint-0.28.0/tests/test_CL0007.py +213 -0
  347. compose_lint-0.28.0/tests/test_CL0008.py +81 -0
  348. compose_lint-0.28.0/tests/test_CL0009.py +333 -0
  349. compose_lint-0.28.0/tests/test_CL0010.py +101 -0
  350. compose_lint-0.28.0/tests/test_CL0011.py +130 -0
  351. compose_lint-0.28.0/tests/test_CL0013.py +428 -0
  352. compose_lint-0.28.0/tests/test_CL0014.py +190 -0
  353. compose_lint-0.28.0/tests/test_CL0016.py +155 -0
  354. compose_lint-0.28.0/tests/test_CL0017.py +114 -0
  355. compose_lint-0.28.0/tests/test_CL0018.py +87 -0
  356. compose_lint-0.28.0/tests/test_CL0019.py +90 -0
  357. compose_lint-0.28.0/tests/test_CL0020.py +393 -0
  358. compose_lint-0.28.0/tests/test_CL0021.py +286 -0
  359. compose_lint-0.28.0/tests/test_CL0022.py +84 -0
  360. compose_lint-0.28.0/tests/test_CL0024.py +125 -0
  361. compose_lint-0.28.0/tests/test_CL0025.py +330 -0
  362. compose_lint-0.28.0/tests/test_CL0026.py +176 -0
  363. compose_lint-0.28.0/tests/test_CL0027.py +90 -0
  364. compose_lint-0.28.0/tests/test_CL0028.py +87 -0
  365. compose_lint-0.28.0/tests/test_CL0029.py +64 -0
  366. compose_lint-0.28.0/tests/test_CL0030.py +60 -0
  367. compose_lint-0.28.0/tests/test_action_contract.py +545 -0
  368. compose_lint-0.28.0/tests/test_assurance.py +238 -0
  369. compose_lint-0.28.0/tests/test_attack_mapping.py +156 -0
  370. compose_lint-0.28.0/tests/test_bind_source_resolution.py +361 -0
  371. compose_lint-0.28.0/tests/test_changelog_shape.py +85 -0
  372. compose_lint-0.28.0/tests/test_cli.py +1219 -0
  373. compose_lint-0.28.0/tests/test_cli_env.py +47 -0
  374. compose_lint-0.28.0/tests/test_config.py +453 -0
  375. compose_lint-0.28.0/tests/test_config_emit.py +128 -0
  376. compose_lint-0.28.0/tests/test_corpus_fetch_url.py +60 -0
  377. compose_lint-0.28.0/tests/test_corpus_fix.py +106 -0
  378. compose_lint-0.28.0/tests/test_corpus_snapshot.py +44 -0
  379. compose_lint-0.28.0/tests/test_corpus_snapshot_schema.py +100 -0
  380. compose_lint-0.28.0/tests/test_coverage_gaps.py +308 -0
  381. compose_lint-0.28.0/tests/test_cross_file_extends.py +586 -0
  382. compose_lint-0.28.0/tests/test_demo_fixture.py +99 -0
  383. compose_lint-0.28.0/tests/test_discovery_parity.py +126 -0
  384. compose_lint-0.28.0/tests/test_engine.py +324 -0
  385. compose_lint-0.28.0/tests/test_env_file.py +427 -0
  386. compose_lint-0.28.0/tests/test_env_file_notes.py +241 -0
  387. compose_lint-0.28.0/tests/test_env_file_semantics.py +297 -0
  388. compose_lint-0.28.0/tests/test_env_interpolation.py +191 -0
  389. compose_lint-0.28.0/tests/test_env_semantics.py +196 -0
  390. compose_lint-0.28.0/tests/test_eol_watch.py +170 -0
  391. compose_lint-0.28.0/tests/test_exit_code_contract.py +391 -0
  392. compose_lint-0.28.0/tests/test_finding_identity.py +333 -0
  393. compose_lint-0.28.0/tests/test_fix.py +907 -0
  394. compose_lint-0.28.0/tests/test_fix_line_space.py +196 -0
  395. compose_lint-0.28.0/tests/test_fix_reset_keys.py +138 -0
  396. compose_lint-0.28.0/tests/test_fixture_coverage.py +71 -0
  397. compose_lint-0.28.0/tests/test_format_equivalence.py +305 -0
  398. compose_lint-0.28.0/tests/test_golden_findings.py +206 -0
  399. compose_lint-0.28.0/tests/test_harness_end_of_options.py +149 -0
  400. compose_lint-0.28.0/tests/test_image_ref.py +34 -0
  401. compose_lint-0.28.0/tests/test_include.py +851 -0
  402. compose_lint-0.28.0/tests/test_init_write_path.py +177 -0
  403. compose_lint-0.28.0/tests/test_integration.py +177 -0
  404. compose_lint-0.28.0/tests/test_interpolation.py +225 -0
  405. compose_lint-0.28.0/tests/test_interpolation_operators.py +173 -0
  406. compose_lint-0.28.0/tests/test_json.py +124 -0
  407. compose_lint-0.28.0/tests/test_json_contract.py +433 -0
  408. compose_lint-0.28.0/tests/test_kics_comparison.py +144 -0
  409. compose_lint-0.28.0/tests/test_line_space_guard.py +54 -0
  410. compose_lint-0.28.0/tests/test_lines.py +230 -0
  411. compose_lint-0.28.0/tests/test_merge_fuzz.py +190 -0
  412. compose_lint-0.28.0/tests/test_merge_semantics.py +611 -0
  413. compose_lint-0.28.0/tests/test_mkdocs_git_dates_hook.py +287 -0
  414. compose_lint-0.28.0/tests/test_no_config_notice.py +117 -0
  415. compose_lint-0.28.0/tests/test_normalized_classification.py +253 -0
  416. compose_lint-0.28.0/tests/test_oracle_divergences.py +175 -0
  417. compose_lint-0.28.0/tests/test_oracle_harness.py +364 -0
  418. compose_lint-0.28.0/tests/test_output_sanitizing.py +272 -0
  419. compose_lint-0.28.0/tests/test_overlay_merge.py +686 -0
  420. compose_lint-0.28.0/tests/test_parser.py +758 -0
  421. compose_lint-0.28.0/tests/test_parser_sequence_lines.py +288 -0
  422. compose_lint-0.28.0/tests/test_patch_coverage.py +170 -0
  423. compose_lint-0.28.0/tests/test_precommit.py +115 -0
  424. compose_lint-0.28.0/tests/test_release_layer.py +440 -0
  425. compose_lint-0.28.0/tests/test_resource_bounds.py +376 -0
  426. compose_lint-0.28.0/tests/test_rule_consistency.py +147 -0
  427. compose_lint-0.28.0/tests/test_rule_loader.py +86 -0
  428. compose_lint-0.28.0/tests/test_rule_membership.py +703 -0
  429. compose_lint-0.28.0/tests/test_rule_surfaces.py +129 -0
  430. compose_lint-0.28.0/tests/test_sarif.py +675 -0
  431. compose_lint-0.28.0/tests/test_sarif_ingestion_probe.py +108 -0
  432. compose_lint-0.28.0/tests/test_selection.py +260 -0
  433. compose_lint-0.28.0/tests/test_selection_semantics.py +196 -0
  434. compose_lint-0.28.0/tests/test_service_env.py +346 -0
  435. compose_lint-0.28.0/tests/test_severity_matrix.py +309 -0
  436. compose_lint-0.28.0/tests/test_smoke_fix_roundtrip.py +136 -0
  437. compose_lint-0.28.0/tests/test_text_formatter.py +499 -0
  438. compose_lint-0.28.0/tests/test_unresolved_notes.py +84 -0
  439. compose_lint-0.28.0/tests/test_validate_rule_premises.py +64 -0
  440. compose_lint-0.28.0/tests/test_vuln_report.py +161 -0
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ while read local_ref local_sha remote_ref remote_sha; do
5
+ if [ "$local_sha" = "0000000000000000000000000000000000000000" ]; then
6
+ continue # branch deletion, skip
7
+ fi
8
+
9
+ # Only check commits unique to this branch — not commits already on main
10
+ # (including GitHub squash-merge commits which carry GitHub's own key).
11
+ base=$(git merge-base "$local_sha" origin/main 2>/dev/null \
12
+ || git rev-list --max-parents=0 HEAD)
13
+
14
+ while IFS= read -r line; do
15
+ sha="${line%% *}"
16
+ status="${line##* }"
17
+ if [ "$status" != "G" ]; then
18
+ echo "error: commit ${sha} is unsigned or unverified — sign your commits before pushing"
19
+ exit 1
20
+ fi
21
+ done < <(git log --format="%H %G?" "${base}..${local_sha}")
22
+
23
+ # DCO. Separate from the signature above: signing proves who committed, the
24
+ # trailer asserts the right to contribute. No git config adds it to every
25
+ # commit (format.signOff only affects format-patch), so without this check a
26
+ # missing trailer surfaces in CI — and on a first-time contributor's fork PR,
27
+ # not until a maintainer approves the run.
28
+ while IFS=$'\t' read -r sha author_name author_email; do
29
+ expected="Signed-off-by: ${author_name} <${author_email}>"
30
+ if ! git log -1 --format='%B' "${sha}" | grep -qiF "${expected}"; then
31
+ echo "error: commit ${sha} is missing '${expected}'"
32
+ echo " add it with 'git commit --amend --signoff', or"
33
+ echo " 'git rebase --signoff ${base}' for a whole branch"
34
+ exit 1
35
+ fi
36
+ done < <(git log --format='%H%x09%an%x09%ae' "${base}..${local_sha}")
37
+ done
@@ -0,0 +1,8 @@
1
+ # Every file in this repo is owned by @tmatens. This is a single-maintainer
2
+ # project today; CODEOWNERS makes ownership explicit and gives us the hook
3
+ # to hand off specific directories to co-maintainers later without rewriting
4
+ # history.
5
+ #
6
+ # See https://docs.github.com/en/repositories/managing-your-repositories-settings-and-security/customizing-your-repository/about-code-owners
7
+
8
+ * @tmatens
@@ -0,0 +1,83 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our Standards
10
+
11
+ Examples of behavior that contributes to a positive environment for our community include:
12
+
13
+ * Demonstrating empathy and kindness toward other people
14
+ * Being respectful of differing opinions, viewpoints, and experiences
15
+ * Giving and gracefully accepting constructive feedback
16
+ * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ * Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior include:
20
+
21
+ * The use of sexualized language or imagery, and sexual attention or advances of any kind
22
+ * Trolling, insulting or derogatory comments, and personal or political attacks
23
+ * Public or private harassment
24
+ * Publishing others' private information, such as a physical or email address, without their explicit permission
25
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
26
+
27
+ ## Enforcement Responsibilities
28
+
29
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
32
+
33
+ ## Scope
34
+
35
+ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
36
+
37
+ ## Enforcement
38
+
39
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at tmatens@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
40
+
41
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
42
+
43
+ ## Enforcement Guidelines
44
+
45
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
46
+
47
+ ### 1. Correction
48
+
49
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
50
+
51
+ **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
52
+
53
+ ### 2. Warning
54
+
55
+ **Community Impact**: A violation through a single incident or series of actions.
56
+
57
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
58
+
59
+ ### 3. Temporary Ban
60
+
61
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
62
+
63
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
64
+
65
+ ### 4. Permanent Ban
66
+
67
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
68
+
69
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
70
+
71
+ ## Attribution
72
+
73
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
74
+
75
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
76
+
77
+ For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
78
+
79
+ [homepage]: https://www.contributor-covenant.org
80
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
81
+ [Mozilla CoC]: https://github.com/mozilla/diversity
82
+ [FAQ]: https://www.contributor-covenant.org/faq
83
+ [translations]: https://www.contributor-covenant.org/translations
@@ -0,0 +1,98 @@
1
+ name: Bug report
2
+ description: Report incorrect behavior in compose-lint (false positive, false negative, crash, wrong output).
3
+ title: "[bug] "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time to file a bug report. Please include a **minimal** Compose file that reproduces the problem — the smaller, the better.
10
+
11
+ Security vulnerabilities should go through [private vulnerability reporting](https://github.com/tmatens/compose-lint/security/advisories/new), not this form.
12
+
13
+ Docs, code quality, tooling, or a question? Use the "Other" template instead. It doesn't ask for a Compose file.
14
+
15
+ - type: textarea
16
+ id: compose-file
17
+ attributes:
18
+ label: Minimal Compose file
19
+ description: The smallest `docker-compose.yml` that reproduces the issue. Strip anything unrelated.
20
+ render: yaml
21
+ placeholder: |
22
+ services:
23
+ web:
24
+ image: nginx:1.27
25
+ privileged: true
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: command
31
+ attributes:
32
+ label: Command you ran
33
+ description: The exact `compose-lint` invocation.
34
+ render: shell
35
+ placeholder: compose-lint docker-compose.yml
36
+ validations:
37
+ required: true
38
+
39
+ - type: textarea
40
+ id: expected
41
+ attributes:
42
+ label: Expected behavior
43
+ description: What did you expect to happen?
44
+ validations:
45
+ required: true
46
+
47
+ - type: textarea
48
+ id: actual
49
+ attributes:
50
+ label: Actual behavior
51
+ description: What actually happened?
52
+ validations:
53
+ required: true
54
+
55
+ - type: textarea
56
+ id: output
57
+ attributes:
58
+ label: Output
59
+ description: The full `compose-lint` output, if there is any.
60
+ render: shell
61
+ validations:
62
+ required: false
63
+
64
+ - type: input
65
+ id: version
66
+ attributes:
67
+ label: compose-lint version
68
+ description: Output of `compose-lint --version`.
69
+ placeholder: "x.y.z"
70
+ validations:
71
+ required: true
72
+
73
+ - type: input
74
+ id: python-version
75
+ attributes:
76
+ label: Python version
77
+ description: Output of `python --version`.
78
+ placeholder: "3.12.3"
79
+ validations:
80
+ required: true
81
+
82
+ - type: input
83
+ id: os
84
+ attributes:
85
+ label: Operating system
86
+ placeholder: "Ubuntu 24.04, macOS 14.5, Windows 11, ..."
87
+ validations:
88
+ required: false
89
+
90
+ - type: checkboxes
91
+ id: checks
92
+ attributes:
93
+ label: Before submitting
94
+ options:
95
+ - label: I searched existing issues and this is not a duplicate.
96
+ required: true
97
+ - label: I am running the latest released version, or I have confirmed the bug still reproduces on `main`.
98
+ required: true
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,45 @@
1
+ name: Feature request
2
+ description: Suggest a non-rule feature (CLI flag, output format, config option, tooling integration, etc.). For new rules, use the "Rule proposal" template instead.
3
+ title: "[feature] "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ compose-lint's scope is deliberately narrow: static security analysis of Compose files. Features that push it toward being a general-purpose Compose linter, a runtime scanner, or a replacement for KICS/Checkov are out of scope. See [AGENTS.md](https://github.com/tmatens/compose-lint/blob/main/AGENTS.md#project-overview) for the full scope statement.
10
+
11
+ **Proposing a new security rule? Use the "Rule proposal" template instead.**
12
+
13
+ - type: textarea
14
+ id: problem
15
+ attributes:
16
+ label: What problem does this solve?
17
+ description: Describe the use case. What can't you do today that you want to do?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: proposed-solution
23
+ attributes:
24
+ label: Proposed solution
25
+ description: What should compose-lint do? Show the CLI invocation, config key, or output format you have in mind.
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: alternatives
31
+ attributes:
32
+ label: Alternatives considered
33
+ description: What workarounds exist today? What other approaches did you consider, and why is this the right one?
34
+ validations:
35
+ required: false
36
+
37
+ - type: checkboxes
38
+ id: scope-check
39
+ attributes:
40
+ label: Scope check
41
+ options:
42
+ - label: This is not a new security rule (those use the "Rule proposal" template).
43
+ required: true
44
+ - label: This fits compose-lint's scope as a zero-config security linter, not a general Compose linter or runtime scanner.
45
+ required: true
@@ -0,0 +1,27 @@
1
+ name: Other
2
+ description: Anything that isn't a linter bug or a feature — docs, code quality, tooling, CI, or a question.
3
+ title: "[other] "
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Use this for anything the other templates don't fit: documentation, code quality, project tooling, CI, or a question about compose-lint.
9
+
10
+ Security vulnerabilities should go through [private vulnerability reporting](https://github.com/tmatens/compose-lint/security/advisories/new), not this form.
11
+
12
+ - type: textarea
13
+ id: details
14
+ attributes:
15
+ label: What's on your mind?
16
+ description: Describe the issue or question. Link to the file, doc, or line if there is one.
17
+ validations:
18
+ required: true
19
+
20
+ - type: input
21
+ id: version
22
+ attributes:
23
+ label: compose-lint version
24
+ description: Only if it matters for this issue.
25
+ placeholder: "x.y.z"
26
+ validations:
27
+ required: false
@@ -0,0 +1,101 @@
1
+ name: Rule proposal
2
+ description: Propose a new CL-XXXX rule. Rules must be grounded in an authoritative source — opinion-only rules are not accepted.
3
+ title: "[rule] "
4
+ labels: ["rule-proposal"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for proposing a new rule. Every rule in compose-lint must be traceable to OWASP, CIS, or Docker's official documentation. If you can't point to an authoritative source, the rule probably isn't a fit for this tool.
10
+
11
+ Please read [AGENTS.md — Rule Design Philosophy](https://github.com/tmatens/compose-lint/blob/main/AGENTS.md#rule-design-philosophy) and [docs/severity.md](https://github.com/tmatens/compose-lint/blob/main/docs/severity.md) before filing.
12
+
13
+ - type: textarea
14
+ id: risk
15
+ attributes:
16
+ label: What is the risk?
17
+ description: Describe the real-world consequence of the misconfiguration. What can an attacker do? What's the blast radius?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: authoritative-source
23
+ attributes:
24
+ label: Authoritative source
25
+ description: |
26
+ Direct link to the OWASP Docker Security Cheat Sheet, CIS Docker Benchmark, or Docker official documentation section that supports this rule. Quote the relevant text.
27
+ placeholder: |
28
+ https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-1-...
29
+
30
+ "Do not use the --privileged flag..."
31
+ validations:
32
+ required: true
33
+
34
+ - type: textarea
35
+ id: insecure-example
36
+ attributes:
37
+ label: Example insecure YAML
38
+ description: A Compose snippet the rule should flag.
39
+ render: yaml
40
+ placeholder: |
41
+ services:
42
+ web:
43
+ image: nginx:1.27
44
+ privileged: true
45
+ validations:
46
+ required: true
47
+
48
+ - type: textarea
49
+ id: fixed-example
50
+ attributes:
51
+ label: Example fixed YAML
52
+ description: The same snippet, remediated. This becomes the fix guidance shown to users.
53
+ render: yaml
54
+ placeholder: |
55
+ services:
56
+ web:
57
+ image: nginx:1.27
58
+ # privileged removed; add specific capabilities instead if needed
59
+ cap_add:
60
+ - NET_BIND_SERVICE
61
+ validations:
62
+ required: true
63
+
64
+ - type: dropdown
65
+ id: proposed-severity
66
+ attributes:
67
+ label: Proposed severity
68
+ description: See [docs/severity.md](https://github.com/tmatens/compose-lint/blob/main/docs/severity.md) for the scoring matrix.
69
+ options:
70
+ - CRITICAL — direct path to host compromise
71
+ - HIGH — exposed attack surface or requires chaining for cross-container/host impact
72
+ - MEDIUM — requires chaining for single-container impact, or hardening gap with cross-container scope
73
+ - LOW — hardening gap contained within a single container
74
+ validations:
75
+ required: true
76
+
77
+ - type: textarea
78
+ id: severity-reasoning
79
+ attributes:
80
+ label: Severity reasoning
81
+ description: Walk through the two axes — exploitability and impact scope — that justify your proposed severity.
82
+ validations:
83
+ required: true
84
+
85
+ - type: textarea
86
+ id: false-positives
87
+ attributes:
88
+ label: Known false positives or edge cases
89
+ description: Are there legitimate reasons to configure it this way? How should the rule handle them?
90
+ validations:
91
+ required: false
92
+
93
+ - type: checkboxes
94
+ id: checks
95
+ attributes:
96
+ label: Before submitting
97
+ options:
98
+ - label: I searched existing rules (`docs/rules/`) and issues to confirm this rule does not already exist and has not already been proposed.
99
+ required: true
100
+ - label: My authoritative source is OWASP, CIS, or Docker official documentation — not a blog post or personal opinion.
101
+ required: true
@@ -0,0 +1,49 @@
1
+ # Security Policy
2
+
3
+ For what compose-lint will and will not protect you against, see
4
+ [docs/SECURITY-EXPECTATIONS.md](../docs/SECURITY-EXPECTATIONS.md). For
5
+ the full assurance case (threat model, trust boundaries, mitigations),
6
+ see [docs/ASSURANCE.md](../docs/ASSURANCE.md).
7
+
8
+ ## Supported Versions
9
+
10
+ compose-lint follows semantic versioning. Only the latest minor release
11
+ receives security fixes.
12
+
13
+ ## Reporting a Vulnerability
14
+
15
+ **Please do not report security vulnerabilities through public GitHub issues.**
16
+
17
+ Use GitHub's private vulnerability reporting:
18
+
19
+ 1. Go to <https://github.com/tmatens/compose-lint/security/advisories/new>
20
+ 2. Submit a report with reproduction steps and impact
21
+
22
+ You should receive an acknowledgement within 7 days. If the report is valid, a fix
23
+ will be coordinated and released, and the advisory will be published with credit
24
+ unless you request otherwise.
25
+
26
+ ## Scope
27
+
28
+ In scope:
29
+
30
+ - Code execution or information disclosure via crafted Compose files
31
+ - Tampering with the published PyPI package or GitHub Action
32
+ - Vulnerabilities in dependencies that are exploitable via compose-lint
33
+
34
+ Out of scope:
35
+
36
+ - False positives or false negatives in security rules — file these as normal
37
+ issues
38
+ - Findings against vulnerable Compose files in `tests/compose_files/` (these are
39
+ intentionally insecure fixtures)
40
+
41
+ ## Supply Chain
42
+
43
+ - PyPI releases use [Trusted Publishing](https://docs.pypi.org/trusted-publishers/)
44
+ via GitHub Actions OIDC. No long-lived API tokens exist.
45
+ - Releases include [Sigstore build attestations](https://docs.pypi.org/attestations/).
46
+ Verify with `pip install compose-lint --require-hashes` plus the published
47
+ attestation.
48
+ - Dependencies are kept current by Renovate. CodeQL and OpenSSF Scorecard run
49
+ on every push and weekly.
@@ -0,0 +1,47 @@
1
+ name: 'Update Docker Hub description'
2
+ description: >
3
+ Sync a Docker Hub repository's overview (long description) and short
4
+ description from a local markdown file (default: the trimmed
5
+ docs/dockerhub-overview.md, kept under Docker Hub's 25000-byte cap —
6
+ NOT README.md, which is uncapped). First-party replacement for
7
+ peter-evans/dockerhub-description — no third-party Node bundle holds the
8
+ delete-capable Docker Hub PAT. Implementation is a single bash script
9
+ invoking the Docker Hub v2 API; review diff before bumping.
10
+
11
+ inputs:
12
+ username:
13
+ description: >
14
+ Docker Hub username of the account that owns the PAT. Not the
15
+ organization name, even if the repository lives under an org.
16
+ required: true
17
+ token:
18
+ description: >
19
+ Docker Hub Personal Access Token with "Read, Write, Delete" scope.
20
+ The description PATCH endpoint rejects narrower scopes with HTTP 403.
21
+ required: true
22
+ repository:
23
+ description: Docker Hub repository in `<namespace>/<name>` form.
24
+ required: true
25
+ readme-filepath:
26
+ description: Path to the markdown file whose contents become the overview.
27
+ required: false
28
+ default: './docs/dockerhub-overview.md'
29
+ short-description:
30
+ description: One-line short description shown under the repo title.
31
+ required: false
32
+ default: 'Security-focused linter for Docker Compose files'
33
+
34
+ runs:
35
+ using: 'composite'
36
+ steps:
37
+ - name: Sync Docker Hub description
38
+ shell: bash
39
+ env:
40
+ DOCKERHUB_USERNAME: ${{ inputs.username }}
41
+ DOCKERHUB_TOKEN: ${{ inputs.token }}
42
+ DOCKERHUB_REPO: ${{ inputs.repository }}
43
+ README_PATH: ${{ inputs.readme-filepath }}
44
+ SHORT_DESCRIPTION: ${{ inputs.short-description }}
45
+ run: |
46
+ "${GITHUB_WORKSPACE}/scripts/update-dockerhub-description.sh" \
47
+ "${DOCKERHUB_REPO}" "${README_PATH}"
@@ -0,0 +1,30 @@
1
+ # SSH allowed-signers file for verifying compose-lint release tags.
2
+ #
3
+ # Format: <principal> [namespaces=...] <key-type> <base64-key> [comment]
4
+ # See `man ssh-keygen` SSH ALLOWED-SIGNERS FILE FORMAT for the full spec.
5
+ #
6
+ # `namespaces="git"` scopes the key to git-context signatures so it cannot
7
+ # be reused for arbitrary SSH signing if leaked.
8
+ #
9
+ # This file is consumed by the `verify-tag` job in .github/workflows/publish.yml,
10
+ # which runs `git verify-tag` against every release tag before any publish step.
11
+ # Adding a key here grants release-signing authority — treat changes like a
12
+ # maintainer promotion (see GOVERNANCE.md §"Adding a maintainer").
13
+ #
14
+ # To add or rotate a key:
15
+ # 1. Add a line below with the new public key.
16
+ # 2. Open a PR titled "Add release signing key for <name>" or "Rotate release signing key".
17
+ # 3. After merge, sign the next release tag with the new key. publish.yml
18
+ # will refuse to publish if it cannot verify against this file.
19
+ #
20
+ # Removing a key revokes release-signing authority and is a maintainer-removal
21
+ # action (see GOVERNANCE.md §"Removing a maintainer").
22
+
23
+ # Todd Matens — release signing key (used to sign vX.Y.Z annotated tags
24
+ # from v0.3.7 onward). Verified against tag v0.7.0 (commit 23da963).
25
+ tmatens@gmail.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINz74LQz7YwG5+9fSmqshOfarZt53sBYgFMTGMKJoBY+
26
+
27
+ # Todd Matens — release signing key for the remote/automated release path (added 2026-06-13).
28
+ # Same principal as the key above; signs vX.Y.Z annotated tags cut from the remote release
29
+ # flow rather than from a workstation. Grants release-signing authority (see GOVERNANCE.md).
30
+ tmatens@gmail.com namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDrB4X76XPEJmLX70W/hdIky3KvboFvWJJKCpL5RE1pT
@@ -0,0 +1,95 @@
1
+ <!--
2
+ Thanks for contributing! Fill in the sections below. Delete any that don't
3
+ apply. See CONTRIBUTING.md for the full workflow, commit conventions, and
4
+ signing requirements.
5
+ -->
6
+
7
+ ## Summary
8
+
9
+ <!-- What does this PR change? One or two sentences. -->
10
+
11
+ ## Why
12
+
13
+ <!-- Why is this change needed? Link to the issue, bug report, OWASP/CIS
14
+ reference, or incident that motivated it. -->
15
+
16
+ Closes #
17
+
18
+ ## Type of change
19
+
20
+ - [ ] New rule (`CL-XXXX`)
21
+ - [ ] Bug fix
22
+ - [ ] Refactor (no behavior change)
23
+ - [ ] Documentation
24
+ - [ ] Build / CI / release tooling
25
+ - [ ] Other:
26
+
27
+ ## Origin
28
+
29
+ <!-- Tick everything that applies. This helps a reviewer decide where to spend
30
+ attention; it does not affect whether the PR is accepted. -->
31
+
32
+ - [ ] Personal contribution
33
+ - [ ] Contributed on behalf of an employer or client
34
+ - [ ] Produced primarily by an automated agent
35
+
36
+ ## Evidence
37
+
38
+ <!-- The questions no check can answer for you. A line each is plenty, and
39
+ "n/a" is a fine answer where it doesn't apply — a blank one is not.
40
+ A question you find you can't answer is the finding. -->
41
+
42
+ **Which tests cover this change, and what do they assert?**
43
+
44
+ <!-- Name them, e.g. `tests/test_CL0031.py::test_flags_privileged`. CI
45
+ already requires 90% of the lines you touched to be covered, so "a test
46
+ executes this line" is proven before a reviewer arrives. This asks the
47
+ part coverage cannot see: whether the assertion would actually fail if
48
+ the behavior regressed. For a rule, that means a case that triggers and
49
+ a case that must not. -->
50
+
51
+ **What does this change make wrong elsewhere?**
52
+
53
+ <!-- README, docs/, examples, a rule page, a message quoted in a test. "It
54
+ doesn't" is a fine answer, but say it deliberately rather than by
55
+ leaving this empty. -->
56
+
57
+ ## Checklist
58
+
59
+ <!-- Short on purpose. CI checks sign-off, the four local gates, AI
60
+ attribution, the rule surfaces and the severity matrix, and a reviewer
61
+ reads those off the checks tab — repeating them here only asks you to
62
+ agree with a check that has already run. What's left is what CI cannot
63
+ see for itself. -->
64
+
65
+ - [ ] Commits are **signed** — GitHub shows a `Verified` badge on the commits
66
+ tab (proves *who committed*; not the same as signing off, which the
67
+ `dco` check enforces separately — see CONTRIBUTING.md)
68
+ - [ ] One logical change per commit; no unrelated changes bundled in
69
+ - [ ] `tests/corpus_snapshot.json.gz` is **not** in this PR (a maintainer regenerates it)
70
+
71
+ ## New rule only
72
+
73
+ <!-- Delete this section if this PR is not a new rule. -->
74
+
75
+ **Which source grounds this rule, and where does it demonstrate the need in a
76
+ container context?**
77
+
78
+ <!-- Link it and quote the line. OWASP, CIS or Docker docs. Generic
79
+ host/Linux hardening that a container's defaults already neutralize is
80
+ not enough — see CL-0022 and CL-0023, which were removed for exactly
81
+ that. If the container-context evidence is thin, the rule's premise
82
+ needs a runtime check in `scripts/validate_rule_premises.py` instead. -->
83
+
84
+ **Paste the before / after YAML a user would apply.**
85
+
86
+ <!-- Copy-pasteable, not a description of what to do. If you can't write the
87
+ "after" without knowing something the finding doesn't tell the user,
88
+ the fix guidance isn't specific enough yet. -->
89
+
90
+ ## Breaking changes
91
+
92
+ <!-- Does this change the CLI, config format, rule IDs, or exit code contract?
93
+ If yes, describe the migration path. If no, write "None". -->
94
+
95
+ None