Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,15 @@ runs:
-e GITHUB_ACTIONS -e GITHUB_REPOSITORY -e GITHUB_REF_NAME -e GITHUB_HEAD_REF \
-e GITHUB_SHA -e GITHUB_ACTOR -e GITHUB_DEFAULT_BRANCH="${{ github.event.repository.default_branch }}" \
"${{ inputs.image }}" scan --mode "${{ inputs.mode }}"

# The container runs as root over the mounted workspace, so anything a
# scanner leaves behind is owned by root. The next `actions/checkout` runs
# as the runner's user, cannot delete those files, and fails the job —
# every job, not only this one. Hand the workspace back before leaving.
- name: Restore workspace ownership
if: always()
shell: bash
run: |
owner=$(stat -c '%u:%g' "${{ github.workspace }}")
docker run --rm -v "${{ github.workspace }}:/src" \
--entrypoint chown "${{ inputs.image }}" -R "$owner" /src || true
8 changes: 8 additions & 0 deletions src/cerberus.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ describe("buildInvocations", () => {
expect(inv.command).toContain("--output-file-path");
});

it("keeps checkov out of the scanned directory", () => {
// github_configuration writes `github_conf/` into the workspace as root,
// which breaks the next checkout on a self-hosted runner.
const inv = buildInvocations(parseConfig({}), "/tmp/out").find((i) => i.name === "checkov")!;
const argv = inv.command as string[];
expect(argv[argv.indexOf("--skip-framework") + 1]).toBe("github_configuration");
});

it("hadolint writes an empty report when the repo has no Dockerfile", () => {
const inv = buildInvocations(parseConfig({}), "/tmp/out").find((i) => i.name === "hadolint")!;
expect(inv.command).toContain('"version":"2.1.0"'); // the no-Dockerfile fallback
Expand Down
8 changes: 8 additions & 0 deletions src/scanners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,19 @@ export function buildInvocations(config: CerberusConfig, outDir: string): Invoca
// --output-file-path takes a directory; checkov names the file itself.
// It also exits non-zero when it finds anything, which is not a failure —
// the runner prefers the report over the exit code.
//
// github_configuration is skipped on purpose: with a GITHUB_TOKEN in the
// environment it calls the API and dumps `github_conf/` into the scanned
// directory. We run as root over a mounted workspace, so that directory
// outlives the container owned by root — and the next `actions/checkout`,
// running as the runner's user, cannot delete it and fails the whole
// pipeline. It audits branch protection, which we do not act on anyway.
inv.push({
name: "checkov",
output: join(outDir, "results_sarif.sarif"),
command: [
"checkov", "-d", ".", "-o", "sarif", "--output-file-path", outDir,
"--skip-framework", "github_configuration",
"--compact", "--quiet", ...s.checkov.args,
],
});
Expand Down
Loading