chore(defaultconfig): curate the shipped default + add extension capability - #365
Conversation
f78a0bc to
1af07ef
Compare
1af07ef to
2381aaf
Compare
358caca to
5ed924a
Compare
5ed924a to
14a89c1
Compare
3ae3ef9 to
b129111
Compare
|
All Claude review controls completed on the latest revision. |
b129111 to
0fd9b54
Compare
|
@Joseph94m ready for review |
0fd9b54 to
be35c6e
Compare
|
@thomasboni I don't mean that the feature should work now but does the code make it easy or difficult on us to do that change? Because I can see the feature coming. Second question: If its not just the default config / automatic ones that are taken as bases, then I am not sure if the name should be Third question: This is just to verify that my understanding is correct.
Alternatively when running Which seems to work because i only overlayed the
Fourth Question:
But isn't the |
|
The Makefile `embed` target prepended a `# DO NOT EDIT` header before catting defaultConfig/.plumber.yaml, but no shipping build path uses it: CI, the release workflow, and the Dockerfile all `cp` the source verbatim before `go build`. That left embed.go carrying `buildHeader` + strip logic (and a `GetRaw` helper) solely to undo a header production builds never produced. Align `make embed` to a plain `cp` so dev and CI generate byte-identical output, then remove the dead header handling: `Get()` is just `return Config`, delete `GetRaw()`, drop the unused `bytes` import, and fix the stale doc comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…it` from it Rework the zero-config baseline (defaultConfig/.plumber.yaml) so a project's FIRST run catches real supply-chain / hardening issues without a flood of false positives, then have `plumber config init` derive its wizard defaults from that same embedded config — one source of truth, no duplication, no drift. Curated default (draws on the FP-calibrated radar study config, minus study/radar-specific bits): - githubActionMustComeFromAuthorizedSources: curated well-known-publisher allowlist (~155 orgs + lowercase aliases) + minimumStars: 20000, replacing the Plumber-self allowlist (the #1 false-positive source on real repos). - containerImageMustComeFromAuthorizedSources (GitLab): drop radar-specific trustedUrls; enrich with generic official / vendor registries. - pipelineMustNotIncludeHardcodedJobs (GitLab): disabled by default. - securityJobsMustNotBeWeakened (GitLab): enable rules/when, keep allow_failure off (stock GitLab templates ship allow_failure: true). - branchMustBeProtected (GitHub): codeOwnerApprovalRequired: false (aligns with GitLab; many first-run repos have no CODEOWNERS). - Remove pipelineMustNotLeakSecretsInConfig (both providers): the control was removed from Plumber and warns under --fail-warnings. - containerImagesMustBePinnedByDigest stays true on both providers (deliberate). `config init` consistency + de-duplication: - Add a wizard question for authorized action sources — include Plumber's curated trusted orgs (recommended) vs start from an empty allowlist. - Source ALL wizard defaults (trusted URLs/actions, minimumStars, forbidden tags/versions, security-job patterns, cache-poisoning inventories, branch patterns, ...) from the embedded default via embeddedDefault(), removing the hand-maintained Go copies (~275 lines) and making init↔default drift impossible by construction. - Align GitLab securityJobs rules/when and the GitHub branch code-owner default in the wizard to the curated default. - Lock `config generate` == embedded default; cover wizard curated/scratch paths and the sourced-from-default invariant with tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n config Commit dd75222 ("clean plumber conf") intentionally dropped the gitlab: section from the repo-root .plumber.yaml — Plumber runs no GitLab CI, so its own self-scan config is GitHub-only. Two tests still assumed that file declared a gitlab section and have been red on main since: - TestSelfScanConfigControlsMatchDefault fataled on the missing gitlab section. Now controlKeys() reports section presence and the test skips a provider the self-scan config doesn't declare (a malformed section still fails hard). The drift guard remains meaningful for every provider the self-scan DOES declare. - TestFilterFindingsByEnabledControls_ProviderApplicability drove the GitLab gate off pc.ControlsFor("gitlab"), which is now empty, so a cross-provider control (ISSUE-401) was reported as over-dropped. It now builds a minimal GitLab ControlsConfig with pipelineMustNotIncludeHardcodedJobs enabled to probe the gate directly, independent of the self-scan file's provider coverage. No production code changes; both tests again exercise their real invariant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes #375. Let a .plumber.yaml be a sparse overlay on Plumber's shipped baseline instead of forcing users to copy and maintain the whole ~1000-line file. - `extends: plumber:default` opts a file into overlay mode: it is deep-merged onto the embedded baseline, so users write only what they change and new controls Plumber ships are inherited automatically. Files without `extends` keep the legacy full-replace behavior byte-for-byte (asserted by test). A section left empty in an overlay inherits the base rather than wiping it. - `includePlumberDefaults` toggle on the authorized-source controls: true (default) unions Plumber's curated trusted list with the user's additions; false uses only the user's list. - New commands: `config resolve` (materialize the full effective config), `config generate --overlay` (minimal starter), `config view --explain` (per-control base-vs-overlay provenance), `config slim` (collapse a full config into a minimal overlay). Resolution runs inside LoadPlumberConfigFromBytes: overlay bytes are merged onto the embedded base, then allowlist fields are materialized so the enforced trust set and the audit report's config hash reflect what actually ran. `config slim` normalizes v1 and legacy sources and preserves disabled-by- omission controls, narrowed trust lists, and strict scalar trust fields, so slim -> resolve never widens trust or re-enables a control. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The capacity hint make([]string, 0, len(cfg.NamePatterns)+1) trips CodeQL's go/allocation-size-overflow. Drop the +1 (append grows the one extra default- branch entry on its own); behavior is unchanged. Pre-existing on main, fixed here so the PR's CodeQL gate is green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
be35c6e to
b02c8be
Compare
…efaults false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efaults false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efaults false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efaults false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efaults to false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efaults to false Mirror TestLoadPlumberConfigFromBytes_OverlayNarrowsTrustedActions for the GitLab containerImageMustComeFromAuthorizedSources branch of materializeAuthorizedSources. Guards the security-critical direction: a config trusting only its own registries must not get the curated base trustedUrls unioned back in on resolve. Addresses the remaining review finding on #365. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## [0.4.27](v0.4.26...v0.4.27) (2026-08-03) ### 🐛 Bug Fixes * **lint:** report all issues instead of golangci-lint's truncated default ([cb5739a](cb5739a)) ### ♻️ Refactoring * remove 50 dead functions unreachable from main ([a28393c](a28393c)) ### ✅ Tests * **config:** cover GitLab trustedUrls narrowing with includePlumberDefaults to false ([46f09ed](46f09ed)), closes [#365](#365) ### 👷 CI/CD * **lint:** gate on whole-program dead code detection ([0aac54c](0aac54c)) * **release:** pin v0.4.26 refs [skip ci] ([e461736](e461736))


What this PR does
Two user-facing improvements to how Plumber is configured.
1. A safer, cleaner default
The shipped default
.plumber.yamlis now curated so a project's first scan catches real supply-chain and hardening problems without a flood of false positives. The same default is used everywhere: a zero-config run,plumber config generate, and theplumber config initwizard all produce a consistent posture, so there is no drift between them.2. Customize without owning the whole file
Until now, changing one setting meant copying the entire configuration and maintaining all of it yourself. You can now keep a small file instead.
Add
extends: plumber:defaultat the top of your.plumber.yamland list only what you want to change. Everything else is inherited from Plumber's baseline, and new checks that Plumber ships are picked up automatically. A file withoutextendskeeps behaving exactly as before, so existing configs are unaffected.For trusted-source lists (GitHub Actions and container registries),
includePlumberDefaults: true(the default) keeps Plumber's curated list and adds your entries on top. Set it tofalseto trust only your own entries.Example:
New config commands
plumber config generate --overlaywrites a short starter overlay instead of the full file.plumber config resolveprints the complete effective configuration, useful to review it or commit a fully explicit version.plumber config view --explainshows, per control, whether a value comes from the baseline or from your file.plumber config slimturns an existing full configuration into a minimal overlay.Closes #375.