Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ but container releases use the upstream-derived format documented in
- Fixed a race in the reload test that read `/proc/PID/status` for a worker
that had already exited, which aborted the listing instead of skipping the
vanished process.
- Resolved the Application Server SRG, pinning V4R5 by digest and recording it
as not applicable to this component: 27 of its 137 rules presuppose a
management interface or hosted applications and 18 refer to accounts, none of
which exist here. Pinned rather than dropped so the determination stays tied
to the revision it was made against.
- Recorded why the DISA Container Platform SRG cannot be retrieved: V2R1 is
officially released and its filename follows DISA's convention, but it is no
longer served from the public download path, and the download index is now a
JavaScript-rendered portal whose HTML contains no download links. It stays
unresolved with the release, filename, and finding recorded, so the search is
not repeated.
- Established the requirement-source register, pinning the 800-53 Rev 5.2.0
catalogue, its High baseline profile, the DISA Web Server SRG, and the RHEL 9
STIG by digest, and recording the Container Platform SRG, Application Server
Expand Down
24 changes: 12 additions & 12 deletions artifacts/requirement-sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
"id": "disa-container-platform-srg",
"publisher": "Defense Information Systems Agency",
"title": "Container Platform Security Requirements Guide",
"release": null,
"released_on": null,
"release": "V2R1",
"released_on": "2024-07-24",
"retrieved_on": null,
"url": null,
"sha256": null,
Expand All @@ -81,23 +81,23 @@
"role": "cross-reference",
"license": "US Government work; redistribution terms stated in the package",
"redistributable": false,
"notes": "Named in the roadmap but not located at a predictable URL on 2026-09-18. DISA rotates release identifiers in the filename, so the exact current package has to be obtained from the published download index by a person rather than guessed. Blocking for the container-platform cross-reference only; the spine does not depend on it."
"notes": "Officially released as V2R1 on 2024-07-24, and the filename follows DISA's published convention as U_Container_Platform_V2R1_SRG.zip, but it is no longer served from the public download path: that URL returns 404 while U_Web_Server_V3R3_SRG.zip returns 200 from the same directory, so the path and method are sound and the file is not there. The download index cannot be used to locate it either; it is now a JavaScript-rendered portal whose HTML contains no download links, so it cannot be resolved programmatically. Retrieval needs a browser session or the SRG-STIG library compilation. Blocking for the container-platform cross-reference only; the spine does not depend on it."
},
{
"id": "disa-application-server-srg",
"publisher": "Defense Information Systems Agency",
"title": "Application Server Security Requirements Guide",
"release": null,
"released_on": null,
"retrieved_on": null,
"url": null,
"sha256": null,
"size": null,
"status": "unresolved",
"role": "cross-reference",
"release": "V4R5",
"released_on": "2026-07-01",
"retrieved_on": "2026-09-18",
"url": "https://dl.dod.cyber.mil/wp-content/uploads/stigs/zip/U_Application_Server_V4R5_SRG.zip",
"sha256": "ea33d7f18f950e86c9e0cc63835cf8802d319804ac143b2020b1fbac13ff2643",
"size": 1253893,
"status": "pinned",
"role": "not-applicable",
"license": "US Government work; redistribution terms stated in the package",
"redistributable": false,
"notes": "Same situation as the container platform SRG. Applicability is also uncertain: this image serves and proxies HTTP rather than hosting an application runtime, so the web server SRG may be the only applicable one. Decide applicability before pinning."
"notes": "Retrieved and pinned, then assessed as not applicable to this component; see docs/adr/0010-application-server-srg-not-applicable.md. Of its 137 rules, 27 presuppose a management interface or hosted applications and 18 refer to accounts. This image has no management interface, no accounts, and hosts no application, so those rules govern objects that do not exist here; the remainder are stated for a component of this kind by the Web Server SRG, which is the applicable DISA cross-reference. Pinned rather than dropped so the determination is tied to the revision it was made against."
},
{
"id": "cis-benchmark",
Expand Down
7 changes: 7 additions & 0 deletions docs/CONTROL-MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ replaces it, and the difference is then visible rather than silent.
CIS is cited by identifier only. Its terms restrict redistribution, so no
benchmark text is reproduced here.

The Application Server SRG is pinned but carries the role `not-applicable`: it
presupposes a management interface, accounts, and hosted applications, none of
which exist here. The reasoning and the counts behind that are in
[ADR-0010](adr/0010-application-server-srg-not-applicable.md). It is pinned
rather than dropped so the determination stays tied to the revision it was made
against.

## Assessment methods

Every `image-owned` control carries an examine, test, or interview method with
Expand Down
16 changes: 9 additions & 7 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,15 @@ resolved.

### Foundation

- [ ] Resolve the three outstanding sources recorded as unresolved or
unavailable in `artifacts/requirement-sources.json`: the DISA Container
Platform SRG and Application Server SRG need their exact current packages
obtained from the published download index, and the CIS benchmark needs an
account holder to retrieve it and record its digest. Decide whether the
Application Server SRG applies at all, since this image serves and proxies
HTTP rather than hosting an application runtime.
- [ ] Obtain the two sources in `artifacts/requirement-sources.json` that
cannot be retrieved without a person. The DISA Container Platform SRG V2R1 is
no longer served from the public download path and the download index is a
JavaScript-rendered portal with no links in its HTML, so it needs a browser
session or the SRG-STIG library compilation; the CIS benchmark needs an
account holder to retrieve it and record its digest. Neither blocks the
spine. The Application Server SRG applicability question is closed: it is
pinned and assessed not applicable, per
[ADR-0010](adr/0010-application-server-srg-not-applicable.md).
- [ ] Verify the pinned sources against their recorded digests as a scheduled
check, so a replaced DISA package is reported rather than silently mapped
against. The structural checks over the component definition are in place.
Expand Down
113 changes: 113 additions & 0 deletions docs/adr/0010-application-server-srg-not-applicable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
status: accepted
date: 2026-09-18
decision-makers: Joey
---

# Treat the Application Server SRG as not applicable to this component

## Context and Problem Statement

[ADR-0009](0009-control-catalogue-and-baseline.md) settled that DISA SRGs and
STIGs are cross-references attached to the 800-53 spine, and that every source
is pinned by URL, release, and SHA-256 before any mapping is made against it.

The requirement-source register named four DISA cross-references. Two resolved
immediately: the Web Server SRG and the RHEL 9 STIG. Two did not, and were
recorded as `unresolved` with the reason rather than omitted. The register also
recorded an open question about one of them: whether the **Application Server
SRG** applies to this component at all, given that the image serves and proxies
HTTP rather than hosting an application runtime.

That question had been answered by assumption. An SRG is either in scope or it
is not, and an assessor reading the component definition is entitled to know
which, and on what basis. Guessing in either direction is the failure mode:
including an inapplicable SRG manufactures 137 rules of hand-waving, and
excluding an applicable one silently drops a body of guidance.

## Decision Drivers

* The applicability of a cross-reference should be decided from its contents,
not from its title
* An assessor will ask why a named SRG is absent; "we assumed" is not an answer
* A not-applicable determination is a claim in its own right and needs evidence
* The decision must be cheap to reverse if the component's function changes

## Considered Options

* **Map it** — treat the Application Server SRG as a cross-reference alongside
the Web Server SRG, marking individual rules not applicable as they arise
* **Exclude it without pinning** — leave it `unresolved` and out of scope
* **Pin it, and record it as assessed not applicable** — retrieve the package,
fix its identity by digest, read it, and record the determination against
that exact revision

## Decision Outcome

**Pin it, and record it as assessed not applicable.**

The package was retrieved and pinned as `V4R5`, benchmark date 01 Jul 2026,
SHA-256 `ea33d7f1…`, in `artifacts/requirement-sources.json` with
`"role": "not-applicable"`. Pinning a source this project does not map against
looks redundant until the determination is questioned: the digest is what ties
the determination to the revision it was made against.

### The evidence

The V4R5 XCCDF contains 137 rules. Counted across them:

| | |
| --- | --- |
| Rules presupposing a management or administrative interface | 23 |
| Rules presupposing hosted applications | 6 |
| Rules presupposing either | **27** |
| Rules referring to accounts | 18 |

This image has no management interface, no user accounts, and hosts no
application. Those rules are not merely unsatisfied; the objects they govern do
not exist here. The remainder — logging, TLS, session handling — are the
general requirements the **Web Server SRG** states for a component of this
kind, and it states them in terms that match what this image actually is.

The Web Server SRG therefore remains the applicable DISA cross-reference for
this component's function, as the register already recorded.

### Consequences

* Good: the determination cites a revision and a count, so a reader can check it
rather than accept it
* Good: no cross-reference work is spent on a body of guidance whose subject
this component is not
* Good: reversal is cheap. The source is already pinned, so revisiting means
changing a role and authoring mappings, not re-establishing identity
* Bad: a reader scanning the register for DISA coverage sees an
application-server SRG present and may assume it is mapped. The
`not-applicable` role and this ADR are the mitigation, and a structural check
requires the basis to be recorded
* Bad: the determination is made against V4R5 only. If DISA broadens the SRG's
scope in a later release, this must be revisited — which is exactly what
pinning by digest makes visible

### The Container Platform SRG is a different problem

It is not a scope question. The document exists and is officially released —
**V2R1**, 24 July 2024 — and the filename follows DISA's published convention,
`U_Container_Platform_V2R1_SRG.zip`. It is simply no longer served from the
public download path: that URL returns 404 while `U_Web_Server_V3R3_SRG.zip`
returns 200 from the same directory, so the path and method are sound and the
file is genuinely not there.

The download index cannot be used to find its current location either. It is
now a JavaScript-rendered portal whose HTML contains no download links at all,
so it cannot be resolved programmatically.

It therefore stays `unresolved` — with the release, filename, and this finding
recorded, so whoever retrieves it is not repeating the search. It is a missing
cross-reference, not a missing part of the spine, and it blocks nothing.

### Enforcement

`tests/test_control_model.py` requires a source whose role is `not-applicable`
to record the basis for that determination, on the same principle that an
unpinned source must record why it is unpinned: a determination without a
stated reason is indistinguishable from an omission.
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ record says so, because an unenforced decision decays quietly.
| [0007](0007-liveness-independent-of-upstreams.md) | Keep liveness independent of upstream health | accepted |
| [0008](0008-hand-authored-svg-diagrams.md) | Author diagrams as hand-written SVG with no rendering toolchain | accepted |
| [0009](0009-control-catalogue-and-baseline.md) | Map controls against 800-53 High as the spine, with SRG, STIG and CIS as cross-references | accepted |
| [0010](0010-application-server-srg-not-applicable.md) | Treat the Application Server SRG as not applicable to this component | accepted |
12 changes: 12 additions & 0 deletions tests/test_control_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,18 @@ def test_the_spine_and_baseline_are_pinned(self) -> None:
for role in ("spine", "baseline"):
self.assertEqual(by_role[role]["status"], "pinned")

def test_a_source_ruled_not_applicable_records_the_basis(self) -> None:
# Deciding an SRG does not apply is a claim in its own right. Without a
# stated basis it is indistinguishable from having forgotten it.
for source in register()["sources"]:
if source["role"] != "not-applicable":
continue
with self.subTest(source=source["id"]):
self.assertTrue(
(source.get("notes") or "").strip(),
"a source ruled not applicable must record why",
)

def test_a_non_redistributable_source_is_marked_as_such(self) -> None:
for source in register()["sources"]:
with self.subTest(source=source["id"]):
Expand Down
Loading