Skip to content

feat(policy): gate credential-bearing file writes and .env as protected metadata - #4

Open
AtropinolTT wants to merge 1 commit into
NanmiCoder:mainfrom
AtropinolTT:feat/credential-write-guard-v2
Open

feat(policy): gate credential-bearing file writes and .env as protected metadata#4
AtropinolTT wants to merge 1 commit into
NanmiCoder:mainfrom
AtropinolTT:feat/credential-write-guard-v2

Conversation

@AtropinolTT

Copy link
Copy Markdown

Why: DESIGN.md lists "credentials, tokens, private keys" as protected material, but the workspace-local file-mutation fast path currently allows any content without classification. An agent (or prompt-injected repo) can write AKIA.../ghp_.../sk-.../BEGIN PRIVATE KEY material into a project file with no review.

What: containsSecretMaterial() matches strong credential/private-key patterns in file-mutation payloads (write/edit content fields and str_replace_editor old_str/new_str/file_text). Hits route to ask instead of the fast-path allow: classifier-eligible for write/edit (their content fields are redacted by the classifier sanitizer), direct ask for str_replace_editor (its payload fields are not covered by the sanitizer's content-key redaction, so the credential would otherwise reach the classifier in cleartext). .env and .env.* (multi-segment included) join isProtectedProjectPath, so env-file writes require explicit authorization.

Design notes: Weak patterns (password = "...") are deliberately excluded — they are routine in fixtures/templates, and classifier payloads already redact content fields. Credential hits are ask rather than hard deny, consistent with the DESIGN.md principle that blanket rules should not block targets the user explicitly authorized; str_replace_editor is the one exception (direct ask) purely because its payload fields are outside the sanitizer's redaction coverage.

Tests: table-driven policy tests covering every regex branch across write/edit and str_replace_editor (credential → ask; ordinary fixture write → allow; .env* → ask; multi-segment .env.development.local → ask). Full suite: 68/68 passing; tsc --noEmit clean (host + client).


Appendix — Known gaps and follow-up intent (PR-B)

This guard covers the file-mutation tools (write/edit/str_replace_editor). Two write paths remain outside its scope by design: shell redirection (echo "AKIA..." > .env) and patch-style tools (apply_patch). The shell-redirect path is the subject of a planned follow-up (PR-B): evaluate shell command segments for credential material in redirect targets (reusing containsSecretMaterial, no new patterns), submitted as a separate PR after this one lands and maintainer feedback is heard.

…ed metadata

containsSecretMaterial() matches strong credential/private-key patterns
(AKIA/ASIA, ghp_/gho_/ghu_/ghs_/github_pat_, sk-(proj-)?, and BEGIN
RSA|OPENSSH|EC|ECDSA|DSA|ENCRYPTED PRIVATE KEY blocks) in file-mutation
payloads - write/edit content fields and str_replace_editor
old_str/new_str/file_text. Hits route to ask instead of the fast-path
allow: classifier-eligible for write/edit (their content fields are
redacted by the classifier sanitizer), direct ask for str_replace_editor
(its payload fields are not covered by the sanitizer's content-key
redaction, so the credential would otherwise reach the classifier in
cleartext).

.env and .env.* (multi-segment included) join isProtectedProjectPath, so
env-file writes require explicit authorization. The str_replace_editor
secret check runs before the protected-path check so credential writes to
.env can never be routed to the classifier in cleartext.

Weak patterns (password = "...") are deliberately excluded - they are
routine in fixtures/templates. Credential hits are ask rather than hard
deny, consistent with the DESIGN.md principle that blanket rules should
not block targets the user explicitly authorized.

Tests: table-driven policy tests covering every regex branch across
write/edit and str_replace_editor (credential -> ask; ordinary fixture
write -> allow; .env* -> ask; multi-segment .env.development.local ->
ask). Full suite: 68/68 passing; tsc --noEmit clean (host + client).
@NanmiCoder

Copy link
Copy Markdown
Owner

感谢贡献!v0.1.4 已将 Auto 重构为 sandbox-first:workspace 内普通写入默认由沙盒约束,凭证读取与外发在风险边界单独处理,因此暂不合入基于 .env* 和 Token 正则拦截写入的方案,以免影响正常开发。

这个 PR 指出的 str_replace_editor 脱敏字段缺口是有效的,我们会拆成更通用的 sanitizer 修复单独处理。

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.

2 participants