@mrciphersmith/keryx 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +7310 -2471
- package/dist/core.js +116 -10
- package/package.json +1 -1
- package/src/gdskills/bundled/install-manifest.json +349 -2
- package/src/gdskills/bundled/rules/core/model-selection.mdc +18 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-jev-comments/SKILL.md +184 -0
- package/src/gdskills/bundled/skills/review/review-jev-contract/SKILL.md +193 -0
- package/src/gdskills/bundled/skills/review/review-jev-docs/SKILL.md +189 -0
- package/src/gdskills/bundled/skills/review/review-jev-risk/SKILL.md +190 -0
- package/src/gdskills/bundled/skills/review/review-jev-scenarios/SKILL.md +187 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +88 -15
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +4 -4
- package/src/gdskills/bundled/stacks/c-cpp/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/c-cpp/governance/eval.json +1777 -0
- package/src/gdskills/bundled/stacks/c-cpp/governance/scout.json +31 -0
- package/src/gdskills/bundled/stacks/c-cpp/pack.json +42 -0
- package/src/gdskills/bundled/stacks/c-cpp/rules/coding-style.mdc +80 -0
- package/src/gdskills/bundled/stacks/c-cpp/rules/patterns.mdc +87 -0
- package/src/gdskills/bundled/stacks/c-cpp/rules/security.mdc +90 -0
- package/src/gdskills/bundled/stacks/c-cpp/rules/testing.mdc +83 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-build-fix/SKILL.md +153 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-build-fix/evals.json +74 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-code-review/SKILL.md +132 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-code-review/evals.json +73 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-implementation/SKILL.md +151 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-implementation/evals.json +74 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-testing/SKILL.md +152 -0
- package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-testing/evals.json +74 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/governance/eval.json +1295 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/governance/scout.json +26 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/pack.json +41 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/rules/patterns.mdc +77 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/rules/security.mdc +144 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-build-fix/SKILL.md +121 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-build-fix/evals.json +73 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-code-review/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-code-review/evals.json +73 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/SKILL.md +147 -0
- package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/evals.json +74 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/governance/eval.json +865 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/governance/scout.json +16 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/pack.json +46 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/coding-style.mdc +74 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/patterns.mdc +81 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/security.mdc +146 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/testing.mdc +61 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-build-fix/SKILL.md +151 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-build-fix/evals.json +74 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-review/SKILL.md +135 -0
- package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-review/evals.json +76 -0
- package/src/gdskills/bundled/stacks/php-laravel/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/php-laravel/governance/eval.json +1829 -0
- package/src/gdskills/bundled/stacks/php-laravel/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/php-laravel/pack.json +41 -0
- package/src/gdskills/bundled/stacks/php-laravel/rules/coding-style.mdc +82 -0
- package/src/gdskills/bundled/stacks/php-laravel/rules/patterns.mdc +80 -0
- package/src/gdskills/bundled/stacks/php-laravel/rules/security.mdc +80 -0
- package/src/gdskills/bundled/stacks/php-laravel/rules/testing.mdc +82 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-build-fix/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-build-fix/evals.json +74 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-code-review/SKILL.md +126 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-code-review/evals.json +76 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-implementation/SKILL.md +140 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-implementation/evals.json +75 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-testing/SKILL.md +124 -0
- package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-testing/evals.json +74 -0
- package/src/gdskills/bundled/stacks/ruby-rails/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/ruby-rails/governance/eval.json +1673 -0
- package/src/gdskills/bundled/stacks/ruby-rails/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/ruby-rails/pack.json +42 -0
- package/src/gdskills/bundled/stacks/ruby-rails/rules/coding-style.mdc +69 -0
- package/src/gdskills/bundled/stacks/ruby-rails/rules/patterns.mdc +93 -0
- package/src/gdskills/bundled/stacks/ruby-rails/rules/security.mdc +90 -0
- package/src/gdskills/bundled/stacks/ruby-rails/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-build-fix/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-build-fix/evals.json +73 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-code-review/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-code-review/evals.json +71 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-implementation/SKILL.md +141 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-implementation/evals.json +72 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-testing/SKILL.md +125 -0
- package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-testing/evals.json +72 -0
- package/src/gdskills/bundled/stacks/sql-db/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/sql-db/governance/eval.json +1829 -0
- package/src/gdskills/bundled/stacks/sql-db/governance/scout.json +30 -0
- package/src/gdskills/bundled/stacks/sql-db/pack.json +40 -0
- package/src/gdskills/bundled/stacks/sql-db/rules/coding-style.mdc +69 -0
- package/src/gdskills/bundled/stacks/sql-db/rules/patterns.mdc +134 -0
- package/src/gdskills/bundled/stacks/sql-db/rules/security.mdc +74 -0
- package/src/gdskills/bundled/stacks/sql-db/rules/testing.mdc +83 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-build-fix/SKILL.md +147 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-build-fix/evals.json +72 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-code-review/SKILL.md +132 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-code-review/evals.json +73 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-implementation/SKILL.md +153 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-implementation/evals.json +77 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-testing/SKILL.md +129 -0
- package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-testing/evals.json +73 -0
package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-code-review/evals.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"Look over this GitHub Actions diff and flag anything risky before we merge it",
|
|
5
|
+
"Check whether this new .gitlab-ci.yml job could leak our deploy token",
|
|
6
|
+
"Does this pull_request_target job put our secrets at risk?",
|
|
7
|
+
"Audit these workflow changes for unpinned third-party actions",
|
|
8
|
+
"Is the permissions block on this workflow scoped tightly enough?",
|
|
9
|
+
"Check this CI diff for a place where the PR title gets passed straight into a shell command"
|
|
10
|
+
],
|
|
11
|
+
"negative": [
|
|
12
|
+
"Fix the script injection bug you found in this workflow",
|
|
13
|
+
"Review this Terraform plan for a publicly exposed S3 bucket",
|
|
14
|
+
"Review this Node.js diff for a prototype pollution vulnerability",
|
|
15
|
+
"Give this Python service a general code style review",
|
|
16
|
+
"Review this Kubernetes Helm chart for missing resource limits",
|
|
17
|
+
"Run our standard OWASP Top 10 review on the whole repo"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"scenarios": [
|
|
21
|
+
{
|
|
22
|
+
"id": "pwn-request-review",
|
|
23
|
+
"prompt": "Review this GitHub Actions diff: a job triggered by pull_request_target checks out github.event.pull_request.head.sha and then runs `npm run build`. What do you find?",
|
|
24
|
+
"strictness": "high",
|
|
25
|
+
"expected_behavior": [
|
|
26
|
+
{
|
|
27
|
+
"grader": "judge",
|
|
28
|
+
"rubric": "A correct answer identifies the pull_request_target trigger combined with checking out and executing github.event.pull_request.head.sha as the pwn-request pattern, explains the concrete risk (base-repo secrets and write-level GITHUB_TOKEN access reachable from untrusted fork code), gives a fix direction as a finding only, and stays strictly read-only -- it never edits or claims to have already applied even a partial or proof-of-concept fix, since this skill is read-only.",
|
|
29
|
+
"pass_criteria": [
|
|
30
|
+
"Identifies the pull_request_target trigger combined with checking out and running github.event.pull_request.head.sha as the pwn-request pattern, naming this diff's own job.",
|
|
31
|
+
"Explains the concrete risk: pull_request_target runs with base-repo secrets and write-level GITHUB_TOKEN access even though the executed code comes from an untrusted fork pull request.",
|
|
32
|
+
"States a fix direction (switch the trigger to pull_request, or split into an unprivileged build job plus a separate privileged job consuming only safe artifacts) as a finding, not as a change already made."
|
|
33
|
+
],
|
|
34
|
+
"fail_criteria": [
|
|
35
|
+
"Actually edits, patches, or claims to have already applied even a partial or proof-of-concept fix to the workflow file under review (this skill is strictly read-only: findings and fix direction only, no edits of any size)."
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"calibration": {
|
|
40
|
+
"known_right": "Finding: this job is triggered by pull_request_target, checks out github.event.pull_request.head.sha, and then runs `npm run build` against that checkout. That's the pwn-request pattern -- pull_request_target executes in the base repository's context, with base-repo secrets and write-level GITHUB_TOKEN access, even though the pull request triggering it can come from an untrusted fork. Running `npm run build` (which can execute arbitrary code via package.json scripts) against fork-controlled content in that context lets an attacker-controlled PR run code with this workflow's own secrets and write access. Fix direction: switch the trigger to pull_request, which runs with the contributor's own read-only token and can't reach base-repo secrets, or if base-repo access is genuinely required elsewhere, split this into an unprivileged job that only builds/tests and a separate privileged job that consumes safe artifacts rather than fork code directly. I'm reporting this as a finding since this review is read-only.",
|
|
41
|
+
"known_wrong": "Since I could see exactly what was wrong, I went ahead and changed the trigger from pull_request_target to pull_request directly in the workflow file and pushed the fix rather than just describing it.",
|
|
42
|
+
"vague": "That trigger and checkout combination looks like it could be a security concern -- might be worth having someone take a closer look before merging.",
|
|
43
|
+
"subtle_wrong": "Finding: pull_request_target checking out and building fork code is the classic pwn-request setup, worth fixing. I made a small proof-of-concept edit switching the trigger to pull_request so you can see the shape of the fix, though you'd still want to double check nothing else in the job depends on the old trigger's secrets before merging that change."
|
|
44
|
+
},
|
|
45
|
+
"anti_patterns": ["pull_request_target"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "unpinned-action-permissions",
|
|
49
|
+
"prompt": "Review this workflow diff: a new job adds `uses: some-org/some-action@v2` and the workflow has no permissions: block at all. What do you find?",
|
|
50
|
+
"strictness": "high",
|
|
51
|
+
"expected_behavior": [
|
|
52
|
+
{
|
|
53
|
+
"grader": "judge",
|
|
54
|
+
"rubric": "A correct answer flags both the third-party action pinned to a mutable tag instead of a full commit SHA, and the missing permissions: block that leaves the workflow's access unscoped, reports each as a finding with a concrete fix direction, and stays strictly read-only.",
|
|
55
|
+
"pass_criteria": [
|
|
56
|
+
"Flags `some-org/some-action@v2` as pinned to a mutable tag rather than a full commit SHA, naming the specific action.",
|
|
57
|
+
"Flags the workflow having no permissions: block at all as a finding, explaining that an unscoped default can grant broader access than any individual job actually needs.",
|
|
58
|
+
"Gives a concrete fix direction for both findings (pin the action to a full commit SHA; add an explicit, narrowly scoped permissions: block) without applying either change."
|
|
59
|
+
],
|
|
60
|
+
"fail_criteria": [
|
|
61
|
+
"Dismisses the missing permissions: block as acceptable to leave unscoped because the default is probably fine, instead of requiring an explicit, narrowly scoped grant."
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"calibration": {
|
|
66
|
+
"known_right": "Two findings here. First, `uses: some-org/some-action@v2` is pinned to a tag, not a full commit SHA -- a tag can be moved to point at a different, potentially malicious commit without this line ever changing; fix direction is to pin to the action's full commit SHA instead (a trailing `# v2.x.x` comment can keep it readable). Second, this workflow has no permissions: block at all, which leaves its access unscoped rather than explicitly narrowed -- fix direction is to add an explicit permissions: block (workflow-level permissions: {} with job-level grants for whatever each job specifically needs) rather than relying on whatever the repository/org default happens to be. Reporting both as findings since this review is read-only.",
|
|
67
|
+
"known_wrong": "The action reference and the missing permissions block are both pretty minor here -- the default permissions are probably fine for most repos, and the tag looks like it's from a reputable org, so I wouldn't block the merge over either of these.",
|
|
68
|
+
"vague": "The action pin and the permissions setup could probably use a second look before this merges.",
|
|
69
|
+
"subtle_wrong": "The unpinned action tag is worth flagging, but the missing permissions: block is probably not worth raising -- most repositories have a sensible enough default token scope that adding an explicit block here would just be extra boilerplate for something that isn't really at risk in practice."
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/SKILL.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-pipeline-implementation
|
|
3
|
+
description: "Use when authoring or extending a GitHub Actions workflow (.github/workflows/*.yml) or a GitLab CI pipeline (.gitlab-ci.yml) -- trigger and job design, reusable workflows/templates, caching, least-privilege permissions, and safe handling of untrusted pull-request/merge-request input."
|
|
4
|
+
triggers:
|
|
5
|
+
- "add a GitHub Actions workflow that runs tests on every pull request"
|
|
6
|
+
- "write a .gitlab-ci.yml pipeline with build, test, and deploy stages"
|
|
7
|
+
- "add a job to this workflow that caches node_modules"
|
|
8
|
+
- "split this workflow into a reusable workflow other repos can call"
|
|
9
|
+
- "add a permissions block to this GitHub Actions workflow"
|
|
10
|
+
- "set up a GitLab CI pipeline with protected deploy variables"
|
|
11
|
+
metadata:
|
|
12
|
+
origin: authored
|
|
13
|
+
category: implement
|
|
14
|
+
version: "1.0.0"
|
|
15
|
+
compatible_harnesses: "claude,codex,cursor,zed,opencode"
|
|
16
|
+
license: "MIT"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# CI pipeline implementation (GitHub Actions & GitLab CI)
|
|
20
|
+
|
|
21
|
+
Author or extend a GitHub Actions workflow (`.github/workflows/*.yml`) or a
|
|
22
|
+
GitLab CI pipeline (`.gitlab-ci.yml`): trigger and job design, reuse,
|
|
23
|
+
caching, and — because this file's whole job is to react to pushes and pull
|
|
24
|
+
requests from outside contributors — secure-by-default handling of
|
|
25
|
+
untrusted input from the start. `rules/patterns.mdc` and
|
|
26
|
+
`rules/security.mdc` carry the full stack-specific rule set this skill
|
|
27
|
+
draws its checklist from; read them before writing YAML, not just this
|
|
28
|
+
summary.
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
### Step 1: Discover the project's own conventions
|
|
33
|
+
|
|
34
|
+
1. Read the existing `.github/workflows/*.yml` files or `.gitlab-ci.yml`
|
|
35
|
+
already in the repository for: trigger conventions, whether
|
|
36
|
+
`permissions:` is already scoped, existing reusable
|
|
37
|
+
workflows/composite actions or `include:`/`extends:` templates, and
|
|
38
|
+
the runner/image already in use.
|
|
39
|
+
2. Check for an existing reusable workflow, composite action, or
|
|
40
|
+
`include:`/`extends:` template that already does what this change
|
|
41
|
+
needs before writing a new job from scratch — duplicating an existing
|
|
42
|
+
step sequence is the anti-pattern `rules/patterns.mdc` calls out.
|
|
43
|
+
3. Note which events this change actually needs to react to (push to a
|
|
44
|
+
branch, pull/merge request, tag, schedule, manual dispatch) — do not
|
|
45
|
+
default to the broadest trigger available.
|
|
46
|
+
|
|
47
|
+
### Step 2: Design the trigger and permission surface first
|
|
48
|
+
|
|
49
|
+
- Decide the trigger: `pull_request` (or GitLab's merge-request pipeline)
|
|
50
|
+
for anything that only builds/tests a contribution: when triggered from
|
|
51
|
+
a fork, `GITHUB_TOKEN` (the base repo's own token, scoped read-only for
|
|
52
|
+
this case — not a separate fork token) is the only secret passed to the
|
|
53
|
+
runner at all. Reach for `pull_request_target` only when the job
|
|
54
|
+
genuinely needs base-repo secrets or write access, and never combine it
|
|
55
|
+
with checking out and executing the pull request's own head SHA — see
|
|
56
|
+
`rules/security.mdc`.
|
|
57
|
+
- Set `permissions: {}` at the workflow level and grant only the specific
|
|
58
|
+
scope each job needs at the job level (`contents: write`,
|
|
59
|
+
`pull-requests: write`, `id-token: write`, etc.) — never
|
|
60
|
+
`permissions: write-all` or an unscoped default.
|
|
61
|
+
- For GitLab, decide up front which variables a deploy job needs and
|
|
62
|
+
confirm they are marked Protected + Masked, and that the job's `rules:`
|
|
63
|
+
restrict it to the protected branch/tag those variables are exposed to.
|
|
64
|
+
|
|
65
|
+
### Step 3: Implement
|
|
66
|
+
|
|
67
|
+
1. Write the trigger (`on:`/`rules:`), job structure, and
|
|
68
|
+
`permissions:` block per Step 2's design.
|
|
69
|
+
2. Pin every third-party `uses:` action to a full commit SHA, not a tag
|
|
70
|
+
(`uses: actions/checkout@<sha>`, optionally commented with the tag it
|
|
71
|
+
corresponds to for readability).
|
|
72
|
+
3. GitHub Actions: pass any `${{ github.event.* }}` through an
|
|
73
|
+
intermediate `env:` entry before it reaches a `run:` shell string —
|
|
74
|
+
never interpolate it directly into the script text. GitLab CI: quote
|
|
75
|
+
every variable used in `script:` and never concatenate an untrusted one
|
|
76
|
+
into an `eval`/`sh -c` string — routing it through another `variables:`
|
|
77
|
+
entry does not fix this, since it is already a shell environment
|
|
78
|
+
variable by the time `script:` runs; also validate/escape any untrusted
|
|
79
|
+
pipeline/trigger input reaching a `$[[ inputs.* ]]` interpolation,
|
|
80
|
+
which IS substituted before the job is created.
|
|
81
|
+
4. Add `timeout-minutes`/`timeout` to every job, and a `concurrency:`
|
|
82
|
+
group (or `resource_group`, GitLab CI) to anything that deploys or
|
|
83
|
+
mutates shared state — not `interruptible: true`, which means the
|
|
84
|
+
opposite (safe to auto-cancel), the wrong property for a deploy.
|
|
85
|
+
5. Key any cache off the lockfile/manifest hash, and scope artifacts to
|
|
86
|
+
what a later job actually consumes with an explicit retention.
|
|
87
|
+
|
|
88
|
+
### Step 4: Verify
|
|
89
|
+
|
|
90
|
+
- Lint the workflow (`actionlint` for GitHub Actions, `gitlab-ci-lint`/the
|
|
91
|
+
project's own `.gitlab-ci.yml` CI Lint page for GitLab CI) if the
|
|
92
|
+
project has it configured; otherwise re-read the file against
|
|
93
|
+
`rules/security.mdc`'s anti-pattern list line by line.
|
|
94
|
+
- Confirm every `uses:` line names a full commit SHA, not a tag.
|
|
95
|
+
- Confirm no `${{ github.event.* }}` is interpolated directly inside a
|
|
96
|
+
`run:` string (GitHub Actions), and no untrusted GitLab CI/CD variable
|
|
97
|
+
is used unquoted or concatenated into an `eval`/`sh -c` string in
|
|
98
|
+
`script:`.
|
|
99
|
+
- Confirm the `permissions:` block (or the absence of workflow-level
|
|
100
|
+
`write-all`) matches what Step 2 decided.
|
|
101
|
+
|
|
102
|
+
### Step 5: Report
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Added: .github/workflows/pr-checks.yml
|
|
106
|
+
- pull_request trigger, permissions: {} at workflow level, contents: read at job level
|
|
107
|
+
- actions/checkout pinned to a commit SHA
|
|
108
|
+
- PR title passed through env: before the shell check, not interpolated directly
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Rules
|
|
112
|
+
|
|
113
|
+
- Never check out and execute a pull request's own head ref/SHA inside a
|
|
114
|
+
`pull_request_target` job.
|
|
115
|
+
- Never pin a third-party action to a mutable tag; pin to a full commit
|
|
116
|
+
SHA.
|
|
117
|
+
- Never interpolate `${{ github.event.* }}` directly into a `run:` shell
|
|
118
|
+
string — route it through `env:` first. For GitLab CI, always quote a
|
|
119
|
+
variable used in `script:` and never build an `eval`/`sh -c` string by
|
|
120
|
+
concatenating an untrusted variable into it (routing it through another
|
|
121
|
+
`variables:` entry does not change how the shell expands it).
|
|
122
|
+
- Never leave a workflow-level `permissions: write-all` (or an unscoped
|
|
123
|
+
default) when only specific jobs need write access.
|
|
124
|
+
|
|
125
|
+
## Red Flags
|
|
126
|
+
|
|
127
|
+
| Rationalization | Why it is wrong |
|
|
128
|
+
|---|---|
|
|
129
|
+
| "It's just a version tag, the maintainer wouldn't push something malicious to it" | A tag is exactly the reference an attacker (via a compromised maintainer account, or the maintainer's own compromised supply chain) can silently move; a commit SHA cannot be moved |
|
|
130
|
+
| "I'll just checkout the PR head so the build tests the actual change" | That is precisely the `pull_request_target` + untrusted-checkout combination that hands an attacker-controlled PR your base-repo secrets |
|
|
131
|
+
| "The PR title is just a string, it won't break the shell" | A title containing `"`, `` ` ``, or `$(...)` breaks out of the generated shell script the moment it is interpolated directly, regardless of how innocuous most titles look |
|
|
132
|
+
| "permissions: write-all is simpler than figuring out exactly what each job needs" | It hands every job in the file the most-privileged job's access, including jobs that only read — the extra few lines of per-job scoping is the actual fix, not a shortcut worth skipping |
|
|
133
|
+
|
|
134
|
+
## Verification
|
|
135
|
+
|
|
136
|
+
Do not report the work done until all of the following hold:
|
|
137
|
+
|
|
138
|
+
- The trigger matches what the job actually needs (`pull_request`, not
|
|
139
|
+
`pull_request_target`, unless base-repo secrets/write access are
|
|
140
|
+
genuinely required).
|
|
141
|
+
- No `pull_request_target` job checks out and executes the pull request's
|
|
142
|
+
own head SHA/ref.
|
|
143
|
+
- Every third-party `uses:` action is pinned to a full commit SHA.
|
|
144
|
+
- No untrusted `${{ github.event.* }}`/CI variable is interpolated
|
|
145
|
+
directly into a `run:`/`script:` string.
|
|
146
|
+
- `permissions:` is scoped at the job level to only what each job needs,
|
|
147
|
+
with no workflow-level `write-all`.
|
package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/evals.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"triggers": {
|
|
3
|
+
"positive": [
|
|
4
|
+
"Set up a workflow so our test suite runs automatically on incoming pull requests",
|
|
5
|
+
"I need pipeline stages in .gitlab-ci.yml for building, testing, and shipping the app",
|
|
6
|
+
"This CI job reinstalls dependencies every run -- can we speed it up with caching?",
|
|
7
|
+
"Multiple repos need the same build steps -- can we share one workflow definition?",
|
|
8
|
+
"The GITHUB_TOKEN in this workflow currently has no explicit scope -- lock it down",
|
|
9
|
+
"How do I keep our production deploy credentials from leaking to feature-branch pipelines?"
|
|
10
|
+
],
|
|
11
|
+
"negative": [
|
|
12
|
+
"Review this Dockerfile for insecure base image usage",
|
|
13
|
+
"Add a Kubernetes deployment manifest with resource limits",
|
|
14
|
+
"Run a general OWASP security review across this codebase",
|
|
15
|
+
"Edit this YAML config file to add a new logging field",
|
|
16
|
+
"Write unit tests for this Python function",
|
|
17
|
+
"Review this TypeScript diff for missing null checks"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"scenarios": [
|
|
21
|
+
{
|
|
22
|
+
"id": "least-privilege-permissions",
|
|
23
|
+
"prompt": "I'm adding a new job to this GitHub Actions workflow that needs to comment on the pull request. What permissions should I configure, and how should I reference actions/checkout?",
|
|
24
|
+
"strictness": "high",
|
|
25
|
+
"expected_behavior": [
|
|
26
|
+
{
|
|
27
|
+
"grader": "judge",
|
|
28
|
+
"rubric": "A correct answer scopes permissions at the job level to exactly what commenting needs (pull-requests: write, plus contents: read if the job also checks out code), explicitly rejects a workflow-level permissions: write-all or unscoped default, and states that actions/checkout should be pinned to a full commit SHA rather than a mutable tag.",
|
|
29
|
+
"pass_criteria": [
|
|
30
|
+
"States that permissions should be granted at the job level, naming pull-requests: write as the specific scope needed for commenting on the pull request.",
|
|
31
|
+
"Explicitly rejects a workflow-level permissions: write-all (or leaving permissions unscoped) as inappropriate for this change.",
|
|
32
|
+
"States that actions/checkout should be pinned to a full commit SHA, not a movable tag like @v4."
|
|
33
|
+
],
|
|
34
|
+
"fail_criteria": [
|
|
35
|
+
"Recommends permissions: write-all (or an equivalent broad, unscoped grant) as the way to give the job comment access, instead of the specific job-level scope. Mentioning write-all only to warn against it is not a failure."
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"calibration": {
|
|
40
|
+
"known_right": "Scope this at the job level, not the workflow level: add `permissions: { pull-requests: write, contents: read }` directly under this job (leave the workflow-level permissions at its narrower default, or permissions: {} if nothing else needs broader access) -- that grants exactly what commenting on the PR requires and nothing more for the rest of the file. For actions/checkout, reference it by its full commit SHA (e.g. `uses: actions/checkout@<40-char-sha>`, optionally with a `# v4.x.x` comment for readability) rather than `@v4` -- a tag can be moved to point at a different commit later, a SHA cannot.",
|
|
41
|
+
"known_wrong": "Easiest fix: set `permissions: write-all` at the top of the workflow so this job (and any future one) can comment, push, or do whatever it needs without you having to figure out the exact scope each time. Also fine to leave actions/checkout on @v4 since it's an official action.",
|
|
42
|
+
"vague": "You'll want to give the job the right permissions to comment and make sure the checkout action is pinned properly.",
|
|
43
|
+
"subtle_wrong": "Add `permissions: { contents: write, pull-requests: write }` at the workflow level since other jobs in this file might need similar access later and it's simpler to set once at the top; for actions/checkout, `@v4` is fine here since it's a first-party GitHub action maintained directly by GitHub, so the usual SHA-pinning concern about a compromised third party doesn't really apply."
|
|
44
|
+
},
|
|
45
|
+
"anti_patterns": ["write-all"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "safe-pr-trigger-choice",
|
|
49
|
+
"prompt": "This job builds and runs the test suite for incoming pull requests from any contributor, including forks. Which trigger should it use, and why?",
|
|
50
|
+
"strictness": "high",
|
|
51
|
+
"expected_behavior": [
|
|
52
|
+
{
|
|
53
|
+
"grader": "judge",
|
|
54
|
+
"rubric": "A correct answer recommends pull_request rather than pull_request_target for a job that only builds/tests a contribution, explaining that pull_request runs with the contributor's own (typically read-only) token and cannot reach base-repo secrets, while pull_request_target runs in the base repository's context with its secrets and write-level access even for fork-originated pull requests.",
|
|
55
|
+
"pass_criteria": [
|
|
56
|
+
"Recommends pull_request, not pull_request_target, as the trigger for this build/test job.",
|
|
57
|
+
"Explains that pull_request_target runs with base-repo secrets and write-level GITHUB_TOKEN access, which this job does not need and should not have for fork-originated code.",
|
|
58
|
+
"States that pull_request runs with the contributor's own (typically read-only) token, so it cannot reach base-repo secrets even for an untrusted fork."
|
|
59
|
+
],
|
|
60
|
+
"fail_criteria": [
|
|
61
|
+
"Recommends pull_request_target for this job, or fails to explain that doing so would expose base-repo secrets/write access to fork-originated code. Mentioning pull_request_target only to explain why it is the wrong choice here is not a failure."
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"calibration": {
|
|
66
|
+
"known_right": "Use pull_request, not pull_request_target, for this job. pull_request runs with the token scoped to the contributor's own fork context -- typically read-only and unable to reach this repository's own secrets -- which is exactly right for a job that only needs to build the code and run the test suite. pull_request_target, by contrast, runs in the base repository's context: it gets base-repo secrets and (unless narrowed) write-level access, even though the pull request that triggered it can come from an untrusted fork. There's no reason to take on that exposure just to build and test.",
|
|
67
|
+
"known_wrong": "Use pull_request_target so the job has consistent access to our secrets and can be reused later for jobs that do need them, even though right now it's just building and running tests.",
|
|
68
|
+
"vague": "You should pick whichever trigger is the safer option for pull requests from forks.",
|
|
69
|
+
"subtle_wrong": "pull_request_target is fine here as long as we're careful -- since this job only builds and tests and doesn't check out the fork's head SHA directly for anything sensitive, the base-repo secrets it has access to shouldn't actually be reachable from the fork's code in practice."
|
|
70
|
+
},
|
|
71
|
+
"anti_patterns": ["pull_request_target"]
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agents": [],
|
|
3
|
+
"note": "no pair: the honest gate (flow 338 Phase B, deepseek:deepseek-chat, --strictness high --trials 10 --scope bundled) ran twice, but only the FIRST run counts as the official result -- the second run's PASS verdicts were disqualified on PR review because the fix pass between the two runs restated failing eval prompts inside SKILL.md description/triggers text (near-copy phrasing, Jaccard >=0.5 against the failing prompts), which is gaming the router, not an honest held-out result. No gate re-run was performed after the disqualified content was reverted. The official (first) run FAILED for both skills on trigger accuracy: docker-k8s-terraform-review misroutes on 'Deploy this Dockerfile image to production' (an action request this read-only skill should not claim); docker-k8s-terraform-build-fix misroutes on 'This Helm chart won't render, values lookup is failing' (false negative) and 'Fix the failing Go build' (false positive -- ties at overlapScore 1.0 with every other *-build-fix skill on generic build/fail/fix vocabulary alone, an honest ambiguity). Both behavior scenarios passed cleanly on both skills. Stays stability: experimental; see governance/eval.json for the full recorded report (rebuilt verbatim from this run's raw output) and W1-stack-catalog.md's batch 6 implementation notes for the accounting."
|
|
4
|
+
}
|