| name | aikido-tickets |
| description | Create GitHub issues in fleetdm/confidential for Aikido pen test findings. Use when asked to "create aikido tickets", "aikido ticket", or "create pen test tickets". |
| allowed-tools | Bash(gh *), Bash(jq *), Read, Grep, Glob, Agent, Write |
| model | sonnet |
| effort | high |
Create Aikido Pen Test Tickets
Create GitHub issues in fleetdm/confidential for Aikido penetration test findings.
Prerequisites
Before starting, walk the user through these steps:
1. Export the Aikido report
The user needs to download the pen test report PDF from Aikido:
- Go to the Aikido assessment page (e.g.,
app.aikido.dev/ai-pentests/projects/.../assessments/.../issues)
- Click the purple "Download Report" button in the top-right corner
- Select "Detailed Auditor Report" (this contains every finding with technical details and remediation steps)
- Click Continue and save the downloaded PDF
- Provide the path to the downloaded PDF
2. GitHub project board permissions
Adding issues to project boards requires the project scope on the GitHub CLI token. Test by running:
gh project list --owner fleetdm --limit 1
If this fails with a scope error, the user needs to run interactively:
gh auth refresh -s project -h github.com
Alternative: If the user cannot or prefers not to grant project scope, skip the project board step. The issues will still be created with correct labels and assignment. The user (or their manager) can manually drag them into the correct project board column afterward.
Inputs
Ask the user for these if not provided:
- Pen test PDF report path: Path to the downloaded Aikido detailed auditor report PDF
- PT ID(s): Which PT-* findings to create tickets for (specific IDs, a range, or "all")
- Team: Which team owns the findings (determines labels, project board, and parent story)
- Assignee: GitHub username to assign the tickets to
- Parent story: The confidential issue number that tracks these findings (e.g., #16715)
Teams and project boards
If the user specifies a team not listed here, ask for the team label and project URL/number.
Ticket format
Title
Aikido-PT-{number} [{SEVERITY}]: {concise title from the finding}
Body structure
## {concise title}
{1-2 sentence explanation of what is wrong}
See full details below.
### Attack path
{Concise but complete description of how an attacker exploits this vulnerability}
### Fix
**Option 1 (recommended):** {Best fix approach described concisely}
{Only add Option 2, Option 3 etc. if there are genuinely different viable approaches. If one fix is clearly best, only list that one.}
---
**Aikido ref:** PT-{number} | CVSS {score} | `{primary affected file}`
**Parent story:** #{parent_story_number}
---
<details>
<summary>Aikido pen test details (PT-{number})</summary>
{Full content from the Aikido PDF report for this finding, including:}
### Description
{original description}
### Business impact
{original business impact}
### How to exploit
{all exploit steps with code blocks}
### Remediation
{all remediation bullets from the report}
### References
{CVSS score and vector}
</details>
Process
-
Read the finding from the pen test PDF report. Locate each finding by its PT-{N} header rather than guessing page numbers. Scan for 2.3.X PT-{N} - {Title} headers in the detailed findings section (starts around page 15). Read pages in chunks to find the right section.
-
Write the ticket body following the format above:
- The top section (title, explanation, attack path, fix) is YOUR synthesis of the finding, written concisely
- The foldable
<details> section at the bottom contains the ORIGINAL Aikido report content verbatim
-
Write the body to a temp file and create the issue:
cat > /tmp/aikido-pt-{N}.md << 'BODY'
{body content}
BODY
gh issue create --repo fleetdm/confidential \
--title "Aikido-PT-{N} [{SEVERITY}]: {title}" \
--assignee {assignee} \
--label "bug,~security,~vulnerability-management,{team_label},p3" \
--body-file /tmp/aikido-pt-{N}.md
-
Add to the correct project board and set status to Ready:
PROJECT_NODE_ID=$(gh api graphql -f query='{ organization(login: "fleetdm") { projectV2(number: {project_number}) { id } } }' | jq -r '.data.organization.projectV2.id')
ITEM_ID=$(gh project item-add {project_number} --owner fleetdm --url {issue_url} --format json | jq -r '.id')
READY_INFO=$(gh project field-list {project_number} --owner fleetdm --format json | jq '.fields[] | select(.name == "Status")')
STATUS_FIELD_ID=$(echo "$READY_INFO" | jq -r '.id')
READY_OPTION_ID=$(echo "$READY_INFO" | jq -r '.options[] | select(.name | test("Ready")) | .id')
gh project item-edit --project-id $PROJECT_NODE_ID --id $ITEM_ID --field-id $STATUS_FIELD_ID --single-select-option-id $READY_OPTION_ID
If the project scope is not available, inform the user that tickets were created but need to be manually added to the project board.
-
Report the created issue URL to the user.
Batch creation
When creating many tickets at once, delegate to subagents via the Agent tool. Launch the whole batch of subagents in a single message so findings are processed concurrently.
Split the requested findings into groups of ~5-7 and spawn one subagent per group (aim for 5-6 subagents at a time). Give each subagent its assigned PT-{N} list and instruct it to:
- Locate each finding by its
PT-{N} header and read those pages of the PDF
- Draft the ticket body and write it to a temp file
- Create the issue with
--body-file, correct labels, and assignee
- Add each issue to the project board and set status to Ready
- Return the created issue URLs (and any failures) so the run is resumable
Important notes
- All tickets go in
fleetdm/confidential (private repo) since they contain security findings
- Always use
p3 priority label unless the user specifies otherwise
- Always use
bug label (not story)
- The foldable
<details> section preserves the full Aikido evidence for reference
- When creating many tickets, read the PDF pages for each finding to get accurate details
- For the Fix section: if one fix is clearly the best, only list that one. Only list multiple options if there are genuinely different viable approaches
- Fetch project field IDs at runtime rather than hardcoding, since they can change across projects