Everything below is verified against main at the time of writing, and is what
stands between the current tree and a defensible 0.7.0 tag. Ordered by what
changes the security claim, not by effort.
1. find_anchor() has two implementations and no test
src/ob-fp-daemon.c:250 and src/pam_openbastion.c:1774 implement the same
walk, and the daemon's own comment says:
This MUST agree exactly with pam_openbastion's find_sshd_session_ancestor(),
or the module looks for a drop under a key this daemon never wrote.
Nothing verifies that sentence: grep -rl 'find_anchor\|find_sshd_session_ancestor' tests/
returns nothing. A divergence breaks the SSH fingerprint binding silently —
no error at login, the module simply finds no drop — and that binding is what
doc/security/99-risk-reduce.md credits with reducing R-S3 and R-S15.
This is the same class of drift that #254 removed for the systemd units, left
in place on the mechanism whose trust root #249 had just moved.
Acceptance: one test drives both implementations over the same synthetic
/proc ancestry and requires identical output, including the edge cases the
walk defines (depth limit, non-contiguous sshd-session, pid 1). It goes in
tests/mutation/catalogue afterwards, so a future divergence fails rather than
being noticed by reading.
2. src/cache_key.c rejection branches have no test
4cbe85c added them and touched no test file; there is no tests/test_cache_key*.
Six rejected paths are uncovered: not a regular file, not root-owned,
setuid/setgid bits, and group/other permission bits.
It is the only hardening of the 0.7.0 series with no proof, and it corrects a
real branch-nesting bug.
Acceptance: unit tests for each refusal, and a catalogue entry so removing
one fails.
3. Documentation that contradicts the tree
Small, no design decisions, and an evaluator reads these before reading code:
4. A process note in the homologation dossier
Not a defect, a gap in the record. 113 of the 166 commits since v0.6.2 carry a
Claude-Session trailer and 160 are dated across three days. Both are accurate:
this was an AI-assisted campaign with human review at each merge, and the
reviews are recorded on the pull requests.
History will not be rewritten — the SHAs are cited in 99-risk-reduce.md and
in issues, so rewriting would break the traceability it would be meant to
protect. The right answer is therefore to state what happened, in
doc/security/08-dossier-homologation.md alongside the trust assumptions, so an
evaluator's first question ("36 PRs in three days — who reviewed them?") has a
verifiable answer instead of an absence.
5. Decide R-P1 — the actual release gate
The only item here that changes what the product claims.
With pamAccessServerGroups empty — the multi-group configuration the
architecture document recommends — any compromised enrolled host can declare
itself a bastion and obtain vouchers. The upstream fix is merged and unreleased;
allowed_bastions empty still means "accept any" by default, for Ansible
compatibility.
It is documented and assumed, but it is the shipped default. Two honest
positions:
- make the published plugins and
pamAccessAllowedRps a documented release
prerequisite; or
- accept R-P1 explicitly as a residual risk in the dossier, with the acceptance
signed.
Anything between the two is what an evaluator will find first.
Not blocking, and tracked separately: #262 (no test covers the 0.6.0 portal
generation, waiting on a published image).
Raised by a global review of v0.6.2..HEAD; items 1–3 verified against the tree
before filing.
Everything below is verified against
mainat the time of writing, and is whatstands between the current tree and a defensible
0.7.0tag. Ordered by whatchanges the security claim, not by effort.
1.
find_anchor()has two implementations and no testsrc/ob-fp-daemon.c:250andsrc/pam_openbastion.c:1774implement the samewalk, and the daemon's own comment says:
Nothing verifies that sentence:
grep -rl 'find_anchor\|find_sshd_session_ancestor' tests/returns nothing. A divergence breaks the SSH fingerprint binding silently —
no error at login, the module simply finds no drop — and that binding is what
doc/security/99-risk-reduce.mdcredits with reducing R-S3 and R-S15.This is the same class of drift that #254 removed for the systemd units, left
in place on the mechanism whose trust root #249 had just moved.
Acceptance: one test drives both implementations over the same synthetic
/procancestry and requires identical output, including the edge cases thewalk defines (depth limit, non-contiguous
sshd-session, pid 1). It goes intests/mutation/catalogueafterwards, so a future divergence fails rather thanbeing noticed by reading.
2.
src/cache_key.crejection branches have no test4cbe85cadded them and touched no test file; there is notests/test_cache_key*.Six
rejectedpaths are uncovered: not a regular file, not root-owned,setuid/setgid bits, and group/other permission bits.
It is the only hardening of the 0.7.0 series with no proof, and it corrects a
real branch-nesting bug.
Acceptance: unit tests for each refusal, and a catalogue entry so removing
one fails.
3. Documentation that contradicts the tree
Small, no design decisions, and an evaluator reads these before reading code:
CMakeLists.txt:2still saysVERSION 0.6.2.doc/security/07-plan-de-traitement.md: MT52 is markedOuvertalthoughThe PAM client signs 2 of 6 /pam/* endpoints, so pamAccessRequestSigningMode=required cannot be turned on #247 and feat(pam): sign every /pam/ call, so pamAccessRequestSigningMode=required becomes deployable #252 are merged.
SECURITY.md:539still lists "Encrypted secrets in the secret store becomepermanently unrecoverable" among the impacts of a machine-id change. The main
passage was corrected when the store was removed; this bullet in the
machine-id section was not.
4. A process note in the homologation dossier
Not a defect, a gap in the record. 113 of the 166 commits since
v0.6.2carry aClaude-Sessiontrailer and 160 are dated across three days. Both are accurate:this was an AI-assisted campaign with human review at each merge, and the
reviews are recorded on the pull requests.
History will not be rewritten — the SHAs are cited in
99-risk-reduce.mdandin issues, so rewriting would break the traceability it would be meant to
protect. The right answer is therefore to state what happened, in
doc/security/08-dossier-homologation.mdalongside the trust assumptions, so anevaluator's first question ("36 PRs in three days — who reviewed them?") has a
verifiable answer instead of an absence.
5. Decide R-P1 — the actual release gate
The only item here that changes what the product claims.
With
pamAccessServerGroupsempty — the multi-group configuration thearchitecture document recommends — any compromised enrolled host can declare
itself a bastion and obtain vouchers. The upstream fix is merged and unreleased;
allowed_bastionsempty still means "accept any" by default, for Ansiblecompatibility.
It is documented and assumed, but it is the shipped default. Two honest
positions:
pamAccessAllowedRpsa documented releaseprerequisite; or
signed.
Anything between the two is what an evaluator will find first.
Not blocking, and tracked separately: #262 (no test covers the 0.6.0 portal
generation, waiting on a published image).
Raised by a global review of
v0.6.2..HEAD; items 1–3 verified against the treebefore filing.