ci: repo hardening (2/3) — CI workflows (shellcheck, prose-lint, CodeQL, gitleaks, Scorecard)#11
Open
ArangoGutierrez wants to merge 17 commits into
Open
ci: repo hardening (2/3) — CI workflows (shellcheck, prose-lint, CodeQL, gitleaks, Scorecard)#11ArangoGutierrez wants to merge 17 commits into
ArangoGutierrez wants to merge 17 commits into
Conversation
Explains the SHA-pinning rule, least-privilege permissions discipline, harden-runner audit-mode defaults, where each workflow surfaces its results, and the fork-PR permission caveat. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The pattern `_*|__*` is redundant because `_*` already matches any string starting with an underscore, so `__*` is unreachable (SC2221, SC2222). No behavior change — scripts continue to skip any skill directory whose name starts with `_`. Surfaced by the new shellcheck workflow added in the same PR. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Runs shellcheck at severity=warning on push to main and on PRs that touch .sh/.bash files or skills/. Pinned, least-privileged, and harden-runner-wrapped per the workflow conventions in .github/workflows/README.md. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Disables line-length (prose), inline-HTML (badges), and first-line-must-be-heading (CHANGELOG) rules. Everything else stays at the markdownlint defaults. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Suppresses link-checker false positives from localhost, example.* domains, and the issue-template new-issue URLs (which 404 until the maintainer enables them in repo settings). Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Three parallel jobs triggered on PR and push-to-main for changes under *.md / *.yml / *.yaml. Lychee runs with fail=false (annotations only) for the first month to establish a clean baseline; a follow-up flips it to blocking. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
- Disable MD034 (bare URLs): prose and research files legitimately contain bare URLs; mechanical <...> wrapping is not worth the churn. - Exclude docs/music/ and data/ from markdownlint globs: these hold content-as-data (artist contact lists, close-out records) that share the fixture pattern — data, not docs. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
…de fences Addresses markdownlint findings (MD022, MD032, MD040, MD049) surfaced by the new lint-prose workflow: - MD022/MD032: add required blank lines before/after headings and lists across skills/, docs/, evals/, research/, and top-level docs. - MD040: tag untagged code fences as `text` (README, evals/README, docs/operations/closing — ASCII-art tree / form templates). - MD049: normalize emphasis markers to asterisks in AGENTS.md. Auto-fixed by `markdownlint-cli2 --fix`; code fences and emphasis were adjusted manually. Verified locally via `act` against the pinned markdownlint-cli2-action. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Matrix covers the two languages skill code is most likely to arrive in. Today both legs find zero source files and exit quickly. When the first .py or .ts file lands, analysis activates automatically without a CI change. Scheduled weekly on Monday 06:00 UTC. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Extends the upstream gitleaks default rule set (cloud tokens, generic-api-key, slack-webhook, etc.) with generic PII patterns: email addresses, US and MX phone numbers, and credit-card-shaped numerics. An allowlist suppresses obvious false positives in example files, docs, issue templates, and colocated Python unit tests (maya/**/test_*.py) that hold synthetic PII as test data. Bar-specific PII patterns can be supplied via the GITLEAKS_PRIVATE_CONFIG repository secret; see the gitleaks workflow for the overlay mechanism. Note on regex syntax: gitleaks uses Go's RE2-based stdlib engine, which does not support lookarounds or backreferences — rules use word boundaries and explicit separators instead. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Runs gitleaks on every PR and push-to-main using the .gitleaks.toml rule set. If the GITLEAKS_PRIVATE_CONFIG repository secret is set, its contents are appended to the config at CI time (runner-local, never committed) so bar-specific PII rules can be maintained outside the public repo. GITLEAKS_LICENSE is read if present (required only under GitHub Organization accounts). Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Expands the optional-secrets section with the expected TOML shape of the private overlay, so the maintainer can add bar-specific PII rules without touching the public repo. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Runs weekly on Tuesday 06:00 UTC plus push-to-main and branch_protection_rule changes. Publishes the public SARIF-backed report to api.securityscorecards.dev and uploads findings to the GitHub Security tab. id-token: write is the minimum required to sign results for public attestation. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The earlier resolution used `gh api .../git/ref/tags/<tag> --jq '.object.sha'`, which for annotated tags returns the tag-object SHA rather than the underlying commit SHA. github/codeql-action and ossf/scorecard-action both ship annotated tags, so both were mis-pinned. Replaces: - github/codeql-action@51313611... (tag object) → afb54ba3... (commit), across 3 uses in codeql.yml and 1 use in scorecard.yml - ossf/scorecard-action@ff5dd892... (tag object) → 62b2cac7... (commit) in scorecard.yml Resolved via `gh api repos/<owner>/<repo>/commits/<tag> --jq '.sha'`, which always returns the commit SHA. The other 7 pinned actions use lightweight tags and were unaffected. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The previous patterns `(^|/)test_[^/]+\.py$` and `_test\.py$` allowlisted ANY Python test-named file anywhere in the repo, meaning a real secret committed under a file named test_foo.py at the repo root or in an unknown path would be silently suppressed. Restricts the allowlist to recognized source subtrees only — maya/, skills/, evals/, tests/ — so a misnamed file in a new subtree is still scanned by default. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Without these additions, a PR that only modifies a linter config (.lycheeignore, .markdownlint.yaml, .yamllint.yaml) or the workflow file itself would not re-run the corresponding linter. Adds the config paths and each workflow's own path to its trigger list. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The previous implementation left .gitleaks-private.toml in the runner workspace after the merge step. Any subsequent artifact upload — in this workflow or a later one — could have leaked the overlay contents. Writes the overlay to mktemp (which GitHub-hosted runners place under $RUNNER_TEMP, auto-wiped on job teardown) and adds a trap to clean up on any exit path, including early failures. The public .gitleaks.toml still gets the appended rules so gitleaks can read a single merged config. Refs: cvander#7 Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
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
Second of three PRs for issue #7. Adds five CI workflows plus their supporting config:
.github/workflows/shellcheck.yml— shellcheck on PR and push-to-main.github/workflows/lint-prose.yml— yamllint + markdownlint + lychee (annotations only for the first month).github/workflows/codeql.yml— Python + JS/TS, pre-wired for the first skill PR.github/workflows/gitleaks.yml— generic PII + upstream defaults + optional private overlay.github/workflows/scorecard.yml— OpenSSF Scorecard, weekly.github/workflows/README.md— pinning / permissions / harden-runner conventions.gitleaks.toml,.markdownlint.yaml,.lycheeignore,.yamllint.yamldocs/MAINTAINER-SETUP.md— expanded withGITLEAKS_PRIVATE_CONFIGformatConventions applied
uses:pinned to a 40-char commit SHA with trailing version commentpermissions: {}with minimum re-grant per jobstep-security/harden-runner@… egress-policy: auditis the first step of every jobpull_request_target— fork-PR safeIn-PR cleanup (not scope creep)
Adding linters to a repo with existing content requires the existing content to lint clean from day one, otherwise the first run is red and the workflow is effectively off. Three follow-on fixes are bundled here:
fix(shell): remove dead pattern __* in case statements— SC2221/SC2222 surfaced by shellcheck;_*already subsumes__*, no behavior change.fix(docs): add blank lines around headings/lists, language tags to code fences— MD022/MD032/MD040/MD049 across existing markdown. Auto-fixed bymarkdownlint-cli2 --fixwhere possible; fences and emphasis adjusted manually.ci: tune markdownlint (disable MD034, exclude data/music dirs)— MD034 (bare URLs) is noisy on prose docs;docs/music/anddata/hold content-as-data, same category as fixtures.Local verification (no speculative CI)
Per the repo's "no speculative CI" rule, every workflow was exercised locally before push:
act -W shellcheck.ymlwith plantedcd /tmp(SC2164)act -W lint-prose.yml -j markdownlintwith planted###Bad heading(MD018)act -W lint-prose.ymlon clean treegitleaks detect --config .gitleaks.tomlwith plantedAKIAABCDEFGHIJKLMNOP¹aws-access-tokenfired on the planted key, clean tree otherwisemaya/,skills/*/main.py,evals/,tests/Plus the static gates:
actionlintclean across all 5 workflows,yamllint --strictclean,shellcheck -S warningclean,git diff --checkclean, all 17 commits GPG-signed.¹ The canonical
AKIAIOSFODNN7EXAMPLEis pre-allowlisted by upstream gitleaks defaults, so a non-canonical 20-character fake AWS key was used to exercise the rule.Known limitations (deliberate)
fail: false— broken links are reported but do not gate merges. Intended for the first month while the link set stabilizes; a follow-up will flip it to blocking.auditmode on every job. After the egress baseline is known (~1 week of runs), a follow-up will flip it toblock.workflow_dispatchon any workflow today — can be added in a follow-up if manual re-runs are needed between crons.credit-card-numberrule is broad (any 13–19 digit run). Upstream defaults catch real card-issuer tokens; this generic rule may produce some noise during audit phase.Checklist
AGENTS.md— this doesn't violate any hard stopsRefs: #7