compose-guard 0.1.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 (160) hide show
  1. compose_guard-0.1.0/.github/workflows/ci.yml +56 -0
  2. compose_guard-0.1.0/.github/workflows/publish.yml +31 -0
  3. compose_guard-0.1.0/.github/workflows/sarif-demo.yml +30 -0
  4. compose_guard-0.1.0/.gitignore +36 -0
  5. compose_guard-0.1.0/AGENTS.md +28 -0
  6. compose_guard-0.1.0/CHANGELOG.md +42 -0
  7. compose_guard-0.1.0/LICENSE +21 -0
  8. compose_guard-0.1.0/Makefile +18 -0
  9. compose_guard-0.1.0/PKG-INFO +449 -0
  10. compose_guard-0.1.0/README.md +413 -0
  11. compose_guard-0.1.0/SPEC.md +242 -0
  12. compose_guard-0.1.0/examples/hardened/compose.yaml +94 -0
  13. compose_guard-0.1.0/examples/insecure/compose.yaml +62 -0
  14. compose_guard-0.1.0/netlify.toml +11 -0
  15. compose_guard-0.1.0/pyproject.toml +81 -0
  16. compose_guard-0.1.0/scripts/update_readme.py +115 -0
  17. compose_guard-0.1.0/src/compose_guard/__init__.py +5 -0
  18. compose_guard-0.1.0/src/compose_guard/__main__.py +6 -0
  19. compose_guard-0.1.0/src/compose_guard/cli.py +182 -0
  20. compose_guard-0.1.0/src/compose_guard/config.py +150 -0
  21. compose_guard-0.1.0/src/compose_guard/engine.py +73 -0
  22. compose_guard-0.1.0/src/compose_guard/errors.py +28 -0
  23. compose_guard-0.1.0/src/compose_guard/interpolation.py +20 -0
  24. compose_guard-0.1.0/src/compose_guard/loader.py +196 -0
  25. compose_guard-0.1.0/src/compose_guard/model.py +120 -0
  26. compose_guard-0.1.0/src/compose_guard/report/__init__.py +20 -0
  27. compose_guard-0.1.0/src/compose_guard/report/json_report.py +65 -0
  28. compose_guard-0.1.0/src/compose_guard/report/sarif.py +95 -0
  29. compose_guard-0.1.0/src/compose_guard/report/text.py +58 -0
  30. compose_guard-0.1.0/src/compose_guard/rules/__init__.py +41 -0
  31. compose_guard-0.1.0/src/compose_guard/rules/base.py +98 -0
  32. compose_guard-0.1.0/src/compose_guard/rules/images.py +43 -0
  33. compose_guard-0.1.0/src/compose_guard/rules/network.py +121 -0
  34. compose_guard-0.1.0/src/compose_guard/rules/parsing.py +301 -0
  35. compose_guard-0.1.0/src/compose_guard/rules/reliability.py +202 -0
  36. compose_guard-0.1.0/src/compose_guard/rules/resources.py +57 -0
  37. compose_guard-0.1.0/src/compose_guard/rules/security.py +273 -0
  38. compose_guard-0.1.0/src/compose_guard/rules/validation.py +91 -0
  39. compose_guard-0.1.0/src/compose_guard/suppress.py +68 -0
  40. compose_guard-0.1.0/tests/__init__.py +0 -0
  41. compose_guard-0.1.0/tests/fixtures/README.md +17 -0
  42. compose_guard-0.1.0/tests/fixtures/bad_cd000.yaml +33 -0
  43. compose_guard-0.1.0/tests/fixtures/bad_cd001.yaml +11 -0
  44. compose_guard-0.1.0/tests/fixtures/bad_cd002.yaml +10 -0
  45. compose_guard-0.1.0/tests/fixtures/bad_cd003.yaml +11 -0
  46. compose_guard-0.1.0/tests/fixtures/bad_cd004.yaml +4 -0
  47. compose_guard-0.1.0/tests/fixtures/bad_cd005.yaml +27 -0
  48. compose_guard-0.1.0/tests/fixtures/bad_cd006.yaml +17 -0
  49. compose_guard-0.1.0/tests/fixtures/bad_cd007.yaml +26 -0
  50. compose_guard-0.1.0/tests/fixtures/bad_cd008.yaml +14 -0
  51. compose_guard-0.1.0/tests/fixtures/bad_cd009.yaml +19 -0
  52. compose_guard-0.1.0/tests/fixtures/bad_cd010.yaml +9 -0
  53. compose_guard-0.1.0/tests/fixtures/bad_cd011.yaml +10 -0
  54. compose_guard-0.1.0/tests/fixtures/bad_cd012.yaml +9 -0
  55. compose_guard-0.1.0/tests/fixtures/bad_cd013.yaml +6 -0
  56. compose_guard-0.1.0/tests/fixtures/bad_cd014.yaml +16 -0
  57. compose_guard-0.1.0/tests/fixtures/bad_cd015.yaml +4 -0
  58. compose_guard-0.1.0/tests/fixtures/good_cd000.yaml +54 -0
  59. compose_guard-0.1.0/tests/fixtures/good_cd001.yaml +19 -0
  60. compose_guard-0.1.0/tests/fixtures/good_cd002.yaml +6 -0
  61. compose_guard-0.1.0/tests/fixtures/good_cd003.yaml +13 -0
  62. compose_guard-0.1.0/tests/fixtures/good_cd004.yaml +9 -0
  63. compose_guard-0.1.0/tests/fixtures/good_cd005.yaml +21 -0
  64. compose_guard-0.1.0/tests/fixtures/good_cd006.yaml +18 -0
  65. compose_guard-0.1.0/tests/fixtures/good_cd007.yaml +19 -0
  66. compose_guard-0.1.0/tests/fixtures/good_cd008.yaml +23 -0
  67. compose_guard-0.1.0/tests/fixtures/good_cd009.yaml +23 -0
  68. compose_guard-0.1.0/tests/fixtures/good_cd010.yaml +10 -0
  69. compose_guard-0.1.0/tests/fixtures/good_cd011.yaml +9 -0
  70. compose_guard-0.1.0/tests/fixtures/good_cd012.yaml +7 -0
  71. compose_guard-0.1.0/tests/fixtures/good_cd013.yaml +8 -0
  72. compose_guard-0.1.0/tests/fixtures/good_cd014.yaml +14 -0
  73. compose_guard-0.1.0/tests/fixtures/good_cd015.yaml +3 -0
  74. compose_guard-0.1.0/tests/fixtures/privacy_broken.yaml +11 -0
  75. compose_guard-0.1.0/tests/fixtures/privacy_secrets.yaml +14 -0
  76. compose_guard-0.1.0/tests/golden/insecure.json +288 -0
  77. compose_guard-0.1.0/tests/integration/__init__.py +0 -0
  78. compose_guard-0.1.0/tests/integration/test_cli_integration.py +217 -0
  79. compose_guard-0.1.0/tests/integration/test_readme.py +37 -0
  80. compose_guard-0.1.0/tests/unit/__init__.py +0 -0
  81. compose_guard-0.1.0/tests/unit/test_cli.py +195 -0
  82. compose_guard-0.1.0/tests/unit/test_config.py +143 -0
  83. compose_guard-0.1.0/tests/unit/test_engine_and_reports.py +190 -0
  84. compose_guard-0.1.0/tests/unit/test_errors.py +20 -0
  85. compose_guard-0.1.0/tests/unit/test_interpolation.py +45 -0
  86. compose_guard-0.1.0/tests/unit/test_loader.py +404 -0
  87. compose_guard-0.1.0/tests/unit/test_model.py +27 -0
  88. compose_guard-0.1.0/tests/unit/test_parsing.py +204 -0
  89. compose_guard-0.1.0/tests/unit/test_rules.py +133 -0
  90. compose_guard-0.1.0/tests/unit/test_suppress.py +66 -0
  91. compose_guard-0.1.0/tests/unit/test_version.py +46 -0
  92. compose_guard-0.1.0/web/README.md +92 -0
  93. compose_guard-0.1.0/web/eslint.config.js +23 -0
  94. compose_guard-0.1.0/web/index.html +27 -0
  95. compose_guard-0.1.0/web/package-lock.json +4755 -0
  96. compose_guard-0.1.0/web/package.json +61 -0
  97. compose_guard-0.1.0/web/public/_headers +15 -0
  98. compose_guard-0.1.0/web/public/_redirects +2 -0
  99. compose_guard-0.1.0/web/public/favicon.svg +1 -0
  100. compose_guard-0.1.0/web/public/theme-init.js +13 -0
  101. compose_guard-0.1.0/web/scripts/e2e.mjs +219 -0
  102. compose_guard-0.1.0/web/scripts/export_snapshot.py +51 -0
  103. compose_guard-0.1.0/web/scripts/prepare-runtime.mjs +56 -0
  104. compose_guard-0.1.0/web/scripts/runtime-config.d.mts +8 -0
  105. compose_guard-0.1.0/web/scripts/runtime-config.mjs +18 -0
  106. compose_guard-0.1.0/web/scripts/serve.mjs +74 -0
  107. compose_guard-0.1.0/web/src/App.tsx +75 -0
  108. compose_guard-0.1.0/web/src/analyzer/analyzer.worker.ts +58 -0
  109. compose_guard-0.1.0/web/src/analyzer/bridge.py +79 -0
  110. compose_guard-0.1.0/web/src/analyzer/client.test.ts +88 -0
  111. compose_guard-0.1.0/web/src/analyzer/client.ts +141 -0
  112. compose_guard-0.1.0/web/src/analyzer/protocol.ts +12 -0
  113. compose_guard-0.1.0/web/src/analyzer/runtime.node.test.ts +157 -0
  114. compose_guard-0.1.0/web/src/analyzer/runtime.ts +49 -0
  115. compose_guard-0.1.0/web/src/analyzer/sources.ts +25 -0
  116. compose_guard-0.1.0/web/src/analyzer/types.ts +65 -0
  117. compose_guard-0.1.0/web/src/analyzer/useAnalyzer.ts +77 -0
  118. compose_guard-0.1.0/web/src/components/layout/SiteFooter.tsx +76 -0
  119. compose_guard-0.1.0/web/src/components/layout/SiteHeader.tsx +107 -0
  120. compose_guard-0.1.0/web/src/components/layout/ThemeToggle.tsx +35 -0
  121. compose_guard-0.1.0/web/src/components/ui/Button.tsx +69 -0
  122. compose_guard-0.1.0/web/src/components/ui/CodeBlock.tsx +41 -0
  123. compose_guard-0.1.0/web/src/components/ui/CopyButton.tsx +50 -0
  124. compose_guard-0.1.0/web/src/components/ui/Severity.tsx +47 -0
  125. compose_guard-0.1.0/web/src/components/ui/YamlLines.tsx +74 -0
  126. compose_guard-0.1.0/web/src/components/ui/icons.tsx +26 -0
  127. compose_guard-0.1.0/web/src/examples/index.ts +132 -0
  128. compose_guard-0.1.0/web/src/examples/invalid.yaml +13 -0
  129. compose_guard-0.1.0/web/src/examples/malformed.yaml +6 -0
  130. compose_guard-0.1.0/web/src/examples/reliability.yaml +37 -0
  131. compose_guard-0.1.0/web/src/examples/security.yaml +37 -0
  132. compose_guard-0.1.0/web/src/examples/suppressions.yaml +40 -0
  133. compose_guard-0.1.0/web/src/features/playground/AnalysisSummary.tsx +73 -0
  134. compose_guard-0.1.0/web/src/features/playground/FindingItem.tsx +111 -0
  135. compose_guard-0.1.0/web/src/features/playground/FindingsList.test.tsx +53 -0
  136. compose_guard-0.1.0/web/src/features/playground/FindingsList.tsx +169 -0
  137. compose_guard-0.1.0/web/src/features/playground/PlaygroundPage.tsx +363 -0
  138. compose_guard-0.1.0/web/src/features/playground/RawOutput.tsx +41 -0
  139. compose_guard-0.1.0/web/src/features/playground/ResultsPanel.tsx +225 -0
  140. compose_guard-0.1.0/web/src/features/playground/YamlEditor.tsx +220 -0
  141. compose_guard-0.1.0/web/src/generated/analyzer-snapshot.json +200 -0
  142. compose_guard-0.1.0/web/src/index.css +156 -0
  143. compose_guard-0.1.0/web/src/lib/cn.ts +4 -0
  144. compose_guard-0.1.0/web/src/lib/download.ts +11 -0
  145. compose_guard-0.1.0/web/src/lib/rules.test.ts +11 -0
  146. compose_guard-0.1.0/web/src/lib/rules.ts +49 -0
  147. compose_guard-0.1.0/web/src/lib/site.ts +23 -0
  148. compose_guard-0.1.0/web/src/lib/storage.ts +19 -0
  149. compose_guard-0.1.0/web/src/lib/theme.ts +38 -0
  150. compose_guard-0.1.0/web/src/main.tsx +18 -0
  151. compose_guard-0.1.0/web/src/pages/DocsPage.tsx +260 -0
  152. compose_guard-0.1.0/web/src/pages/ExamplesPage.tsx +85 -0
  153. compose_guard-0.1.0/web/src/pages/HomePage.tsx +356 -0
  154. compose_guard-0.1.0/web/src/pages/NotFoundPage.tsx +19 -0
  155. compose_guard-0.1.0/web/src/pages/pages.test.tsx +51 -0
  156. compose_guard-0.1.0/web/src/test/render.tsx +7 -0
  157. compose_guard-0.1.0/web/src/test/setup.ts +7 -0
  158. compose_guard-0.1.0/web/src/vite-env.d.ts +11 -0
  159. compose_guard-0.1.0/web/tsconfig.json +21 -0
  160. compose_guard-0.1.0/web/vite.config.ts +25 -0
