Skip to content

feat(security): config secret redaction — Spring application.{properties,yml} + Shopify {% schema %} (closes #58 phase-2)#136

Merged
Wolfvin merged 1 commit into
mainfrom
feat/issue-58-config-secret-redaction-phase-2
Jul 1, 2026
Merged

feat(security): config secret redaction — Spring application.{properties,yml} + Shopify {% schema %} (closes #58 phase-2)#136
Wolfvin merged 1 commit into
mainfrom
feat/issue-58-config-secret-redaction-phase-2

Conversation

@Wolfvin

@Wolfvin Wolfvin commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

Implements Phase 2 of issue #58 — config secret redaction for Spring application.properties/application.yml and Shopify Liquid {% schema %} blocks.

(Supersedes the closed PR #133 — that PR was based on the Phase 1 branch feat/issue-58-path-traversal-phase-1, which got deleted when PR #131 was merged. This PR is rebased directly onto main and contains only the Phase 2 commit.)

CodeLens's job is to map code structure — not to be a vault for production secrets. But many config-file formats mix structural metadata (key names) with sensitive values (passwords, API keys, connection strings) in the same file. If an agent-driven extraction layer indexes these files naively, CodeLens becomes a secret sink — the value ends up in the SQLite registry, outline.json, MCP tool responses, and snapshot exports.

This PR provides format-aware redaction that returns a key-only view of these config files. The raw file content stays on disk — an agent that needs the actual value reads the file directly, just like any source file. CodeLens never persists it.

Depends on #131 (Phase 1, MERGED) — Phase 2's safe_read_file_for_indexing composes Phase 1's safe_read_file_within_project with the new redaction layer.

Files

New:

  • scripts/security/config_secret_redaction.pyredact_application_properties(), redact_application_yml(), redact_shopify_schema(), redact_config_file() (auto-detect), is_config_file(), safe_read_file_for_indexing() (composes Phase 1 path-traversal + Phase 2 redaction)
  • tests/test_config_secret_redaction.py — 63 tests covering all three formats, idempotency, malformed-JSON handling, profile-specific Spring variants, integration with Phase 1 path traversal

Modified:

  • scripts/security/__init__.py — re-exports Phase 2 public API alongside Phase 1

Key design decisions

  1. Conservative bias — when in doubt, redact. A false positive (redacting a non-secret value) costs an agent a file read; a false negative (storing a real secret) costs a security incident. The structural allowlist (server.port, spring.datasource.url, spring.application.name, etc.) is intentionally narrow.
  2. Line-by-line YAML parsing, not PyYAML. PyYAML is an optional dependency (Phase 1 doctor warns when missing); making it required for redaction would break CodeLens on minimal installs. Spring application.yml is a strict subset of YAML where every value is on the same line as its key — the line-by-line approach handles it correctly. A full YAML parser would also happily load anchors, tags, and multi-line strings — each one a redaction-bypass waiting to happen.
  3. YAML bare-key allowlist, not dotted-path. In YAML the key is the bare last segment (url:, port:, password:) — not the dotted path. The properties-file allowlist matches dotted paths; the YAML allowlist matches bare keys. Both are conservative.
  4. Shopify schema: parse JSON, walk in-place, re-serialize. Walks the parsed JSON tree, replacing every default field whose value is a non-empty string with <redacted>. Number/boolean defaults preserved (they're never secrets). Malformed JSON → block replaced with a {% comment %}schema redacted (malformed JSON){% endcomment %} marker so the agent sees something happened.
  5. safe_read_file_for_indexing composes Phase 1 + Phase 2. Single safe entry point for any extraction layer that might ingest config files: path-traversal check first (Phase 1), then format-aware redaction (Phase 2), then return.
  6. Idempotent. Re-running redaction on already-redacted content is a no-op (verified by tests) — so a future "redact on read AND on write" pipeline won't double-redact.
  7. Never raises on format errors. A parse failure in one config file must not break a workspace-wide scan. Falls back to a placeholder comment + log warning.

What Phase 2 deliberately does NOT do

  • It does not detect secrets by pattern (that's secrets_engine.py's job, already shipped).
  • It does not refuse to read config files (Phase 1 path-traversal handles file-access safety; this module handles value-persistence safety).
  • It does not auto-discover config files — callers pass file paths in. The redaction is a pure function on content.

Acceptance criteria

  • Spring application.properties values redacted (except structural allowlist)
  • Spring application.yml scalar values redacted (except allowlist + numbers/booleans)
  • Shopify {% schema %} string default fields redacted
  • Profile-specific Spring variants (application-prod.properties) detected
  • Malformed Shopify JSON handled safely (block replaced with comment marker)
  • Idempotent (re-redaction is a no-op)
  • safe_read_file_for_indexing integrates Phase 1 path-traversal + Phase 2 redaction
  • No new dependencies (uses stdlib json + re only)

(Phases 3–7 of #58 — git safety guard, Secretlint, file system MCP tools, LLM schema validation, PoC generation — are out of scope for this Phase 2 PR.)

Test results

  • 63 new tests in tests/test_config_secret_redaction.py — all pass
  • Phase 1 tests (tests/test_path_traversal.py, 41 tests) — still pass (no regression after rebase onto merged main)

Closes #58 (phase-2).

…ies,yml} + Shopify {% schema %} (closes #58 phase-2)
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Wolfvin Wolfvin merged commit a875428 into main Jul 1, 2026
0 of 7 checks passed
@Wolfvin Wolfvin deleted the feat/issue-58-config-secret-redaction-phase-2 branch July 1, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Security & safety hardening — path traversal, config secret redaction, git safety guard, Secretlint

1 participant