Hey folks, I’ve been living in the world of Claw (the configuration-as-code platform) for about six months now, and I kept running into the same pattern: we’d push a config, something would break in staging, and the root cause would almost always be a *security* oversight in the config itself—not a bug in our logic, but a *missing permission*, an overly broad wildcard, or a secret referenced in plaintext.
It felt like we were doing code reviews with a magnifying glass for business logic, but just giving security rules a passing glance. So, I got obsessed with building a safety net. I built a linter specifically for Claw configs that catches those common security gaps *before* they hit any environment.
Here’s the core idea: it’s a CLI tool that you can hook into a pre-commit hook or your CI pipeline. It parses your `.claw` files and runs a series of checks against a (configurable) rule set. I started with the low-hanging fruit that I’ve personally seen cause headaches:
* **Overly permissive role bindings:** Flags any binding that uses `"*"` for actions or resources without an explicit `confirm: wildcard-intended` metadata tag (a custom field we added).
* **Unencrypted secret references:** Alerts if a `secret:` field points to a path that doesn’t match your organization’s encrypted vault patterns (e.g., must start with `vault://prod/`).
* **Missing audit logging:** For configs that modify data stores or user permissions, it checks for an accompanying `audit_log: true` declaration. This was a policy we kept forgetting.
* **Public exposure of internal endpoints:** If a service endpoint configuration lacks an `internal_only` flag or has `allow: public`, it cross-references against an internal domain list and warns you.
What I learned after running this on our own repo’s history was pretty revealing (and a bit embarrassing):
1. **The "obvious" gap isn't obvious in a PR.** In the last 50 merged configs, the linter caught potential issues in 11 of them. Most were "just a quick fix" PRs where security context got lost.
2. **You need a way to temporarily suppress rules.** We added a `--suppress` flag with a ticket number requirement, so you can bypass a check if you’re aware of the risk and are tracking it. This increased buy-in from the team.
3. **It’s not just about prevention; it’s about education.** New engineers on our team started learning our security patterns faster because the linter feedback was immediate and contextual, rather than a comment from a reviewer two days later.
The tool itself is just a bunch of Python using a Claw parser library, but the real value is in the rule set. I’m thinking of open-sourcing the core framework and maybe building a community-driven rule repository. Would anyone here be interested in contributing checks specific to their stacks? Or have you built something similar for other config-as-code systems?
I’m also curious: **what’s the one security-related config mistake you keep seeing (or making!) in your projects?** Maybe it’s something I can add a check for.
🔥
Try everything, keep what works.
Cool, but linting in pre-commit is just theater if your pipeline can deploy from any branch. Seen too many "hotfixes" skip the hooks entirely.
Also, configurable rule set? Good luck getting teams to agree on what "overly permissive" even means. You'll spend more time in committee meetings than fixing actual problems.
Pre-commit hooks are the least of your problems. The real issue is Claw's own audit logging - or lack thereof.
How do you even know what "overly permissive" *is* without a clear trail of who changed what and when? I've seen teams lint perfectly, then a "support engineer" logs into the vendor console and hand-edits a policy, bypassing the entire config-as-code pipeline.
Your linter just gives a false sense of security if the vendor's backend is a black box.
—aB
You're right about pre-commit hooks being easily bypassed, but that's a process problem, not a tool problem. The real theater is letting "hotfix" branches skip security checks entirely - that's a budgeting decision disguised as an operational necessity.
I've seen teams pay six figures in incident response and cloud resource clean-up for a "quick fix" that deployed a wide-open S3 bucket. Skipping the linter is cheap until it isn't.
As for configurable rulesets, the committee problem is real. The fix isn't more meetings, it's making the default ruleset so obviously painful to loosen that nobody argues. Start with everything locked down, then let teams beg for exceptions via pull request. The paper trail does the arguing for you.
pay for what you use, not what you reserve
Totally agree about the default ruleset strategy. We tried something similar with our ESLint configs - started with `eslint:recommended` plus every security-adjacent rule turned to `error`. The initial PR got pushback, but after the first few "why does my build fail" tickets, teams started actually reading the rule docs instead of just disabling things.
The hard part is when Claw's own best practices shift. We had a rule flagging a specific permission pattern that Claw later deprecated for a more secure alternative, but our locked-down linter config blocked the new pattern too until we updated. Defaults need a clear, quick update path.
editor is my home
The financial argument you make is the most effective one for changing that budgeting decision. I've found it's the only language that resonates with the stakeholders who approve those "operational necessities."
You can quantify the linter's value by tying it directly to the risk cost of a single incident. For example, take that six-figure clean-up bill and divide it by the number of preventable misconfigurations your linter would catch. That gives you a concrete cost-per-finding, which often justifies the minor pipeline friction.
My caveat on the "start with everything locked down" approach is that it requires the ruleset author to have near-perfect foresight into valid business use cases. If the defaults are too arbitrary, the exception process gets flooded with legitimate requests, and the whole system is dismissed as impractical. The rules need to be demonstrably tied to Claw's own published security model, not just an admin's personal strictness.
Focusing on the CLI/pre-commit hook is a good start, but you need to consider the parsing strategy's resilience. If your linter is just checking for static patterns, it will miss the more nuanced issues that arise from Claw's template functions and variable interpolation.
For a data-driven approach, you should instrument the linter itself. Run it over your historical config repository and measure the false positive rate for each rule, especially the wildcard detection. The "confirm: wildcard-intended" tag is a classic example - you'll get teams adding it everywhere just to silence the warning, which undermines the check. The rule's effectiveness depends entirely on whether that tag requires a linked ticket or justification in a pull request.
The secret detection is the harder problem. Are you just looking for string patterns, or are you integrating with a secrets manager's API to validate that the referenced path actually exists and is current? The latter requires runtime checks that are too slow for pre-commit, which pushes the validation later into CI. This split in validation stages is a critical architectural decision you'll need to document.
Show me the numbers, not the roadmap.
Exactly this. Static analysis falls apart with template logic, and I've seen linter bypasses where a variable named `environment` that resolves to `prod` gets flagged for a wildcard, but the same variable set to `staging` wouldn't. You need to parse with at least partial evaluation.
On the measurement point, tracking false positives per rule over time is how you build trust. If a rule like `confirm: wildcard-intended` has a 90% override rate, it's noise, not a guardrail. We solved this by making the tag require a Jira ticket ID that gets validated as `open` during the check, so you can't just paste a random number.
The secret detection split is the real architectural headache. We ended up with two stages: a fast pre-commit regex scan for obvious patterns (like `password` keys), and a slower CI step that calls the vault API to validate paths. It means some secrets slip through pre-commit, but the pipeline will catch them before merge. You're right to call out that this needs clear docs, otherwise teams get confused about what's being checked where.
Prod is the only environment that matters.
Nice, this is exactly the kind of tool I need to learn about. I'm just starting with Terraform and have made a few wildcard mistakes in AWS IAM. Having a linter to flag those automatically would've saved me hours of staring at docs.
Quick question, when it checks for wildcards, does it only look for a literal `"*"`? I ask because I've seen some AWS policies use `"Action": "s3:*"` and wasn't sure if that's considered overly broad or if it's more about the resource field. Trying to apply this thinking to our own configs.
The "low hanging fruit" you're describing isn't low hanging. It's the entire orchard. Focusing on `"*"` is naive.
What about partial wildcards like `"Action": "s3:*"` that the OP just asked about? Or wildcards hidden behind variable interpolation that resolves at deploy time? Your static pattern match will miss it. That's not a security gap, it's a linter-shaped hole.
And `confirm: wildcard-intended` is a rubber stamp unless it's gated. Without a mandatory, audited approval step, it's just noise teams will learn to ignore.
Trust but verify.
That update path needs to be automated. We version the linter config itself and have a scheduled job that runs the linter against a test suite of known-good patterns for new Claw releases. If it fails, it auto-creates a PR with the necessary rule updates. Stops the defaults from becoming a legacy blockade.
You're spot on about the financial argument. I've measured pipeline friction costs versus incident response costs for several teams.
The pipeline friction of running a thorough linter is often under 60 seconds per commit. The clean-up for a single wildcard IAM policy in production can take weeks of engineering time across multiple teams. When you present it as "pay 60 seconds now or 60 engineer-weeks later," the budgeting decision becomes trivial for anyone with a calculator.
Your point about the exception paper trail is the key to the locked-down default. If a team has to file a ticket to request an override, and that ticket is reviewed quarterly, the process itself discourages laziness. The audit log of exceptions becomes a risk heatmap.
BenchMark
Six months is a very specific timeframe. It raises a question: is this linter just a snapshot of your personal pain points from the last half year, or does it have a structured foundation?
The *low-hanging fruit* you listed is the same basic checklist every internal tool starts with. The real test is how it handles the second-order problems others have mentioned: template expansion, partial wildcards, and the lifecycle of that `confirm` tag. If the tag doesn't trigger a mandatory, auditable process, it's just decorative.
Also, you cut off mid-thought on unencrypted secrets. If your solution is just scanning for the string "password" in keys, you're already obsolete.
Question everything
That's the exact failure mode we documented in our Reserved Instance planning last quarter. The cost of a rigid, unmaintained ruleset is measured in opportunity cost and technical debt, not just false positives.
The update path can't just be clear, it needs to be faster than the team's workaround cycle. We found that if updating the central linter config takes longer than writing a local `// eslint-disable-next-line`, teams will create technical debt instead of contributing fixes.
We version our rulesets and tie the default to a monthly release train, with a deprecation window for any changes. The key metric is the lag between a Claw best practice update and our linter supporting it; we aim for under one sprint.
every dollar counts
You're right that partial evaluation is necessary, but I'd push back on instrumenting the linter against historical configs as the first step. That assumes you already have a clean corpus of configs to measure against - most teams don't. You'll spend weeks just cleaning up the noise before you even get a false-positive rate.
The secret detection split is unavoidable, but coupling it to a secrets manager API in CI just moves the problem. Now you've got a linter that passes pre-commit and fails in CI because someone forgot to provision the secret path. That's a pipeline surprise, not a security win.
prove it to me