blob: 7df5bebaba138d8679422ad67d1a55dd988beca4 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Technical documentation
Documentation for the security issue dashboard.
* [`schemas/case.schema.json`](schemas/case.schema.json):
JSON Schema for the case files that back the dashboard.
* [Input data](#input-data):
how those files are laid out and what the dashboard reads from them.
## Input data
The dashboard is read-only:
it renders a directory tree of JSON files and never writes to it.
`data_dir` in `config.yaml` points at that tree.
One file is one case: a single reported security issue.
It lists every email linked to that issue —
the original report,
any duplicate reports of the same issue,
and follow-ups that are not part of the same mail thread.
The file **contents** are header metadata only (no message bodies)
and are described by [`schemas/case.schema.json`](schemas/case.schema.json).
The file **path and name** carry the classification,
as described below.
### Directory layout
Every project has a directory named after its PMC:
```
<data_dir>/
<project>/*.json
```
A case leaves the project directory once it is resolved,
or once it turns out not to be an issue.
It then disappears from the project page,
and stops adding to the project's debt in the statistics
from the date of its last email onwards —
or, if its CVE is listed in `old_cve_close_dates`, from the date given there.
ASF Security moves closed cases into one of two trees that mirror the per-project layout:
```
<data_dir>/
zzz-resolved/<project>/*.json accepted cases, once resolved
zzz-non-issue/<project>/*.json rejected cases
archive/ older closed cases, in the same two trees
```
Only the statistics read these trees
to find out when each case was closed:
the date of its last email,
not counting follow-ups sent after its CVE was published.
To reopen a case, ASF Security moves its file back into the project directory,
and the dashboard shows it as open again.
### File names
The name of a case file records how the case was classified.
Free-form text describing the issue is wrapped in optional tokens:
```
[CVE-<id> [CVE-<id> …] | YYYY-MM-DD] [<subproject>] [<issue number>] <free text> [wf <state>].json
```
All of this follows the default process for handling a possible vulnerability,
[documented for committers](https://www.apache.org/security/committers.html#possible).
#### Standing labels
A file named `aaa-<topic>.json` or `zzz-<topic>.json` is not a case
but a standing label of the project,
collecting every email on one recurring topic.
The `aaa-` labels gather reports that are not handled as cases:
for example `aaa-dependencies` for questions about dependencies,
`aaa-support` for support requests,
`aaa-glasswing` for the reports of the Glasswing scans
and `aaa-non-fwd` for emails that were not forwarded to the project.
The `zzz-` labels hold discussions with the project team that concern no open case,
such as `zzz-admin`.
The set of topics is not fixed;
the prefixes merely sort these labels before and after the cases.
The dashboard does not treat them specially.
While such a file sits in the project directory,
the project page shows it as an untriaged case named after its first email,
and the statistics count it as open;
once it is moved to a closed tree, the statistics ignore it.
#### Prefix
Once the case has CVE IDs
([allocated by the security team](https://www.apache.org/security/committers.html#ids)),
the name starts with them —
repeated, when a single case covers more than one.
That also marks the case as confirmed on the project page:
it has been accepted and is being
[resolved](https://www.apache.org/security/committers.html#resolve).
Every other case is named after `YYYY-MM-DD`,
the day its first report came in.
The date is informational:
the dashboard takes the dates it displays from the emails, not from the name.
#### Subproject
For the PMCs listed in `pmcs_with_subprojects`,
the token after the prefix names the subproject the issue belongs to.
#### Issue number
The next token, when it is a number,
is the identifier of the issue tracking the case:
a Jira issue for the PMCs listed in `pmcs_using_jira`,
a GitHub issue for those listed in `pmcs_using_github`.
Such an issue must not reveal that the case is security-related:
either it is private,
or it is public and describes the problem as an ordinary bug —
see [Work in private](https://www.apache.org/security/committers.html#work-in-private).
#### State
A `wf <state>` suffix says what the case is waiting for:
| State | Meaning |
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `wf cve-allocation` | The report has been **accepted**, but no CVE ID has been [allocated](https://www.apache.org/security/committers.html#ids) yet. |
| `wf non-issue-feedback` | The report has been **rejected**, and the reporter still has to be [told why](https://www.apache.org/security/committers.html#acknowledge). |
| `wf non-issue-docs` | **Rejected** as a vulnerability, but the documentation should be improved. |
| `wf non-issue-upstream` | **Rejected**: the flaw is in an upstream component and has to be fixed, or avoided, there. |
| `wf disclosure` | The fix has been released and the [announcement](https://www.apache.org/security/committers.html#announce) still has to go out. |
| anything else | Shown as "waiting for …". |
A case with neither CVE IDs nor a `wf` suffix is untriaged:
it is waiting for the project team to
[investigate the report and accept or reject it](https://www.apache.org/security/committers.html#acknowledge).
### Contents
Beyond what the schema can express:
* Emails should be ordered oldest first.
The dashboard takes the first entry as the moment the issue was reported
and — for a case that has been closed — the last as the moment it was closed.
* An empty array is not an error but has no meaning to the dashboard:
it is skipped, with a warning on the server log.
* `subj`, `from`, `to`, `cc` and `reply_to` hold raw header values,
exactly as they appeared in the message.
They may be RFC 2047 encoded words and are decoded,
and in the case of the title sanitized,
before being rendered.
* Only `mailtime`, `subj`, `from`, `to` and `message_id` are required.
`cc` and `reply_to` are read when a producer supplies them:
`cc` helps identify the mailing list an email belongs to,
and `reply_to` recovers the reporter behind a sender rewritten by a list.
### Validating
With [`check-jsonschema`](https://pypi.org/project/check-jsonschema/):
```sh
find "$DATA_DIR" -name '*.json' -print0 |
xargs -0 uvx check-jsonschema --schemafile docs/schemas/case.schema.json
```