Skip to content

ci: add security-scan + semgrep + dependabot#228

Merged
Cre-eD merged 12 commits intomainfrom
ci/security-scans
May 7, 2026
Merged

ci: add security-scan + semgrep + dependabot#228
Cre-eD merged 12 commits intomainfrom
ci/security-scans

Conversation

@Cre-eD
Copy link
Copy Markdown
Contributor

@Cre-eD Cre-eD commented May 7, 2026

Summary

  • Adds 4 wrapper workflows that delegate to simple-container-com/actions:
    • security-scan — TruffleHog + Syft + Trivy + Grype, sticky PR comment, status gate
    • semgrep — SC custom ruleset + optional consumer rules / registry packs, sticky PR comment, status gate
  • Adds .github/dependabot.yml for weekly bumps (github-actions + gomod where applicable, minor+patch grouped)

Trust posture

Scan jobs run on pull_request (not _target), read-only token, no secrets — safe for fork PRs. Comment posting lives in a separate workflow_run-triggered workflow that never reads PR code.

Test plan

  • First scan + comment runs end-to-end
  • Sticky PR comment appears with status table
  • No false positives on the existing codebase

Cre-eD added 2 commits May 7, 2026 16:15
Wires this repo to the org-wide reusable workflows in simple-container-com/actions:
- security-scan: TruffleHog (secrets) + Syft/CycloneDX SBOM + Trivy + Grype, sticky PR comment, status gate
- semgrep: SC custom ruleset + optional consumer rules / registry packs, sticky PR comment, status gate

Both follow the GitHub Security Lab 'preventing pwn requests' split: scan jobs run in pull_request context (read-only token, no secrets, fork-PR safe); comment posting lives in a workflow_run-triggered job that never reads PR code.

Adds .github/dependabot.yml with weekly bumps for both github-actions and gomod ecosystems, with minor+patch grouped to reduce PR noise.
@Cre-eD Cre-eD force-pushed the ci/security-scans branch from 72da963 to ed43825 Compare May 7, 2026 12:27
@Cre-eD Cre-eD self-assigned this May 7, 2026
@Cre-eD Cre-eD force-pushed the ci/security-scans branch from ed43825 to 5d4d273 Compare May 7, 2026 12:40
Cre-eD added 2 commits May 7, 2026 16:54
Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
…w path-excludes

