Skip to content

Commit cdaea8e

Browse files
authored
Merge pull request #12 from IMIO/add/claude-agent
Add/claude agent
2 parents 316abd1 + 408cc48 commit cdaea8e

5 files changed

Lines changed: 392 additions & 0 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changelog
22

3+
## [v7.2.0] - 2026-04-23
4+
### Added
5+
- claude-agent
6+
- New composite action wrapping `anthropics/claude-code-action` (SHA-pinned) for running a Claude Code agent in CI pipelines
7+
- Accepts a `PROMPT`, an optional newline-separated list of `FILES` to expose, a `MODEL` override (default `claude-sonnet-4-6`), and an optional `GITHUB_TOKEN` for GitHub API operations
8+
- Claude output is displayed in the GitHub Actions Step Summary
9+
- trivy-claude-analysis
10+
- New composite action that reads a Trivy JSON report and asks Claude to create one private draft GitHub security advisory per finding
11+
- Takes a `JSON_FILE` path (from `trivy-scan-notify`'s `json_file` output in the same job, or from `actions/download-artifact` in a later job)
12+
- `SEVERITIES` input (default `CRITICAL,HIGH`) controls which severity levels are processed; append `,MEDIUM` to include medium findings
13+
- Advisories are deduplicated against existing drafts and processed in CRITICAL → HIGH → MEDIUM order
14+
- Requires `repository-advisories: write` permission in the calling workflow
15+
- Enables a two-job manual-approval pattern: job 1 scans and uploads the JSON artifact, job 2 (gated by a GitHub Environment with required reviewers) downloads the exact artifact and runs Claude — no re-scan, no state drift, no `EXIT_CODE: '0'` hack
16+
### Changed
17+
- trivy-scan-notify
18+
- Now uploads the Trivy JSON report as a workflow artifact (14-day retention) in addition to the SARIF artifact
19+
- Exposes outputs `critical`, `high`, `medium`, `json_file`, and `artifact_name` for chaining with `trivy-claude-analysis`
20+
321
## [v7.1.0] - 2026-04-21
422
### Added
523
- trivy-scan-notify

‎README.md‎

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ This repository hosts a set of github actions we use to deploy our apps.
4848
- [trivy-sbom-notify](#trivy-sbom-notify)
4949
- [Inputs](#inputs-12)
5050
- [Example of usage](#example-of-usage-13)
51+
- [trivy-claude-analysis](#trivy-claude-analysis)
52+
- [Inputs](#inputs-13)
53+
- [Example of usage](#example-of-usage-14)
54+
- [claude-agent](#claude-agent)
55+
- [Inputs](#inputs-14)
56+
- [Example of usage](#example-of-usage-15)
5157
- [Contribute](#contribute)
5258
- [Release](#release)
5359

@@ -374,6 +380,16 @@ External actions are pinned by SHA as required by the iMio security référentie
374380
| GITHUB_TOKEN | no | string | | Pass `secrets.GITHUB_TOKEN` to avoid Trivy DB rate-limits |
375381
| MATTERMOST_WEBHOOK_URL | no | string | | Webhook URL to send notifications on Mattermost |
376382

383+
#### Outputs
384+
385+
| name | description |
386+
| ------------- | ----------- |
387+
| critical | Number of CRITICAL findings |
388+
| high | Number of HIGH findings |
389+
| medium | Number of MEDIUM findings |
390+
| json_file | Filename of the Trivy JSON report (relative to the workspace) — use as `JSON_FILE` input to `trivy-claude-analysis` in the same job |
391+
| artifact_name | Name of the uploaded Trivy JSON workflow artifact — use with `actions/download-artifact` in a later job |
392+
377393
#### Example of usage
378394

379395
```yaml
@@ -422,6 +438,8 @@ jobs:
422438
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
423439
```
424440

441+
To run Claude on the scan results — either immediately in the same job, or after a manual approval step in a second job — see [`trivy-claude-analysis`](#trivy-claude-analysis) below.
442+
425443
---
426444
### trivy-sbom-notify
427445

@@ -457,6 +475,155 @@ jobs:
457475
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
458476
```
459477

478+
---
479+
### trivy-claude-analysis
480+
481+
Post-processing action that reads a Trivy JSON report and asks Claude to create **private draft** GitHub repository security advisories — one per finding, at the severities you choose. The Trivy-specific prompt (CVE handling, ecosystem mapping, deduplication) is versioned inside this action, so caller repositories never duplicate it.
482+
483+
> [!IMPORTANT]
484+
> The calling workflow must grant `permissions: repository-advisories: write` for advisory creation to succeed.
485+
486+
This action is typically chained after [`trivy-scan-notify`](#trivy-scan-notify), which produces the JSON report and uploads it as a workflow artifact.
487+
488+
#### Inputs
489+
490+
| name | required | type | default | description |
491+
| ----------------- | -------- | ------ | --------------------- | ----------- |
492+
| JSON_FILE | yes | string | | Path to the Trivy JSON report (e.g. `trivy-image.json`). Use `steps.<id>.outputs.json_file` from `trivy-scan-notify` in the same job. |
493+
| SCAN_TYPE | yes | string | | `image`, `fs`, or `config` |
494+
| TARGET | yes | string | | What was scanned (image reference or scan path) |
495+
| SARIF_CATEGORY | no | string | `"trivy-<SCAN_TYPE>"` | SARIF category from the originating scan, used to link advisories to the Code Scanning report |
496+
| SEVERITIES | no | string | `"CRITICAL,HIGH"` | Comma-separated severities. Append `,MEDIUM` to include medium findings. |
497+
| ANTHROPIC_API_KEY | yes | string | | Anthropic API key. Pass `secrets.ANTHROPIC_API_KEY`. |
498+
| GITHUB_TOKEN | yes | string | | GitHub token with `repository-advisories: write`. Pass `secrets.GITHUB_TOKEN`. |
499+
| MODEL | no | string | `"claude-sonnet-4-6"` | Claude model ID override |
500+
501+
#### Example — single-job (scan and analyze immediately)
502+
503+
```yaml
504+
permissions:
505+
contents: read
506+
security-events: write
507+
repository-advisories: write
508+
509+
jobs:
510+
trivy:
511+
runs-on: ubuntu-latest
512+
steps:
513+
- uses: imio/gha/trivy-scan-notify@v7
514+
id: trivy
515+
with:
516+
SCAN_TYPE: image
517+
IMAGE_REF: registry.example.org/myapp:${{ github.sha }}
518+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
519+
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
520+
521+
- uses: imio/gha/trivy-claude-analysis@v7
522+
if: steps.trivy.outputs.critical > 0 || steps.trivy.outputs.high > 0
523+
with:
524+
JSON_FILE: ${{ steps.trivy.outputs.json_file }}
525+
SCAN_TYPE: image
526+
TARGET: registry.example.org/myapp:${{ github.sha }}
527+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
528+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
529+
```
530+
531+
The JSON file is already on disk from `trivy-scan-notify`, so no re-scan is needed.
532+
533+
#### Example — two-job pattern with manual approval
534+
535+
This pattern gates the Claude analysis (and the Anthropic token cost) behind a human approval step. Job 1 runs the scan and posts finding counts to Mattermost. A reviewer approves job 2 only when Claude analysis is worth running. Job 2 operates on the **exact JSON** produced by job 1 (downloaded from the workflow artifact), so there is no re-scan and no risk of state drift.
536+
537+
> [!NOTE]
538+
> Create a `security-review` environment in repo Settings → Environments and add required reviewers before using this pattern.
539+
540+
```yaml
541+
jobs:
542+
scan:
543+
runs-on: ubuntu-latest
544+
permissions:
545+
contents: read
546+
security-events: write
547+
outputs:
548+
critical: ${{ steps.trivy.outputs.critical }}
549+
high: ${{ steps.trivy.outputs.high }}
550+
json_file: ${{ steps.trivy.outputs.json_file }}
551+
artifact_name: ${{ steps.trivy.outputs.artifact_name }}
552+
steps:
553+
- uses: imio/gha/trivy-scan-notify@v7
554+
id: trivy
555+
with:
556+
SCAN_TYPE: image
557+
IMAGE_REF: registry.example.org/myapp:${{ github.sha }}
558+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
559+
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
560+
561+
claude-analysis:
562+
needs: scan
563+
if: needs.scan.outputs.critical > 0 || needs.scan.outputs.high > 0
564+
environment: security-review # pauses for human approval
565+
runs-on: ubuntu-latest
566+
permissions:
567+
contents: read
568+
repository-advisories: write
569+
steps:
570+
- uses: actions/download-artifact@v4
571+
with:
572+
name: ${{ needs.scan.outputs.artifact_name }}
573+
574+
- uses: imio/gha/trivy-claude-analysis@v7
575+
with:
576+
JSON_FILE: ${{ needs.scan.outputs.json_file }}
577+
SCAN_TYPE: image
578+
TARGET: registry.example.org/myapp:${{ github.sha }}
579+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
580+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
581+
```
582+
583+
---
584+
### claude-agent
585+
586+
Run a [Claude Code](https://docs.anthropic.com/claude/claude-code) agent with a given prompt in a CI pipeline. Thin, opinionated wrapper around `anthropics/claude-code-action` with prompt composition, optional file exposure, model selection, and GitHub API access for operations such as creating security advisories.
587+
588+
> [!NOTE]
589+
> The calling workflow must grant the permissions required for the operations Claude will perform. For security advisory creation, add `repository-advisories: write`.
590+
591+
#### Inputs
592+
593+
| name | required | type | default | description |
594+
| ----------------- | -------- | ------ | --------------------- | ----------- |
595+
| PROMPT | yes | string | | Instructions for Claude |
596+
| FILES | no | string | | Newline-separated list of file paths to expose to Claude (appended to the prompt as a "Files to examine" section) |
597+
| ANTHROPIC_API_KEY | yes | string | | Anthropic API key. Pass `secrets.ANTHROPIC_API_KEY`. |
598+
| MODEL | no | string | `"claude-sonnet-4-6"` | Claude model ID |
599+
| GITHUB_TOKEN | no | string | | GitHub token forwarded to Claude for GitHub API operations (e.g. creating security advisories). Pass `secrets.GITHUB_TOKEN`. |
600+
601+
Claude's output is displayed in the GitHub Actions Step Summary (`display_report: true`).
602+
603+
#### Example of usage
604+
605+
```yaml
606+
jobs:
607+
security-advisory:
608+
runs-on: ubuntu-latest
609+
permissions:
610+
contents: read
611+
repository-advisories: write
612+
steps:
613+
- uses: imio/gha/claude-agent@v7
614+
with:
615+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
616+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
617+
PROMPT: |
618+
Review the dependency list and create a private draft security advisory
619+
for any known critical vulnerability you find.
620+
FILES: |
621+
package.json
622+
requirements.txt
623+
```
624+
625+
For Trivy scan post-processing, use the dedicated [`trivy-claude-analysis`](#trivy-claude-analysis) action instead of calling `claude-agent` directly — it keeps the Trivy-specific prompt versioned inside the iMio actions.
626+
460627
## Contribute
461628

462629
### Release

‎claude-agent/action.yml‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Claude agent
2+
description: Run a Claude Code agent with a given prompt, optionally focusing on specific files. Thin wrapper around anthropics/claude-code-action with sensible CI defaults.
3+
4+
inputs:
5+
PROMPT:
6+
description: 'Instructions for Claude'
7+
required: true
8+
FILES:
9+
description: 'Newline-separated list of file paths to expose to Claude (appended to the prompt as context)'
10+
required: false
11+
default: ''
12+
ANTHROPIC_API_KEY:
13+
description: 'Anthropic API key (pass secrets.ANTHROPIC_API_KEY from the calling workflow)'
14+
required: true
15+
MODEL:
16+
description: 'Claude model ID'
17+
required: false
18+
default: 'claude-sonnet-4-6'
19+
GITHUB_TOKEN:
20+
description: 'GitHub token forwarded to Claude for GitHub API operations (e.g. creating security advisories). Requires the appropriate permissions in the calling workflow (e.g. repository-advisories: write).'
21+
required: false
22+
default: ''
23+
24+
runs:
25+
using: 'composite'
26+
steps:
27+
- name: Compose prompt
28+
id: compose
29+
shell: bash
30+
env:
31+
PROMPT: ${{ inputs.PROMPT }}
32+
FILES: ${{ inputs.FILES }}
33+
run: |
34+
FULL_PROMPT="$PROMPT"
35+
if [ -n "$FILES" ]; then
36+
FILES_LIST=$(printf '%s' "$FILES" | sed '/^[[:space:]]*$/d' | sed 's/^/- /')
37+
FULL_PROMPT="${FULL_PROMPT}"$'\n\n'"Files to examine:"$'\n'"${FILES_LIST}"
38+
fi
39+
DELIMITER="PROMPT_EOF_$(openssl rand -hex 8)"
40+
{
41+
echo "prompt<<$DELIMITER"
42+
printf '%s\n' "$FULL_PROMPT"
43+
echo "$DELIMITER"
44+
} >> "$GITHUB_OUTPUT"
45+
46+
- name: Run Claude agent
47+
uses: anthropics/claude-code-action@b4d67413279fc18c6e5de930ae307c4f108714eb # v1
48+
with:
49+
prompt: ${{ steps.compose.outputs.prompt }}
50+
anthropic_api_key: ${{ inputs.ANTHROPIC_API_KEY }}
51+
github_token: ${{ inputs.GITHUB_TOKEN }}
52+
claude_args: '--model ${{ inputs.MODEL }}'
53+
display_report: 'true'

0 commit comments

Comments
 (0)