Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class “security advisory” support to the seclab taskflow ecosystem by introducing a new MCP server/toolbox for fetching repository security advisories, wiring it into audit taskflows, and making it optionally runnable from the audit script.
Changes:
- Introduce a new
security_advisoriesMCP server plus toolbox definition. - Add a new audit taskflow to fetch advisories, and update existing audit prompts to incorporate advisories from memcache.
- Add a
--advisoryflag to the audit runner to optionally fetch advisories as part of the pipeline.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/seclab_taskflows/toolboxes/security_advisories.yaml |
Adds toolbox wiring for the new security advisories MCP server. |
src/seclab_taskflows/taskflows/audit/filter_severity.yaml |
Aligns SPDX header format with repo convention. |
src/seclab_taskflows/taskflows/audit/fetch_security_advisories.yaml |
New taskflow to fetch/review advisories (header format currently inconsistent). |
src/seclab_taskflows/taskflows/audit/classify_application_local.yaml |
Updates classification prompt to consider advisories from memcache; adds required toolboxes. |
src/seclab_taskflows/taskflows/audit/audit_issue_local_iter.yaml |
Updates audit prompt to consider advisories from memcache; adds required toolboxes. |
src/seclab_taskflows/personalities/web_application_security_expert.yaml |
Makes the new toolbox available to the security expert personality. |
src/seclab_taskflows/mcp_servers/security_advisories.py |
Implements advisory fetch/filter logic and stores results into memcache. |
scripts/audit/run_audit.sh |
Adds --advisory flag to optionally fetch advisories during audits. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/seclab_taskflows/taskflows/audit/fetch_security_advisories.yaml
Outdated
Show resolved
Hide resolved
….yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
I think this is duplicating some of the code that's already in ghsa.py |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/seclab_taskflows/mcp_servers/security_advisories.py:108
- The pagination logic could potentially result in an infinite loop if the API keeps returning exactly 100 results indefinitely. Consider adding a maximum page limit as a safety measure, or tracking if we've seen duplicate results across pages. The existing ghsa.py server handles this more robustly by using the Link header from the API response to determine if there's a next page.
while True:
url = f"https://api.github.com/repos/{owner}/{repo}/security-advisories?per_page=100&page={page}"
headers = {
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {GH_TOKEN}",
"X-GitHub-Api-Version": "2022-11-28",
}
try:
async with httpx.AsyncClient() as client:
r = await client.get(url, headers=headers)
r.raise_for_status()
data = r.text
page_advisories = json.loads(data)
if not page_advisories:
break
advisories.extend(page_advisories)
if len(page_advisories) < 100:
break
page += 1
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/seclab_taskflows/taskflows/audit/classify_application_local.yaml
Outdated
Show resolved
Hide resolved
|
|
||
| Based on this, determine whether the component is likely to have security problems. | ||
|
|
||
| ## Known Security Advisories for this Repository |
There was a problem hiding this comment.
Maybe pull this out and turn it into a reusable prompt and include it in this and the other taskflow? Use this version is better because it instructs the LLM to skip the advisory analysis if advisory isn't found.
There was a problem hiding this comment.
Sure, makes sense. Let me know if it's what you were thinking.
src/seclab_taskflows/taskflows/audit/audit_issue_local_iter.yaml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - seclab_taskflows.toolboxes.local_file_viewer | ||
| - seclab_taskflows.toolboxes.gh_file_viewer |
There was a problem hiding this comment.
fetch_security_advisories is only describing fetching advisories + writing to memcache, but the task grants local_file_viewer and gh_file_viewer toolboxes as well. If they aren’t needed for this flow, removing them reduces tool surface area and avoids unnecessary tool calls/context overhead.
| - seclab_taskflows.toolboxes.local_file_viewer | |
| - seclab_taskflows.toolboxes.gh_file_viewer |
| user_prompt: | | ||
| Fetch all GitHub Security Advisories (GHSAs) for the repo {{ globals.repo }}. | ||
|
|
||
| After fetching, store the list of advisories in memcache under the key 'security_advisories_{{ globals.repo }}'. | ||
|
|
||
| Provide a summary of: | ||
| 1. How many advisories were found | ||
| 2. The severity levels of the advisories | ||
| 3. Key recommendations for addressing them |
There was a problem hiding this comment.
Downstream prompts expect to be able to reason about “how many advisories were found”, but this taskflow doesn’t define a stable memcache value format (e.g., empty list vs error string like “No advisories found.”). Consider normalizing what gets stored (e.g., always JSON list; store [] on no results; store a structured error separately) so later steps can reliably count/skip advisories.
| prompt: | | ||
| ## Known Security Advisories for this Repository | ||
|
|
||
| Fetch the security advisories for {{ globals.repo }} from memcache (stored under the key 'security_advisories_{{ globals.repo }}'). If the value in the memcache is null, clearly state so and skip advisory analysis. Otherwise, state how many advisories were found. |
There was a problem hiding this comment.
This prompt only checks for a null memcache value, but the GHSA fetch tool can also yield non-null sentinel strings (e.g. “No advisories found.”) or error strings. Handle those cases explicitly (treat as empty/skip advisory analysis), otherwise later steps may incorrectly claim advisories exist or fail to report a count.
| Fetch the security advisories for {{ globals.repo }} from memcache (stored under the key 'security_advisories_{{ globals.repo }}'). If the value in the memcache is null, clearly state so and skip advisory analysis. Otherwise, state how many advisories were found. | |
| Fetch the security advisories for {{ globals.repo }} from memcache (stored under the key 'security_advisories_{{ globals.repo }}'). If the value in the memcache is null, a sentinel string indicating no advisories (for example, "No advisories found."), or an error message, clearly state that no advisories are available and skip advisory analysis. Otherwise, state how many advisories were found. |
| {% include 'seclab_taskflows.prompts.audit.known_security_advisories' %} | ||
|
|
||
| {% include 'seclab_taskflows.prompts.audit.audit_issue' %} |
There was a problem hiding this comment.
Including the full “known security advisories” section inside a repeat_prompt audit loop means the same advisories may be fetched/summarized for every issue, increasing token usage and prompt size. Consider fetching/summarizing advisories once (outside the loop) and storing a short summary in memcache, then referencing that summary here.
| *) | ||
| echo "Unknown option: $1" | ||
| exit 1 | ||
| ;; |
There was a problem hiding this comment.
Unknown option handling prints to stdout and doesn’t show usage/help. Prefer writing option parse errors to stderr and including the usage string (or supporting --help) to make failures easier to diagnose in scripts/CI.
| __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
|
|
||
| ${__dir}/../run_in_docker.sh ${__dir}/run_audit.sh "$1" | ||
| ${__dir}/../run_in_docker.sh ${__dir}/run_audit.sh "$@" |
There was a problem hiding this comment.
Consider quoting the script paths when invoking run_in_docker.sh/run_audit.sh (e.g., "${__dir}/../run_in_docker.sh") to avoid issues if the repo path contains spaces.
| ${__dir}/../run_in_docker.sh ${__dir}/run_audit.sh "$@" | |
| "${__dir}/../run_in_docker.sh" "${__dir}/run_audit.sh" "$@" |
|
@anticomputer Is there a way to use the Jinja syntax to make it so that the prompt related to fetching and reviewing advisories is only included when the command line is passed? |
I'll take a poke now |
Implemented using the -g logic we use for repo passing as well in 9ec009c cc @m-y-mo @Kwstubbs can you test to make sure that works for your intended logic still? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| If fetching is successful, store the list of advisories in memcache under the key 'security_advisories_{{ globals.repo }}'. | ||
|
|
||
| If one ore more advisories are found, provide a summary of the findings including: |
There was a problem hiding this comment.
Typo in line 29: "one ore more" should be "one or more".
| If one ore more advisories are found, provide a summary of the findings including: | |
| If one or more advisories are found, provide a summary of the findings including: |
Pass --advisory to run_audit.sh to add advisory support to results.