chore: add gitignore, buddy security profile and shared secret scanner - #682
Open
allanice001 wants to merge 3 commits into
Open
chore: add gitignore, buddy security profile and shared secret scanner#682allanice001 wants to merge 3 commits into
allanice001 wants to merge 3 commits into
Conversation
The repo had no .gitignore at all. Given this module mints IAM secret access keys and takes a GitHub App private key, an OAuth client secret and the autoglue org secret as inputs, an accidentally committed *.tfstate, *.tfplan or *.tfvars would leak live credentials. Ignore those, plus Terraform working dirs, crash logs and CLI config. Also add the dragon-dev-buddy profile that security tooling reads: exposure (public, via the Route53 zones and the *.apps wildcard), data sensitivity (credentials), trust boundaries and known risk areas. config.json is tracked so the team shares one profile; reports/ is ignored because audit output quotes real findings. scan-config.sh + scan-config.py guard that decision: a pre-commit hook blocks the commit if a credential-shaped value ever lands in the profile. Install locally with: ln -sf ../../.dragon-buddy/scan-config.sh .git/hooks/pre-commit
.git/hooks/ is not shared by git, so the pre-commit guard added in the previous commit only protected whoever installed it by hand. Move the hook into a tracked .githooks/ directory, enabled per clone with: git config core.hooksPath .githooks core.hooksPath is local config and cannot be committed, so an unenabled hook is still possible. Add a pull_request job running the same scanner as the backstop that covers everyone regardless. Document both in .dragon-buddy/README.md rather than README.md, which is generated wholesale by terraform-docs from docs/.header.md. This supersedes the ln -sf install line in the previous commit message.
The profile was hand-built because config.example.json was not reachable
at setup time. The pack's actual schema turned up afterwards at
DragonSecurity/dragon-dev-buddy, and the guessed structure diverged:
- project.stack was a string, the schema wants an array. Any skill
iterating it would have gotten characters.
- version, project.repo, practice.lint_command, practice.build_command,
output.format and voice.avoid were absent entirely.
- the buddy block used name/mcp_server instead of the schema's
server/advise_before_work/observe_after_every_skill/skill_prefix.
- engagement was {} rather than the empty-array shape the skills that
gate on authorized_scope actually read.
Key parity against config.example.json is now exact in both directions.
output.reports_dir stays .dragon-buddy/reports rather than the schema's
docs/security default: docs/ is tracked here and README.md is generated
from docs/.header.md, so audit reports would end up committed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three things, in dependency order.
1. A
.gitignore, which this repo did not have at all.This module mints IAM secret access keys and takes a GitHub App private key, an OAuth client secret and the autoglue org secret as inputs. Without a
.gitignore, a stray*.tfstate,*.tfplanor*.tfvarscommits live credentials. Now covered, along with Terraform working directories, crash logs and CLI config.Verified no currently-tracked file becomes ignored —
.terraform-docs.ymlwas the near-miss, and**/.terraform/*does not match it.2. A committed dragon-dev-buddy profile at
.dragon-buddy/config.json.Records exposure (
public— the module publishes Route53 zones and a*.appswildcard pointing at cluster ingress), data sensitivity (credentials), the four real trust boundaries, and known risk areas. Security tooling reads this instead of re-deriving it each run. Tracked so the team shares one profile;reports/is ignored because audit output quotes real findings.3. A secret scanner guarding that decision.
A committed profile is readable by everyone with repo access, so a credential landing in it is a leak.
.dragon-buddy/scan-config.pydetects AWS access key ids, GitHub tokens and PATs, PEM private keys, Slack tokens, JWTs, Vault tokens, and opaque high-entropy values under secret-named keys..dragon-buddy/scan-config.shwraps it for both staged (hook) and file modes.It is enforced twice, because either alone has a hole:
.githooks/pre-commit, tracked, enabled per clone withgit config core.hooksPath .githooks. Fast local feedback, butcore.hooksPathis local config and cannot be committed, so it can go unenabled..github/workflows/scan-buddy-profile.yml, running the same scanner on every PR. Covers everyone regardless.Testing
Scanner unit-tested against six inputs: clean config passes; AWS key, GitHub token, PEM-in-prose, opaque-value-under-
api_key, and empty-document all reject. Then end-to-end through the real hook viacore.hooksPath— a commit carrying a seededghp_token was refused and no commit object was created. CI step dry-run under bash; workflow YAML parses.Worth noting the first version of the scanner was broken in a way that passed everything: a heredoc occupied python's stdin, so it read an empty document and exited clean. That is why the empty-document case is now an explicit failure rather than a silent success.
Notes for review
README.mdis generated wholesale by terraform-docs fromdocs/.header.md, so the setup docs live in.dragon-buddy/README.mdinstead.git config core.hooksPath .githooksonce.