|
| 1 | +# Security Policy |
| 2 | + |
| 3 | +## Supported versions |
| 4 | + |
| 5 | +`claude-memory-lint` ships fixes only on the latest minor line. Older |
| 6 | +minor releases receive no security backports — upgrade to the latest |
| 7 | +release to get fixes. |
| 8 | + |
| 9 | +| Version | Supported | |
| 10 | +| --- | --- | |
| 11 | +| `0.3.x` | ✅ | |
| 12 | +| `0.2.x` | ❌ — please upgrade | |
| 13 | +| `< 0.2` | ❌ — please upgrade | |
| 14 | + |
| 15 | +## Reporting a vulnerability |
| 16 | + |
| 17 | +**Please do not open a public GitHub issue for security problems.** |
| 18 | +Instead, file a private report through GitHub Security Advisories: |
| 19 | + |
| 20 | +1. Open the [repository Security tab](https://github.com/hinanohart/claude-memory-lint/security/advisories/new). |
| 21 | +2. Click **"Report a vulnerability"** and describe what you found — |
| 22 | + reproduction steps, the affected version, and the impact you can |
| 23 | + demonstrate. |
| 24 | +3. Maintainers acknowledge new advisories within **7 days**, and aim |
| 25 | + to ship a fix within **30 days** of acknowledgement when the report |
| 26 | + is reproducible. Reports that turn out to be wider issues (e.g. |
| 27 | + upstream Python or runner bugs) are co-disclosed with the relevant |
| 28 | + project on a coordinated timeline. |
| 29 | + |
| 30 | +If GitHub Security Advisories is unavailable for any reason, you may |
| 31 | +fall back to opening an issue titled "security: please contact me |
| 32 | +privately" without reproduction details, and a maintainer will reach |
| 33 | +out off-platform. |
| 34 | + |
| 35 | +## In scope |
| 36 | + |
| 37 | +We treat the following as security-relevant and welcome reports on |
| 38 | +them: |
| 39 | + |
| 40 | +* **Secret leakage by the linter itself** — any path through which a |
| 41 | + matched secret literal reaches stdout, stderr, the JSON / SARIF |
| 42 | + output, the `.bak` file, log files, or any error message. R009 has |
| 43 | + defence-in-depth tests asserting the matched substring is never |
| 44 | + written to user-facing output; a regression there is the most |
| 45 | + serious class of bug this project can ship. |
| 46 | +* **Path-handling weaknesses** — any way to make `cml fix` write |
| 47 | + outside the directory it was pointed at, follow symlinks into |
| 48 | + unrelated trees, or overwrite files under a malicious target name. |
| 49 | +* **Backup-file leakage** — `.bak` files written by `cml fix` are |
| 50 | + created with mode `600`. A regression that widens those permissions, |
| 51 | + or that writes `.bak` files outside the corpus directory, is in |
| 52 | + scope. |
| 53 | +* **Atomic-write regressions** — `cml fix` writes through tmpfile + |
| 54 | + rename to avoid leaving a truncated file on `SIGKILL`. Any change |
| 55 | + that observably leaves a half-written `.md` is in scope. |
| 56 | +* **Privacy regressions** — the `stats` command and JSON output deliberately |
| 57 | + print only filenames, rule IDs, and counts. A change that leaks |
| 58 | + body content into any non-`text` reporter is in scope. |
| 59 | +* **Supply-chain integrity of releases** — issues with the OIDC-based |
| 60 | + PyPI publish workflow (see `.github/workflows/publish.yml`), |
| 61 | + including any change that lets a non-`main` branch produce a |
| 62 | + PyPI release, or that bypasses the test / lint / privacy-scan |
| 63 | + gates that run before publication. |
| 64 | + |
| 65 | +## Out of scope |
| 66 | + |
| 67 | +* Dependency advisories on transitively-installed packages that are |
| 68 | + development-only (e.g. `pytest`, `ruff`, `build`, `twine`). Report |
| 69 | + those upstream; we will follow when a fix is released. |
| 70 | +* Lint findings that you disagree with. Open a regular issue for |
| 71 | + rule-design feedback. |
| 72 | +* Theoretical attacks against secret patterns the linter does not |
| 73 | + claim to detect. R009 enumerates the supported pattern set; expanding |
| 74 | + it is enhancement work, not a security report. |
| 75 | + |
| 76 | +## Hardening posture |
| 77 | + |
| 78 | +Some defences are already in place and are exercised by the test |
| 79 | +suite or CI: |
| 80 | + |
| 81 | +* **No LLM API calls.** The linter is heuristic-only; matched content |
| 82 | + never leaves the local machine. |
| 83 | +* **Atomic writes** for `cml fix` (`tmpfile + os.replace`). |
| 84 | +* **Mode 600** on `.bak` files and on the temp file used for atomic |
| 85 | + replacement. |
| 86 | +* **`realpath` confinement** in path resolution for `cml fix` so |
| 87 | + symlinks cannot redirect a write to an arbitrary tree (see |
| 88 | + `src/cml/cli.py` and the corresponding unit tests). |
| 89 | +* **Privacy-scan workflow** runs on every PR; see |
| 90 | + `.github/workflows/test.yml`. Catches token literals committed |
| 91 | + alongside unrelated changes. |
| 92 | +* **Pre-commit secret scan** (`pre-commit-security` hook) runs on the |
| 93 | + maintainer side as the last write-time gate before a commit lands |
| 94 | + on this repository. |
| 95 | +* **OIDC-based PyPI publishing** with `attestations: true` (PEP 740) |
| 96 | + starting at `0.3.1` — downstream installers can verify artifact |
| 97 | + provenance without long-lived API tokens. |
0 commit comments