@@ -0,0 +1,56 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ concurrency:
11
+ group: ci-${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ check:
16
+ name: check (Python ${{ matrix.python-version }})
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+ cache: pip
28
+ cache-dependency-path: pyproject.toml
29
+ - name: Install
30
+ run: make install
31
+ - name: Check
32
+ run: make check
33
+
34
+ web:
35
+ name: web playground
36
+ runs-on: ubuntu-latest
37
+ defaults:
38
+ run:
39
+ working-directory: web
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: actions/setup-node@v4
43
+ with:
44
+ node-version: "22"
45
+ cache: npm
46
+ cache-dependency-path: web/package-lock.json
47
+ - name: Install
48
+ run: npm ci
49
+ - name: Lint and type-check
50
+ run: npm run lint && npm run typecheck
51
+ - name: Unit tests (including the real analyzer in Pyodide)
52
+ run: npm test
53
+ - name: Build
54
+ run: npm run build
55
+ - name: End-to-end tests
56
+ run: npx playwright install --with-deps chromium && npm run test:e2e
@@ -0,0 +1,31 @@
1
+ # Publish compose-guard to PyPI when a GitHub Release is published.
2
+ # Requires a Trusted Publisher on https://pypi.org/manage/account/publishing/
3
+ # for owner yagnang-vyas, repo compose-guard, workflow publish.yml, environment pypi.
4
+ name: Publish
5
+
6
+ on:
7
+ release:
8
+ types: [published]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ publish:
16
+ name: PyPI
17
+ runs-on: ubuntu-latest
18
+ environment: pypi
19
+ permissions:
20
+ id-token: write
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.13"
26
+ - name: Build
27
+ run: |
28
+ python -m pip install --upgrade pip build
29
+ python -m build
30
+ - name: Publish
31
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,30 @@
1
+ # Uploads Compose Guard findings for the deliberately insecure example to GitHub code scanning.
2
+ # Manual only, so the example does not create permanent alerts on every push.
3
+ name: SARIF demo
4
+
5
+ on:
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ security-events: write
11
+
12
+ jobs:
13
+ scan:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.13"
20
+ - name: Install Compose Guard
21
+ run: pip install .
22
+ - name: Lint the insecure example
23
+ run: >
24
+ compose-guard examples/insecure/compose.yaml
25
+ --format sarif --fail-on never > compose-guard.sarif
26
+ - name: Upload to code scanning
27
+ uses: github/codeql-action/upload-sarif@v3
28
+ with:
29
+ sarif_file: compose-guard.sarif
30
+ category: compose-guard
@@ -0,0 +1,36 @@
1
+ # Byte-compiled / cache
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+
8
+ # Packaging
9
+ build/
10
+ dist/
11
+ *.egg-info/
12
+ .eggs/
13
+
14
+ # Coverage
15
+ .coverage
16
+ .coverage.*
17
+ htmlcov/
18
+ coverage.xml
19
+
20
+ # Virtual environments
21
+ .venv/
22
+ venv/
23
+ env/
24
+
25
+ # Local secrets
26
+ .env
27
+
28
+ # Editors / OS
29
+ .idea/
30
+ .vscode/
31
+ .DS_Store
32
+
33
+ # Web playground
34
+ web/node_modules/
35
+ web/dist/
36
+ web/public/runtime/
@@ -0,0 +1,28 @@
1
+ # Working on Compose Guard
2
+
3
+ These rules apply to every change, whether made by a person or an AI coding agent.
4
+
5
+ 1. **Real functionality only.** No stubs, `pass` bodies, `TODO` placeholders, or mocked behaviour
6
+ presented as working.
7
+ 2. **Fix, don't report.** When a check fails, fix the code. Never weaken or skip a test, add
8
+ `# type: ignore` / `# noqa` without a one-line justification comment, or lower the coverage
9
+ threshold.
10
+ 3. **No invented output.** Every sample output in README.md must come from actually running the CLI.
11
+ 4. **Never print secret values.** Findings about environment variables name the *key* only. No
12
+ output format, error message or log line may contain an environment value from the input file.
13
+ 5. **Safe YAML only.** Never call `yaml.load` or construct arbitrary Python objects. Parse with
14
+ `yaml.compose` (node tree) and convert nodes in `loader.py`.
15
+ 6. **One runtime dependency:** `PyYAML`. Justify any other in SPEC.md; prefer the standard library.
16
+ 7. **Fixtures are synthetic** and use obviously fake values (see `tests/fixtures/README.md`).
17
+ 8. **Git:** Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`).
18
+ Run `make check` before every commit; do not commit while it fails.
19
+ 9. If something is ambiguous or contradictory, take the most conservative interpretation and
20
+ record it in SPEC.md under "Decisions".
21
+
22
+ ## Commands
23
+
24
+ ```
25
+ make install # pip install -e ".[dev]"
26
+ make check # ruff, ruff format --check, mypy --strict, pytest with >=90% branch coverage
27
+ make format # apply ruff formatting and safe fixes
28
+ ```
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Changed
10
+
11
+ - Renamed the project to **Compose Guard** for PyPI publication (`compose-doctor` was already
12
+ taken by an unrelated package). Distribution/CLI `compose-guard`, import `compose_guard`,
13
+ config `.compose-guard.yml`, suppressions `# compose-guard: …`, exception base
14
+ `ComposeGuardError`, and repository/docs/UI branding. Rule IDs `CD000`–`CD015` are unchanged.
15
+
16
+ ### Added
17
+
18
+ - Web playground in `web/`: a landing page, docs, examples and an editor that runs the real
19
+ `compose_guard` package in the browser with Pyodide, with Netlify configuration and CI.
20
+ - GitHub Actions workflow that publishes to PyPI on a published GitHub Release (Trusted Publishing).
21
+
22
+ ## [0.1.0] - 2026-10-25
23
+
24
+ ### Added
25
+
26
+ - Located YAML loader built on `yaml.compose`: 1-based line and column for every key and list
27
+ item, YAML 1.1 aliases and merge keys, and protection against alias bombs, recursive aliases and
28
+ deep nesting.
29
+ - Sixteen rules: CD000 (invalid configuration) and CD001–CD015 covering image pinning, privileged
30
+ mode, Docker socket and sensitive host mounts, host networking and namespaces, exposed database
31
+ ports, hard-coded secrets, dangerous capabilities, disabled security profiles, healthchecks,
32
+ restart policies, `depends_on` conditions, memory limits and fixed container names.
33
+ - Text, JSON (`schema_version` 1) and SARIF 2.1.0 output.
34
+ - Inline suppressions (`# compose-doctor: ignore ...`, `ignore-file`) and a `.compose-doctor.yml`
35
+ config file with global and per-service ignores, severity overrides and `fail_on`
36
+ (renamed to Compose Guard in Unreleased).
37
+ - CLI with default-file discovery, standard input, `--fail-on`, `--ignore`, `--show-suppressed`,
38
+ `--list-rules` and documented exit codes.
39
+ - Insecure and hardened example stacks, CI on Python 3.10–3.13, and a manually triggered SARIF
40
+ upload workflow.
41
+
42
+ [0.1.0]: https://github.com/yagnang-vyas/compose-guard/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yagnang Vyas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ .PHONY: install lint typecheck test check format
2
+
3
+ install:
4
+ pip install -e ".[dev]"
5
+
6
+ lint:
7
+ ruff check . && ruff format --check .
8
+
9
+ typecheck:
10
+ mypy src
11
+
12
+ test:
13
+ pytest --cov=compose_guard --cov-branch --cov-report=term-missing --cov-fail-under=90
14
+
15
+ check: lint typecheck test
16
+
17
+ format:
18
+ ruff format . && ruff check --fix .