Development record
GHSA-22f8-qf5r-gjgq (CWE-451, CWE-1427): a `.abcd/rules.json` override replaces a bundled domain's rules wholesale (`mergeDomain`, internal/core/rules/rules.go) and nothing downstream records where the words came from — `ResolvedDomain` carries no origin, `renderDomain` emits name and bullets only, the prompt-router diagnostic prints names, and `abcd rules --json` marshals the same origin-less shape — so a hostile or compromised checkout injects attacker-chosen text under `## PII` and the tool's own `# abcd rules` header, byte-indistinguishable from a bundled default in every consumer-visible surface. Reproduced at v0.7.0. The fix must derive provenance at merge time with no rules.json schema change: a `source` field on `ResolvedDomain` valued `bundled` or `repo` (leaving room for `user`, spc-23 AC6), the rendered heading `## NAME (repo override)` for a repo-sourced domain so the marker lands in the agent's context, in `abcd rules` and inside the dedup signature, the source per injected name on the hook's stderr diagnostic, and the field in `rules --json`. The marker moves `Signature` for overridden domains only: a one-time re-injection on the first post-upgrade prompt. Named as out of scope: the guard registry merge (internal/core/guard/config.go) has the same provenance-less shape for `.abcd/guard.json` overrides, but its surface is a block/allow decision, not injected prose. Siblings captured separately: `"rules": []` injecting a heading-only block, and a stop-word recall keyword firing on ordinary prose. iss-174 (an override withholds bundled upgrades) stays open and distinct. Advisory severity medium.
GHSA-22f8-qf5r-gjgq (CWE-451, CWE-1427): a .abcd/rules.json override replaces a bundled domain's rules wholesale (mergeDomain, internal/core/rules/rules.go) and nothing downstream records where the words came from — ResolvedDomain carries no origin, renderDomain emits name and bullets only, the prompt-router diagnostic prints names, and abcd rules --json marshals the same origin-less shape — so a hostile or compromised checkout injects attacker-chosen text under ## PII and the tool's own # abcd rules header, byte-indistinguishable from a bundled default in every consumer-visible surface. Reproduced at v0.7.0. The fix must derive provenance at merge time with no rules.json schema change: a source field on ResolvedDomain valued bundled or repo (leaving room for user, spc-23 AC6), the rendered heading ## NAME (repo override) for a repo-sourced domain so the marker lands in the agent's context, in abcd rules and inside the dedup signature, the source per injected name on the hook's stderr diagnostic, and the field in rules --json. The marker moves Signature for overridden domains only: a one-time re-injection on the first post-upgrade prompt. Named as out of scope: the guard registry merge (internal/core/guard/config.go) has the same provenance-less shape for .abcd/guard.json overrides, but its surface is a block/allow decision, not injected prose. Siblings captured separately: "rules": [] injecting a heading-only block, and a stop-word recall keyword firing on ordinary prose. iss-174 (an override withholds bundled upgrades) stays open and distinct. Advisory severity medium.
Grounds
- pursued: provenance, not permission, is the fix the advisory and spc-23 both call for; the origin is only knowable at merge, so it is recorded there and read by every consumer through one field
Frontmatter
| id | iss-2609012039215212 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2609012039215212-ghsa-22f8-qf5r-gjgq-cwe-451-cwe-1427-a.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-174mergeDomain replaces a domain's recall and rules arrays wholesale, so a repo that overrides either array silently withholds every later security upgrade to the bundled defaults: internal/core/rules/rules.go copies the override array over the base one instead of unioning, with no schema bump and no notice, so a repo that pinned PII recall or PII rules before iss-156 keeps the old set and never sees the new network keywords or the never-commit-network-identifiers rule line. Per-field merge is the documented and wanted behaviour for state, but for security-bearing arrays the quiet outcome is a stale ruleset that looks current. Options to weigh: union rather than replace for recall/aliases (additive, no loss), a distinct replace-vs-extend marker in the override, or at minimum a loud diagnostic in abcd rules naming which bundled entries an override is withholding. First activated by the iss-156 PII upgrade, which is why it is captured now. Prior disposition to weigh when triaging: iss-66 (resolved, rules-loader trust boundary) document-accepted the adjacent risk that an override can weaken a default guardrail domain (its P15); this entry is the distinct case of an override silently withholding later upgrades rather than deliberately silencing a domain.
- spc-23development-instructions-live-in-the-right-tier-abcd-manages