fix: address CodeQL alert and review findings

- config_manager: the "secrets list longer than config list" warning now
  interpolates only config-side data (no key name or secrets-derived
  values), resolving the CodeQL clear-text-logging alert.
- base_plugin: validate_config rejects bool display_duration, matching
  get_display_duration (bool is an int subclass and would otherwise pass
  as a positive number).
- config_helper: merge_configs deep-copies override values in the
  non-recursive branch so mutating the merged result cannot reach back
  into override_config.
- saved_repositories: saves are atomic (temp file + fsync + os.replace),
  so a failed write can no longer truncate saved_repositories.json.
- tests: regression cases for each fix, plus a pin that whole-item
  array secrets (key[] + key[].field both marked) strip to empty {}
  skeletons — no secret values can reach config.json.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NohXi78cwsAKtN1sCfxjUh
This commit is contained in:
Claude
2026-08-07 18:32:26 +00:00
parent c9239d0c46
commit 41f91a40b9
8 changed files with 114 additions and 11 deletions
+10
View File
@@ -139,6 +139,16 @@ class TestMergeConfigs:
assert base == {'a': {'b': 1}}
assert override == {'a': {'c': 2}}
def test_no_aliasing_of_override_values(self, helper):
# The non-recursive branch must deep-copy the override value too:
# mutating a merged-in list or dict must not reach back into
# override_config.
override = {'teams': ['A', 'B'], 'nested': {'x': [1]}}
merged = helper.merge_configs({}, override)
merged['teams'].append('C')
merged['nested']['x'].append(2)
assert override == {'teams': ['A', 'B'], 'nested': {'x': [1]}}
class TestValidateConfig:
def test_no_schema_dict_is_valid(self, helper):