Aikido triage
bb-huge π€ , Personal bug bounty findings hub and bug bounty orchestration for multiple agents
npx -y skills add ShulkwiSEC/bb-huge --skill aikido-triageAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 18 stars18 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Triages an Aikido security findings CSV against a local codebase. For each finding, reads the flagged file, traces the code path, and verdicts it as KEEP OPEN or CLOSE with a specific reason. Outputs a reviewed CSV and a self-contained HTML evidence report. Run this at the end of a pentest when an Aikido CSV is available.
SKILL.md
12.2 KB, ~2.9k tokens by cl100k_base, as published. Nobody here has run it
Aikido Findings Triage Workflow
You are triaging an Aikido SAST/SCA/secret-scanning CSV export against a local codebase. Your job is to read every finding, investigate the flagged code, and verdict each one with evidence. At the end you produce a reviewed CSV and a self-contained HTML report.
Do not guess. Read the actual files before rendering a verdict.
Arguments
Parse from the user's invocation:
CSV_PATHβ path to the Aikido CSV exportCODEBASE_PATHβ absolute path to the local codebase to investigate
If either argument is missing, ask the user before proceeding.
Phase 1 β Parse the CSV
-
Read
CSV_PATHwith the Read tool. -
Parse every row. Key columns to extract per finding:
aikido_issue_idβ unique IDtypeβsast|open_source|leaked_secret|eolseverityβ critical / high / medium / lowaffected_fileβ relative path to the flagged filerelated_cveβ CVE or advisory ID (may be empty)ruleβ rule name that firedstart_line/end_lineβ flagged line rangeinstalled_version/patched_versionβ for SCA findingsaffected_packageβ for SCA/EOL findings
-
Group findings by
typeso you can batch-investigate efficiently.
Phase 2 β Investigate Each Finding
Work through findings type by type. For each one, read the flagged file and apply the investigation playbook for that type.
2a β leaked_secret findings
Step 1 β Does the file exist?
Use the Read tool on CODEBASE_PATH/affected_file. If the file does not exist:
β Verdict: CLOSE β File Removed
β Note: "File does not exist at HEAD. Finding references removed code in git history."
β Move on. Do not investigate further.
Step 2 β Read the flagged lines.
Read start_line to end_line (expand by Β±3 lines for context).
Apply these patterns:
| What you see | Verdict |
|---|---|
ENV.fetch(...), ENV[...], ENV.fetch(..., nil) | CLOSE β False Positive (env var read) |
${{ secrets.* }} (GitHub Actions) | CLOSE β False Positive (GH Actions secret) |
${VARIABLE_NAME} in .npmrc/.env.example | CLOSE β False Positive (env var placeholder) |
--mount=type=secret in Dockerfile | CLOSE β False Positive (Docker build secret) |
| A long regex, UA string, or binary-looking data | CLOSE β False Positive (pattern mismatch) |
| An actual hardcoded token/key/password string | KEEP OPEN β check liveness if possible |
| A real URL with embedded credentials (user:pass@host) | KEEP OPEN |
For sidekiq-sensitive-url rule: check whether the flagged content is a Redis URL with credentials or just a gem declaration. Almost always a false positive in Gemfile/Gemfile.lock.
Step 3 β If hardcoded secret found:
- Note the exact line and masked value
- Check if
secret_livenesscolumn saysactiveβ if so, escalate to critical - Verdict: KEEP OPEN β Hardcoded Secret
2b β sast findings
Step 1 β Read the flagged file and lines.
Read CODEBASE_PATH/affected_file at start_line Β± 10 lines of context.
Step 2 β Apply rule-specific investigation:
NoSQL injection (NoSQL injection attack possible)
- Trace what the flagged call actually does. Follow the call chain:
- What does the flagged function call?
- Does it call a NoSQL driver (MongoDB, Redis query, Elasticsearch, Mongoose)?
- Or does it call an HTTP client (axios, fetch, HTTParty)?
- Check
CODEBASE_PATH/GemfileandCODEBASE_PATH/package.jsonfor NoSQL drivers. - If no NoSQL driver exists in the stack: CLOSE β False Positive
SQL injection (SQL injection, string-based query concatenation)
- Read the flagged method. Check:
- Is there actual string interpolation into a raw SQL string? (
"... #{variable}") - What is the type of the interpolated variable? (Ruby
Date,Integer,String?) - Is it executed via
select_all,execute, orconnection.exec? - Trace the variable back to its source β is it user-controlled?
- Is there actual string interpolation into a raw SQL string? (
- If raw interpolation exists but type coercion removes the injection vector: KEEP OPEN β Medium (dangerous pattern, mitigated)
- If raw interpolation with no type coercion on a user-controlled string: KEEP OPEN β High
- If interpolation is of a hardcoded or server-side-only value: CLOSE β False Positive
Unpinned GitHub Actions (3rd party Github Actions should be pinned)
- Read the workflow file at the flagged line.
- Check if
uses:has a SHA pin (@abc123def...) or only a tag (@v2,@main). - Tag-pinned or branch-pinned: KEEP OPEN β Real Finding
- SHA-pinned: CLOSE β False Positive
NODE_AUTH_TOKEN (Use of NODE_AUTH_TOKEN)
- Read the flagged line. If value is
${{ secrets.* }}: CLOSE β False Positive - If hardcoded token value: KEEP OPEN
Other SAST rules
- Read the flagged lines. Apply judgment: is the finding actually present in the code, or is it a pattern-match on a non-vulnerable construct? Document what you found.
2c β open_source / SCA findings
For each SCA finding:
Step 1 β Identify the vulnerable function from the CVE/advisory.
Use your knowledge of the CVE to identify what specific function/class is vulnerable. If you need more detail, use /analyze-cve to do a full dataflow trace.
Step 2 β Check if the package is used in application source code.
Use Grep to search for imports of the package in the application source:
- JS/TS:
import .* from 'package-name'orrequire('package-name') - Ruby:
require 'package'or check Gemfile for direct gem declaration vs transitive
Step 3 β Apply these verdicts:
| Scenario | Verdict |
|---|---|
| Package not imported anywhere in app source (transitive/build-only) | CLOSE β Not Exploitable |
| Package imported but vulnerable function never called | CLOSE β Not Exploitable |
| Package imported, vulnerable function called, no user input reaches it | CLOSE β Not Exploitable |
| Package imported, vulnerable function called with user-controlled input, no sanitization | KEEP OPEN |
| devDependency only (webpack-dev-server, jest, babel plugins) | CLOSE β Not Exploitable |
Step 4 β For complex SCA findings with user-reachable code paths:
Run /analyze-cve skill to do a full dataflow trace before rendering the verdict.
2d β eol findings
- Read the version file (
.ruby-version, checkpackage.jsonfor the framework version). - Confirm the actual installed version.
- Look up the EOL date from your knowledge.
- If EOL date has passed: KEEP OPEN β Real Finding
- Document the EOL date and recommended upgrade path.
Phase 3 β Assign Final Verdicts
For every finding, assign:
| Field | Values |
|---|---|
recommended_action | KEEP OPEN or CLOSE |
close_category | False Positive / File Removed / Not Exploitable / Real Finding |
analyst_notes | One sentence β what you found and why |
evidence | Specific file:line references and code fragments proving the verdict |
Phase 4 β Output the Reviewed CSV
Write a new CSV to the same directory as the input CSV, named <original-name>-reviewed.csv.
Column set (lean β do not include empty cloud/VM/container columns from the original):
aikido_issue_id, type, severity, affected_file, related_cve, rule, start_line,
recommended_action, close_category, analyst_notes, evidence
Rules:
- Wrap any field containing commas in double quotes
- Use
|(space-pipe-space) as separator within theevidencefield β never commas - Keep
analyst_notesto one sentence with no commas - Every row must have exactly 11 fields
Phase 5 β Generate the HTML Evidence Report
Write a self-contained HTML file to the same directory as the CSV, named <project-name>-security-review.html.
HTML structure (follow this exactly)
1. <header> β project name, analyst, date, branch/source
2. Stats bar β total / close / keep open / false positive / file removed / not exploitable counts
3. Jump nav β anchor links to each section
4. Full summary table β all findings, colour-coded by severity and action
5. KEEP OPEN section β one detailed card per finding with full code evidence
6. FALSE POSITIVES section β one card per finding with evidence showing why it's a FP
7. FILE REMOVED section β simple table (no code to show)
8. NOT EXPLOITABLE section β one card per finding with code evidence
9. <footer>
Card anatomy (for sections 5, 6, 8)
Each finding card must contain:
- Finding ID, severity badge, type, file:line
recommended_actionbadge- Verdict paragraph β plain English explanation
- Fix (for KEEP OPEN only) β exact command or code change required
- Evidence code block β the actual lines from the file, syntax-highlighted, with line numbers and comments explaining what is or isn't vulnerable
Code block style
Use <pre> blocks with dark background. Add inline <span> highlights:
class="highlight"β red, for the vulnerable or suspicious lineclass="ok"β green, for the safe/correct patternclass="comment"β gray, for explanatory annotations added by the analyst
Severity badge colours
- Critical β red background
- High β orange background
- Medium β yellow background
- Low β green background
Action badge colours
- KEEP OPEN β red
- CLOSE β green
Close category badge colours
- False Positive β blue
- File Removed β purple
- Not Exploitable β green
- Real Finding β red
CSS
Embed all CSS in a <style> block in <head>. No external dependencies β the file must be fully self-contained and openable offline.
Use a clean, professional light theme. Monospace font for file paths and code. System font stack for prose.
Phase 6 β Summary to User
After writing both files, output a short summary:
## Triage complete
**CSV:** /path/to/reviewed.csv
**Report:** /path/to/report.html
| Action | Count |
|------------|-------|
| KEEP OPEN | N |
| CLOSE | N |
| β False Positive | N |
| β File Removed | N |
| β Not Exploitable| N |
**Keep open findings:**
- [ID] severity β short description
- ...
Rules
- Read every flagged file before rendering a verdict. Never close a finding based on the rule name alone.
- Batch independent reads in parallel β read multiple files in one response when they don't depend on each other.
- Use
/analyze-cvefor complex SCA findings where user input may reach the vulnerable function. Do not skip this. - For
leaked_secretfindings on files that exist: always read the exact flagged lines. Do not assume it's a false positive without looking. - Preserve line numbers in all code snippets β use the actual line numbers from the source file.
- Do not fabricate code. Only quote lines you have actually read from the file.
- Write the HTML last β after all verdicts are finalized, so the report is complete.
- Do not include empty columns in the output CSV β strip the cloud/VM/container/ARN columns from the original Aikido export.
Finding type quick reference
Aikido type | Primary check | Most common outcome |
|---|---|---|
leaked_secret | Does file exist? Then read flagged lines. | False Positive or File Removed |
sast β NoSQL | Trace call chain to actual DB driver | Almost always False Positive if MySQL/Postgres stack |
sast β SQLi | Read raw SQL method, check interpolation + type coercion | Medium finding, often partially mitigated |
sast β Actions | Check for SHA pin vs tag pin | Real finding if tag-pinned |
open_source | Grep app source for import, check if vulnerable function used | Often Not Exploitable (transitive/build-only) |
eol | Read version file, check EOL date | Always a real finding if EOL date passed |