Summary
.claude/hooks/safety-guardrails.py (PreToolUse guardrail, mapify_version 3.20.0) blocks Edit/Write on legitimate, non-credential files whenever any path segment matches secrets? and the file has a .json/.yaml/.yml/.toml extension — even when the "secret" match comes from a directory/component name (e.g. secrets-injector, stackland-secrets-webhook) rather than an actual credentials file.
Observed
Working in azalio/quantum (Stackland platform monorepo), branch caldera-firestorm, on a MAP subtask (ST-001) whose entire job is to add a skipTLSVerify Helm value/env var to a component literally named "secrets injector" / "stackland-secrets-webhook" (a legitimate webhook that injects secrets into pods — the name itself, not a credential file).
All four target Edit calls were denied with File is in a directory that is denied by your permission settings.:
secrets-injector/deploy/webhook/helm/stackland-secrets-webhook/values.yaml
secrets-injector/deploy/webhook/helm/stackland-secrets-webhook/templates/deployment.yaml
helm-charts/stackland-secrets/charts/stackland-secrets-webhook/values.yaml
helm-charts/stackland-secrets/charts/stackland-secrets-webhook/templates/deployment.yaml
Root cause traced to .claude/hooks/safety-guardrails.py:
_DEFAULT_DANGEROUS_FILE_MARKERS includes the bare substring "secret", so the fast pre-check any(marker in path_lower for marker in _DEFAULT_DANGEROUS_FILE_MARKERS) is true for any path containing "secret"/"secrets" ANYWHERE (component name, directory name, chart name — not just the leaf filename).
- Once that pre-check trips,
DANGEROUS_FILE_PATTERNS regex r"secrets?\.(json|ya?ml|toml)" is evaluated against the full lowercased path (not just the basename), so .../stackland-secrets-webhook/values.yaml matches because the substring secrets-webhook/values.yaml — wait, actually more precisely .../stackland-secrets-webhook/... contains secrets immediately followed eventually by a yaml extension path; the regex is unanchored and scans the whole path string, so any directory literally named ...secrets... combined with a .yaml/.json/.toml file ANYWHERE later in the path can match, independent of directory/file semantics.
- This combination affects an entire class of legitimate Kubernetes/Helm assets: any secrets-management operator/webhook/controller chart (external-secrets, secrets-store-csi-driver, HashiCorp Vault integrations, custom secrets-injector components, etc.) that stores its config in
values.yaml/Chart.yaml under a directory containing "secret(s)" in the name.
This is a project (host-repo) .claude/settings.json + hook combo that mapify generated/manages (_map_managed.generated_by: mapify-cli, version 3.20.0), so it is a map-framework-shipped artifact, not a host-repo hand-written rule.
Expected
The dangerous-file heuristic should target actual credential/secret-value files (e.g. a literal secrets.yaml/secret.json file used to STORE secret material, or paths like **/secrets/*.yaml used as a secret-mount convention), not any path where a component/directory is merely named "secrets-" or "-secrets-*". Suggested improvches (not prescribing the fix, just observed signal):
- Anchor the regex to the basename only (e.g.
^secrets?\.(json|ya?ml|toml)$ against os.path.basename(path)), not the full path.
- Or require the "secret" token to be a whole path segment equal to
secret/secrets (e.g. /secrets/foo.yaml) rather than a substring of a longer component name like stackland-secrets-webhook.
- Consider allow-listing common non-secret-value file types even under secret-related directories:
values.yaml, Chart.yaml, deployment.yaml, template files under templates/.
Environment
- mapify_version: 3.20.0
- File:
.claude/hooks/safety-guardrails.py (function check_file_safety, lines ~126-149 in the affected checkout)
- Host repo: azalio/quantum, branch caldera-firestorm
Impact
Blocks all Actor edits to a real (in-scope, approved) MAP subtask whose target files are Helm chart values/templates for a secrets-injector webhook component — a false positive that halts an otherwise-correct implementation with no safe workaround other than expanding safe_path_prefixes in .map/config.yaml (host-repo config change, out of scope for the current subtask) or disabling the hook (not appropriate to do unilaterally as an Actor).
Summary
.claude/hooks/safety-guardrails.py(PreToolUse guardrail, mapify_version 3.20.0) blocksEdit/Writeon legitimate, non-credential files whenever any path segment matchessecrets?and the file has a.json/.yaml/.yml/.tomlextension — even when the "secret" match comes from a directory/component name (e.g.secrets-injector,stackland-secrets-webhook) rather than an actual credentials file.Observed
Working in
azalio/quantum(Stackland platform monorepo), branchcaldera-firestorm, on a MAP subtask (ST-001) whose entire job is to add askipTLSVerifyHelm value/env var to a component literally named "secrets injector" / "stackland-secrets-webhook" (a legitimate webhook that injects secrets into pods — the name itself, not a credential file).All four target
Editcalls were denied withFile is in a directory that is denied by your permission settings.:secrets-injector/deploy/webhook/helm/stackland-secrets-webhook/values.yamlsecrets-injector/deploy/webhook/helm/stackland-secrets-webhook/templates/deployment.yamlhelm-charts/stackland-secrets/charts/stackland-secrets-webhook/values.yamlhelm-charts/stackland-secrets/charts/stackland-secrets-webhook/templates/deployment.yamlRoot cause traced to
.claude/hooks/safety-guardrails.py:_DEFAULT_DANGEROUS_FILE_MARKERSincludes the bare substring"secret", so the fast pre-checkany(marker in path_lower for marker in _DEFAULT_DANGEROUS_FILE_MARKERS)is true for any path containing "secret"/"secrets" ANYWHERE (component name, directory name, chart name — not just the leaf filename).DANGEROUS_FILE_PATTERNSregexr"secrets?\.(json|ya?ml|toml)"is evaluated against the full lowercased path (not just the basename), so.../stackland-secrets-webhook/values.yamlmatches because the substringsecrets-webhook/values.yaml— wait, actually more precisely.../stackland-secrets-webhook/...containssecretsimmediately followed eventually by a yaml extension path; the regex is unanchored and scans the whole path string, so any directory literally named...secrets...combined with a.yaml/.json/.tomlfile ANYWHERE later in the path can match, independent of directory/file semantics.values.yaml/Chart.yamlunder a directory containing "secret(s)" in the name.This is a project (host-repo)
.claude/settings.json+ hook combo that mapify generated/manages (_map_managed.generated_by: mapify-cli, version 3.20.0), so it is a map-framework-shipped artifact, not a host-repo hand-written rule.Expected
The dangerous-file heuristic should target actual credential/secret-value files (e.g. a literal
secrets.yaml/secret.jsonfile used to STORE secret material, or paths like**/secrets/*.yamlused as a secret-mount convention), not any path where a component/directory is merely named "secrets-" or "-secrets-*". Suggested improvches (not prescribing the fix, just observed signal):^secrets?\.(json|ya?ml|toml)$againstos.path.basename(path)), not the full path.secret/secrets(e.g./secrets/foo.yaml) rather than a substring of a longer component name likestackland-secrets-webhook.values.yaml,Chart.yaml,deployment.yaml, template files undertemplates/.Environment
.claude/hooks/safety-guardrails.py(functioncheck_file_safety, lines ~126-149 in the affected checkout)Impact
Blocks all Actor edits to a real (in-scope, approved) MAP subtask whose target files are Helm chart values/templates for a secrets-injector webhook component — a false positive that halts an otherwise-correct implementation with no safe workaround other than expanding
safe_path_prefixesin.map/config.yaml(host-repo config change, out of scope for the current subtask) or disabling the hook (not appropriate to do unilaterally as an Actor).