ci(sync): update GitHub Actions - #113
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
Remove or define the ineffective trivy-licenses skip token.
Pull request overview
This PR syncs GitHub Actions and related configuration to add Trivy license scanning.
Changes:
- Adds configurable license scanning to the Trivy action.
- Invokes license scanning for filesystem scans.
- Updates the pre-commit skip list.
File summaries
| File | Summary |
|---|---|
.github/workflows/pre-commit.yaml |
References an undefined trivy-licenses hook, so the intended skip is ineffective. |
.github/actions/trivy/action.yaml |
Adds and runs configurable license scanning. |
Review details
Suppressed comments (1)
.github/workflows/pre-commit.yaml:71
pre_commit_skipis passed directly to pre-commit'sSKIPvariable, but this repository only defines thetrivyhook (.pre-commit-config.yaml:39), nottrivy-licenses. As a result, the new entry has no effect and the Trivy hook will still run on the runs this list is intended to skip; remove this token (the existingtrivyentry already covers the configured hook) or add/update the corresponding hook definition.
commitlint,trivy,trivy-conf,trivy-filesystem,trivy-licenses,checkov,checkov_diff,terraform_validate
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
d8c0d7f to
a684581
Compare
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
a684581 to
5561426
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate security, validation, accuracy, and dependency-coverage findings remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (6)
.github/actions/trivy-license/action.yaml:49
- Although the action documentation says it fails when the committed report differs,
fail-on-diffdefaults to false and the wrapper at.github/actions/trivy/action.yaml:162-165does not enable it. Every normal scan therefore skipstrivy-license/check-diff, so a changed license report is only uploaded and never blocks or requires a commit. Either passfail-on-diff: 'true'once reproducibility is ready or make the contract explicitly generation-only.
default: 'false'
.github/actions/trivy-license/script.sh:180
- This includes every
license-fileresult from scanning${REPO_ROOT}, including the repository's ownLICENSEand loose license headers in source files. Becausepkg_offalls back to the file path, those repository-owned files are emitted as if they were third-party packages, which makes the report inaccurate. Restrict loose-file results to dependency directories/package-associated results or explicitly exclude repository-owned files.
[.Results[]? | select(.Class == "license" or .Class == "license-file")
| . as $r | ($r.Licenses // [])[] | . as $lic
| { Target: $r.Target,
Package: (if ($lic.PkgName // "") == "" then (try pkg_of($lic.FilePath // "-") catch ($lic.FilePath // "-")) else $lic.PkgName end),
License: ($lic.Name // "UNKNOWN"),
Classification: ($lic.Category // "-"),
Severity: ($lic.Severity // "-") }]
| unique
.github/actions/trivy-license/script.sh:236
- This hard-coded link exposes
indykite/.githubin the generated report, contradicting the script's promise that the internal repository URL is never printed (lines 33-35). Since the report is explicitly described as shareable with customers, omit the internal URL or use a caller-provided public attribution instead.
echo "Auto-generated by \`trivy fs --scanners license\` via the"
echo "[.github//trivy-license](https://github.com/indykite/.github/tree/master/.github/actions/trivy-license) action."
echo "Regenerate with \`${REGEN_CMD}\`."
.github/actions/trivy-license/script.sh:290
- The plain-text renderer also embeds the
indykite/.githubURL, so this output leaks the internal action repository despite the privacy guarantee in the script header. Remove this URL or replace it with an explicitly public, caller-provided attribution.
echo "Auto-generated by: trivy fs --scanners license (.github//trivy-license action)"
echo "https://github.com/indykite/.github/tree/master/.github/actions/trivy-license"
.github/actions/trivy-license/script.sh:151
- The workflow invokes this script on a clean checkout, but the script only preloads Go modules and (when
pipenvhappens to be installed) Pipenv. It never installs npm/yarn/pnpm, pip, or Poetry dependencies, so theirnode_modules/virtualenvs are absent and the generated LICENSES report silently omits those common dependencies. Add deterministic dependency preparation or explicitly document/disable these ecosystems.
echo "scanning ${REPO_ROOT} for 3rd-party dependency licenses..."
# '--exit-code 0' overrides any 'exit-code' set in the repo's own '.trivy.yaml': this scan only
# ever reports, it never enforces (allowed/forbidden licenses are the repo's own concern).
# '--offline-scan=false' overrides the repo's own 'scan.offline' setting (usually 'true', to keep
# the main vuln/misconfig scan network-free): license detection for Go/npm packages often needs
# to fetch package source when it isn't already in a warm module/dependency cache (e.g. a fresh
# CI runner), otherwise most packages silently end up with no detected license at all.
trivy fs --scanners license "${CONFIG_ARGS[@]}" "${SKIP_ARGS[@]}" --exit-code 0 --offline-scan=false \
--format json --output "${JSON_FILE}" "${REPO_ROOT}"
.github/actions/trivy/action.yaml:165
- This invocation does not pass
fail-on-diff, whose default in.github/actions/trivy-license/action.yamlisfalse, so thetrivy-license/check-diffstep is skipped. The new scan therefore neither requires a committed LICENSES report nor detects report changes, despite the child action's documented contract saying it validates one; expose/pass an explicit validation policy, or revise the contract if report-only behavior is intended.
- name: trivy/license
uses: indykite/.github/.github/actions/trivy-license@master
if: ${{ inputs.scan-type == 'fs' && inputs.license-scan != 'false' }}
with:
format: ${{ inputs.license-format }}
- Files reviewed: 6/6 changed files
- Comments generated: 3
- Review effort level: Lite
| echo "Pipfile found in ${pipfile_dir#"${REPO_ROOT}"/}, running 'pipenv sync --dev' into an in-project .venv..." | ||
| # 'sync' (not 'install'): installs exactly what's pinned in Pipfile.lock, never re-resolves | ||
| # or rewrites it -- this is a read-only scan, not a dependency update. | ||
| (cd "${pipfile_dir}" && PIPENV_VENV_IN_PROJECT=1 pipenv sync --dev) || echo "warning: 'pipenv sync' failed in ${pipfile_dir}, Python license detection may be incomplete" >&2 |
| echo "no 3rd-party licenses detected, skipping ${REPORT_FILE}" | ||
| exit 0 |
| ' "${DEDUPED_JSON}" | ||
| )" | ||
|
|
||
| TOTAL_PACKAGES="$(echo -n "${ROWS}" | grep -c . || true)" |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate findings affect report correctness, CI enforcement, security, and scan performance.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (4)
.github/actions/trivy-license/script.sh:333
- When no licenses are detected, this early exit leaves any pre-existing
LICENSES.*file untouched. Withfail-on-diff: true, the checker then sees the stale file and compares it with the identical HEAD copy, so its "committed but no licenses detected" path is never reached and reports can survive dependency removal. Remove${REPORT_FILE}before exiting, or propagate the zero-findings state to the checker.
if [[ "${TOTAL_PACKAGES}" -eq 0 ]]; then
echo "no 3rd-party licenses detected, skipping ${REPORT_FILE}"
exit 0
.github/actions/trivy-license/script.sh:220
ROWSis explicitly one row per(target, package, license), so counting its lines overstates packages whenever a package has multiple licenses (and can count the same package across targets). The generated "Total packages scanned" value is therefore inaccurate; count unique(Target, Package)pairs fromDEDUPED_JSONinstead.
TOTAL_PACKAGES="$(echo -n "${ROWS}" | grep -c . || true)"
.github/actions/trivy-license/script.sh:135
- This shared action now runs
pipenv sync --devagainst every PR-controlledPipfile/lockfile. Installing a locked package executes its build/install hooks, so a malicious dependency can run arbitrary code in the license-scan job; the calling workflow grantscontents: write. Avoid installing untrusted dependencies in this privileged job, or isolate this enrichment in a read-only-permission job/sandbox.
(cd "${pipfile_dir}" && PIPENV_VENV_IN_PROJECT=1 pipenv sync --dev) || echo "warning: 'pipenv sync' failed in ${pipfile_dir}, Python license detection may be incomplete" >&2
.github/actions/trivy-license/script.sh:120
- For every repository containing a
go.mod, this downloads the full module graph on each invocation, but the caller's cache only covers.cache/trivy, not Go's module cache. On fresh GitHub-hosted runners this adds an uncached network download to every PR and can dominate the license job; cacheGOMODCACHEkeyed by the Go lockfiles (or avoid hydration when the cache is unavailable).
if command -v go >/dev/null 2>&1; then
while IFS= read -r -d '' gomod; do
gomod_dir="$(dirname "${gomod}")"
echo "go.mod found in ${gomod_dir#"${REPO_ROOT}"/}, running 'go mod download'..."
(cd "${gomod_dir}" && go mod download) || echo "warning: 'go mod download' failed in ${gomod_dir}, Go license detection may be incomplete" >&2
done < <(find "${REPO_ROOT}" \( -path '*/.git' -o -path '*/.terraform' -o -path '*/.terragrunt-cache' -o -path '*/site-packages' -o -path '*/node_modules' \) -prune -o -name go.mod -print0 || true)
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Lite
| with: | ||
| format: ${{ inputs.license-format }} |
Automatically generated PR to sync GitHub Actions and related configs.