From ae0c6a421ad9bd2973c7f9bb030312a3098c48d5 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 27 Jul 2026 21:41:10 +0000 Subject: [PATCH 1/4] chore(security): ignore key material so an identity file cannot be committed data/hub/identity.json reached PR #2043 with private keys in plaintext. It never landed on dev, but the data/ ignore rules are a per-file allowlist so nothing would have stopped a repeat. Adds pattern-based ignores for key material. Verified no tracked file becomes ignored. --- .gitignore | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.gitignore b/.gitignore index fdb2c1ac2..99fe27ef3 100644 --- a/.gitignore +++ b/.gitignore @@ -152,3 +152,17 @@ data/.seeded-agent-tokens.json data/secrets.db* data/*.key data/*.token + +# Key material and secrets. Added 2026-07-28 after data/hub/identity.json was +# committed to PR #2043 with signing_private and encryption_private in +# PLAINTEXT. It was removed before merge and the repo squash-merges, so it never +# reached dev, but nothing STOPPED it. The data/ rules above are a per-file +# allowlist, so any new data file slips through; these are pattern-based so a +# future one cannot. Verified against every tracked file: none become ignored. +data/hub/ +*.key +*_private.* +*_private_key* +identity.json +*.p8 +*credentials.json From 4a0dc7893c5526a18cc810c3e0089bf71fb1493c Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 27 Jul 2026 21:55:23 +0000 Subject: [PATCH 2/4] chore: correct the date in the ignore comment CodeRabbit was right: the comment said 2026-07-28 but the change is dated 2026-07-27. The date came from a UTC-rolled timestamp rather than the actual date. A comment that exists to preserve WHY a rule was added should not carry a wrong WHEN. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 99fe27ef3..570976971 100644 --- a/.gitignore +++ b/.gitignore @@ -153,7 +153,7 @@ data/secrets.db* data/*.key data/*.token -# Key material and secrets. Added 2026-07-28 after data/hub/identity.json was +# Key material and secrets. Added 2026-07-27 after data/hub/identity.json was # committed to PR #2043 with signing_private and encryption_private in # PLAINTEXT. It was removed before merge and the repo squash-merges, so it never # reached dev, but nothing STOPPED it. The data/ rules above are a per-file From 97bd98e98d390750b57a0952f4ba8bbd7b803879 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 27 Jul 2026 22:10:54 +0000 Subject: [PATCH 3/4] chore: drop the duplicate data/hub/ rule and correct the rationale qodo was right. dev already ignores data/hub/ (line 96, added in #2042); my second copy was redundant and the two rationale comments would drift apart. The premise of my original comment was also wrong: I ran git check-ignore against a stale local branch rather than origin/dev, so I reported a gap dev had already closed. The other six patterns ARE genuinely new, and that is what this PR is now scoped to. --- .gitignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 570976971..c6cfd6c97 100644 --- a/.gitignore +++ b/.gitignore @@ -155,11 +155,11 @@ data/*.token # Key material and secrets. Added 2026-07-27 after data/hub/identity.json was # committed to PR #2043 with signing_private and encryption_private in -# PLAINTEXT. It was removed before merge and the repo squash-merges, so it never -# reached dev, but nothing STOPPED it. The data/ rules above are a per-file -# allowlist, so any new data file slips through; these are pattern-based so a -# future one cannot. Verified against every tracked file: none become ignored. -data/hub/ +# PLAINTEXT. data/hub/ is already covered above; these patterns close the REST +# of the surface, which was open: an identity.json or a *.key written anywhere +# outside data/hub/ had nothing stopping it. Pattern-based on purpose, since a +# per-file allowlist cannot catch a file that does not exist yet. +# Verified against every tracked file: none become ignored. *.key *_private.* *_private_key* From 6eeedf7df1bb0b3e8ad46cc327dd97b2f0e63994 Mon Sep 17 00:00:00 2001 From: jaylfc Date: Mon, 27 Jul 2026 22:25:54 +0000 Subject: [PATCH 4/4] chore: narrow *_private.* so it cannot swallow source files kilo was right that *_private.* is overly broad: it matches api_private.py, utils_private.ts and similar plausible source names, which would be silently untracked. Narrowed to the key-material extensions (.pem/.key/.json). Verified again against every tracked file, and that a _private.py is no longer caught. A pattern that silently ignores working source is worse than the hole it closes. --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c6cfd6c97..c17699b73 100644 --- a/.gitignore +++ b/.gitignore @@ -161,7 +161,9 @@ data/*.token # per-file allowlist cannot catch a file that does not exist yet. # Verified against every tracked file: none become ignored. *.key -*_private.* +*_private.pem +*_private.key +*_private.json *_private_key* identity.json *.p8