Brings the security-scan workflow to 0 TruffleHog findings while preserving detection coverage. Approach (per Codex review of PR-A's design tradeoffs and the public-actions-repo concern):

1. SOURCE-LEVEL REPLACEMENTS (preferred — no exclusion needed)
   - MongoDB / Postgres URIs in docs/.md and pkg/**/*_test.go: 'user:pass@host' -> '<USER>:<PASS>@<host>'. Angle brackets break the alphanumeric regex of TruffleHog's URI detectors. ~25 lines across docs and Go tests.
   - Gitlab CI placeholder text in docs/product-manager/container-security/acceptance-criteria.md: 'gitlab.com/myorg/myrepo' / 'CI_PROJECT_PATH=myorg/myrepo' replaced with '<gitlab-host>/<org>/<repo>' style; defuses the GitLab project-path detector.
   - Mailgun + Cloudflare fake tokens in docs/.../secrets.yaml: replaced with '<your-mailgun-api-key>' and '<your-cloudflare-api-token>' literals.

2. INLINE TRUFFLEHOG IGNORE (when format-locked but file accepts comments)
   - pkg/clouds/docker/types_test.go: nested base64 of fake user:password test fixture. TruffleHog scans decoded base64 (per Codex), so no source replacement defeats it without breaking the test. Added '// trufflehog:ignore' Go comment on the affected line with justification.

3. NOSEMGREP suppressions (org-owned bootstrap scripts; same posture as go-aws-lambda-sdk's welder.sh)
   - .github/workflows/branch-preview.yaml lines 52, 73: 'curl ... | bash' for dist.simple-container.com/sc.sh and welder.simple-container.com/welder.sh. Both are org-owned services. Justifications inline; checksum-pinned welder release tracked as a follow-up.

4. NARROW PATH-EXCLUDES via wrapper input (last resort, file-specific)
   - docs/docs/examples/.*/secrets\\.yaml — example SC secrets.yaml files containing placeholder GCP service-account JSON; the GCP detector's regex matches even '<service-account>@<project>.iam.gserviceaccount.com' placeholders.
   - docs/docs/examples/secrets/.*/README\\.md — corresponding example READMEs.
   - docs/docs/guides/parent-gcp-gke-autopilot\\.md — single guide file.
   - pkg/api/secrets/testdata/repo/ + pkg/provisioner/testdata/ — raw OpenSSH private-key fixtures (no comment syntax in the file format).

   These are the only public excludes we accept. The actions repo's PR #2 README explicitly frames such excludes as last-resort + file-specific, given that exclusion patterns in public repos become attacker evasion hints.

5. WIRING
   - Wrapper now references simple-container-com/actions/.github/workflows/security-scan.yml@feat/secret-scan-extra-excludes for testing. Will bump to @main once that PR merges.

Local scan with the new wrapper input + content: 0 findings (down from 39 on first run, with FormBucket already excluded by the actions-repo default).

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
@blacksmith-sh

This comment has been minimized.

Cre-eD added 2 commits May 7, 2026 21:22
…ection

WHAT changed
============

* `pkg/clouds/pulumi/mongodb/util_test.go` — replace mongo URI placeholder
  hostnames with `example.com` style. The previous round's `<test-shard>`
  used angle brackets, which are not valid URI characters; `url.Parse`
  silently returned the raw input and the test broke. example.com
  hostnames parse normally and don't trip TruffleHog's MongoDB detector.

* `welder.yaml` — `docker-login` task no longer bootstraps `sc` via
  `bash <(curl … sc.sh)`. The CI workflow now installs `sc` upstream
  via the `install-sc` composite, so welder can use the binary already
  on PATH. Removes a curl-pipe-to-shell finding inside CI-executed code
  (welder.yaml is invoked by `welder run` on the runner, so it IS in
  scope for our shell rules).

* `.github/workflows/*.yml{,aml}` — workflow hardening:

  - **Composites instead of curl-pipe** for tool installs and Telegram
    notifications: `simple-container-com/actions/install-sc@main`,
    `install-welder@main`, `notify-telegram@main`. Replaces
    `curl … | bash`, `bash <(curl …)`, and `yanzay/notify-telegram@v0.1.0`
    (third-party, tag-pinned) at all consumer sites.

  - **Script-injection mitigation** for attacker-controlled values.
    Heredocs that wrote `${{ github.event.head_commit.message }}` into
    `/tmp/commit_message.txt` now route the value through `env:` and
    `printf` to the file. Same pattern for `${{ github.ref_name }}`
    in docker-buildx tag construction and in echoes.

  - **`actions/checkout` pinned by SHA** to `v6.0.2`
    (`de0fac2e4500dabe0009e67214ff5f5447ce83dd`). Replaces the floating
    `@v4` tag, which would also have started warning about Node.js 20
    deprecation in June 2026.

* `.semgrepignore` — `sc.sh` (the published end-user installer; runs on
  user machines, different threat model from CI).

* `.github/workflows/security-scan.yml` — drop the temporary "@feat"
  branch comment now that `simple-container-com/actions` PR #2 merged.

* `.github/workflows/branch-preview.yaml` — preview-build step summary
  no longer hands users `curl … | bash`; instead it shows the
  `install-sc` action invocation pinned to the preview version.

WHY
===

PR #228 added the security-scan + Semgrep + Dependabot workflows. The
first run on `ci/security-scans` flagged 26 ERROR-severity Semgrep
findings (16 curl-pipe-to-shell, 10 script-injection) and 15 TruffleHog
findings (cross-ref bug — `actions@main` pre-merge — now resolved).
This commit clears all of them at the source rather than via
suppressions. Side effects: removes one third-party action with an
unpinned tag (`yanzay`), prevents the Telegram bot token from leaking
in CI logs (handled inside the new composite via `::add-mask::`), and
gets ahead of the Node.js 20 deprecation.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
Re-run TruffleHog over PR #228 was flagging the test's `want:` literal
because the rendered post-injection URI matched the MongoDB detector's
`<scheme>://<user>:<password>@<host>` shape — even with `example.com`
hosts, the connection-string structure itself triggers the detector.

Refactor the test to:
  1. Call AppendUserPasswordAndDBToMongoUri.
  2. Parse the result with `net/url`.
  3. Assert: scheme + host + raw query unchanged from input; user info
     exactly matches the supplied user/password; path becomes
     `/<dbName>`.

This covers the same behavior as the prior full-string equality check
(the function is itself just `url.Parse` + assignment + `String()`),
without any `mongodb://user:pass@host` literal in source.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
smecsia
smecsia previously approved these changes May 7, 2026
Replace the file-level `.semgrepignore` exclusion with a single
`# nosemgrep: shell-curl-pipe-to-shell` comment above the one
problematic line in `sc.sh` (the upstream pulumi installer bootstrap).

Why: blanket-ignoring the whole file means any future curl-pipe added
to `sc.sh` for any other reason would also slip through. With a
per-line ignore, only the specific pulumi-installer line is exempt
and everything else in `sc.sh` stays in-scope for the shell rules.

`.semgrepignore` is now empty and removed.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
smecsia
smecsia previously approved these changes May 7, 2026
…text/suffix

Wire the api workflows to the new notify-telegram inputs (clickable title
inline, no separate URL line, no Telegram preview card). Per workflow:

* branch.yaml (pull_request) — link-url = PR html_url; link-text =
  `PR #N: <title>`. Falls back to run URL + workflow name when somehow
  triggered without a PR.

* branch-preview.yaml (workflow_dispatch) — link-url = run URL;
  link-text = `v<preview-version>`.

* push.yaml (push to main) — link-url = head commit URL with run URL
  fallback; link-text = `v<release-version>`.

* build-staging.yml (push to main) — link-url = head commit URL with
  run URL fallback; link-text = workflow name (job-level VERSION env
  isn't visible in the finalize job, and adding an inter-job output
  just for this is more change than warranted).

Branch ref pinned to `@feat/notify-telegram-append-run-url` for
testing the actions PR end-to-end. Will bump to `@main` after that PR
merges.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
Cre-eD added 3 commits May 7, 2026 23:31
Run 25516915000 startup-failed (0 jobs) because the link-text value:

  ${{ ... format('PR #{0}: {1}', ...) || ... }}

was an unquoted YAML scalar. The `: ` inside the format() string
literal got interpreted by the YAML parser as a key/value boundary
inside the scalar, which then made the embedded `'` look like an
unterminated quote to the GHA expression lexer (actionlint reported
"unexpected EOF while lexing end of string literal").

Wrap the whole expression in double quotes so YAML treats it as one
opaque scalar and forwards it to the expression engine intact.
Single quotes inside (the format() literal) survive YAML double-quoted
parsing without escaping.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
…ge ref

Dev feedback: prior text was too vague — "✅ success (228/merge) -
by Cre-eD" doesn't tell you what just happened (CI passed? deploy?
release?) and "228/merge" is GitHub's auto-merge ref, not the actual
branch you'd checkout.

Per workflow:

  branch.yaml:        '✅ CI passed: <PR title> on <head_ref> by <author>'
  branch-preview.yaml: '✅ Preview published: v<version> on <head_ref> by <author>'
  push.yaml:          '🚀 Released: v<version> by <author>'
  build-staging.yml:  '🏗️ Staging built: <workflow> on <head_ref> by <author>'

(failure variants use ❗ + "<verb> failed:")

Branch source bumped from `steps.extract_git_ref.outputs.branch`
(which is `$GITHUB_REF_NAME` = `228/merge` on PR runs) to
`github.head_ref || github.ref_name` — head_ref is the source branch
on PR events; ref_name is the target on push events.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
simple-container-com/actions PR #5 merged into main, so the inline-link
inputs (link-url / link-text / suffix), HTML escaping, and `grep -z`
multiline-rejection are all on @main. Drop the temporary @feat ref
across all four api workflows.

Signed-off-by: Dmitrii Creed <creeed22@gmail.com>
@Cre-eD Cre-eD requested a review from smecsia May 7, 2026 20:32
@Cre-eD Cre-eD merged commit b67cc6e into main May 7, 2026
16 checks passed
@Cre-eD Cre-eD deleted the ci/security-scans branch May 7, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants