Skip to content

Add keycloak-private CVE triage dashboard with severity-based SLAs#36

Open
abstractj wants to merge 1 commit intokeycloak:mainfrom
abstractj:keycloak-private
Open

Add keycloak-private CVE triage dashboard with severity-based SLAs#36
abstractj wants to merge 1 commit intokeycloak:mainfrom
abstractj:keycloak-private

Conversation

@abstractj
Copy link

  • Adds a new "CVEs per team - keycloak-private" section to the bugs dashboard showing triage and open CVE counts per team from the keycloak/keycloak-private repository
  • Private issues are fetched in-memory via GITHUB_PRIVATE_TOKEN PAT — data is never persisted to disk to prevent accidental leakage of embargoed CVE information
  • Section is only rendered in local/internal builds (!publish mode) and hidden from the public GitHub Pages deployment

Proposal

image

Considerations

  • The implementation uses a dedicated PAT to access the private repository, but if the app is installed on the keycloak org and granted access to keycloak-private. Probably this will become redundant.
  • For the private repo we do not generate data.json considering that we don't want sensitive data there.
  • Probably those SLAs for fixing are too agressive. We can focus only on the "Triage" and "Triage Overdue"

Triage SLA Rules by Severity

Issues with status/triage in keycloak-private are evaluated for overdue status based on their severity label:

Severity SLA Calculation
severity/important 2 business days Weekends excluded
severity/moderate 7 business days Weekends excluded
severity/low 15 calendar days Weekends included
No severity label 2 business days Defaults to most aggressive threshold

Business days exclude Saturdays and Sundays. The rationale: important and moderate CVEs require active team attention during working hours, so weekend days are not counted against the SLA. Low severity items have a relaxed 3-week window where elapsed calendar time is sufficient.

A single overdue issue at any severity level is enough to flag the "Triage Overdue" cell as red (error=1).

Security measures

  • GitHubData.privateIssues is @JsonIgnore on field, getter, and setter — never serialized to data.json
  • PrivateIssuesLoader fetches directly from GitHub API into JVM heap — no intermediate file
  • Dashboard skips the private API call entirely when -Dpublish is set
  • FreeMarker template guards with <#if !publish && privateCveTeamStats?has_content>

Testing it

  • Export GITHUB_PRIVATE_TOKEN with repo scope and run mvn clean install exec:java -Pdashboard — verify "CVEs per team - keycloak-private" section appears in docs/bugs.html
  • Run with -Dpublish flag — verify section is hidden even if token is present
  • Inspect data.json after running -Pgithub with the token — check if no privateIssues key exists
  • Verify triage overdue thresholds match the SLA table above

- Adds a new "CVEs per team - keycloak-private" section to the bugs
dashboard showing triage and open CVE counts per team from the
keycloak/keycloak-private repository
- Private issues are fetched in-memory via GITHUB_PRIVATE_TOKEN PAT —
data is never persisted to disk to prevent accidental leakage of
embargoed CVE information
- Section is only rendered in local/internal builds (!publish mode)
and hidden from the public GitHub Pages deployment

Signed-off-by: Bruno Oliveira da Silva <bruno@abstractj.com>
@ahus1
Copy link
Member

ahus1 commented Mar 19, 2026

Thank you for preparing this PR.

Section is only rendered in local/internal builds (!publish mode) and hidden from the public GitHub Pages deployment

How would this dashboard help in our day-to-day workflows? How would people know about the their team's status? Is there another place where we can publish the data to (Google Doc? Google Sheet?)

Private issues are fetched in-memory via GITHUB_PRIVATE_TOKEN PAT — data is never persisted to disk to prevent accidental leakage of embargoed CVE information

Is this then supposed to run locally on my machine? If it would run on CI, it would be important that the information is also not logged.

@stianst
Copy link
Contributor

stianst commented Mar 19, 2026

As long as this requires a local build this is a no-go, so that needs to be figured out before we go ahead with this.

I'm probably okay with just making the counts of open issues publicly available on keycloak.org/dashboard. An alternative option could be to make the whole dashboard private by simply converting the repo to private and instead of generating html/webpage we'd just have some generated markdown files.

As there are different SLAs for different severities there should be individual columns per-severity.

@abstractj
Copy link
Author

Thank you for preparing this PR.

Section is only rendered in local/internal builds (!publish mode) and hidden from the public GitHub Pages deployment

That's a good catch and my fault while playing with it locally. That's no problem about removing those safeguards.

How would this dashboard help in our day-to-day workflows? How would people know about the their team's status? Is there another place where we can publish the data to (Google Doc? Google Sheet?)

I want us to use Keycloak Bugs dashboard and the single place for people to look and I can share with you some context. So let's answer your questions one by one.

  1. How would this dashboard help in our day-to-day workflows?

Today our team is doing a great job and things are starting to shape up with CVEs, but we are not quite there yet. We have so many communication channels that it is not unusual for people to miss notifications from GitHub. On the daily basis people can incorporate the bugs dashboard as part of team's routine to they can review during weekly meetings, instead of multiple fragmented pings on github issues.

Even though every team member is able to access their GH inbox and check for the notification that does not give us a full overview about the current status of things. In this way, we ensure that this will become part of team's routine, and also part of weekly meetings.

The intent is to reduce the workload in the security team which today is responsible to chase people and ask them to respond. We will introduce accountability and ownership as we did for the issues in the upstream.

Private issues are fetched in-memory via GITHUB_PRIVATE_TOKEN PAT — data is never persisted to disk to prevent accidental leakage of embargoed CVE information

Is this then supposed to run locally on my machine? If it would run on CI, it would be important that the information is also not logged.

That was a failure on my end. Data will be dynamically fetched and never logged into data.json to prevent disclosure.

@abstractj
Copy link
Author

As long as this requires a local build this is a no-go, so that needs to be figured out before we go ahead with this.

You are damn right, as mentioned before, it was a failure on my end.

I'm probably okay with just making the counts of open issues publicly available on keycloak.org/dashboard. An alternative option could be to make the whole dashboard private by simply converting the repo to private and instead of generating html/webpage we'd just have some generated markdown files.

From my standpoint if we agree to keep it as is, it should be alright. People do not have access to our private repo, also they won't have any idea about how many are critical, high, moderate, low. So the less information we provide, the better, we only need the counting and the information when miss the SLA.

As there are different SLAs for different severities there should be individual columns per-severity.

@stianst I'd avoid that. The only thing that matters is the counting and when people miss the SLA. The less we disclose any information the better, we only need to raise awareness for the team and provide them visibility about their issues. In the end, vulnerabilities are bugs with higher priority.

About the PAT, please let me know what is the best approach.

@stianst @ahus1 after your feedback, I will iterate over those changes.

@ahus1
Copy link
Member

ahus1 commented Mar 20, 2026

@abstractj - thank you for your answers. My question "How would this dashboard help in our day-to-day workflows?" was due to my confusion where the numbers would be published. If they are published to a central location (and no-one would need to build it locally), this is all great and aligned.

+100 for having a centrally published dashboard, it would make the work so much easier.

When publishing the overdue triage numbers, I was first thinking about only publishing only the overdue numbers. But that's not so helpful as it doesn't allow you to click on a "green" number and stay on track with the triaging.

I support Bruno to not break down the dashboard by severity when we make it public - at least not until we figure out that we really need it.

@abstractj - Not sure if you aware and when you are building a link for users to jump to the overdue items and it you want have a more complex filter for the different severities: There GitHub now supports OR and AND, and also nesting. See https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/filtering-and-searching-issues-and-pull-requests#using-boolean-operators

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants