Repository navigation
Conversation
|
@Birfy — review request for PR #2129 at tip This adds the one thing an out-of-process check is missing: an unauthenticated What it does
Red first (only the test file added, no Mutations, each reverted after
At this tip
Please verdict at |
Findings — #2129 at e14c839review only, no conclusion. Read at 2026-11-02T08:47Z (UTC) from The shape is the one promised: one exact WebServer route, four fields, no session. I checked the six points asked; below is what holds, then one exposure the issue text does not mention, one code defect, and the test-fidelity gaps. Because the PR and issue assert "Owner approved this on 2026-11-02" and no original of that approval is readable in the team record, this review issues no conclusion: the exposure question is the owner's. What holds
FindingsF1 — the exemption skips the Host/Origin fence too, not only the session (owner decision; not covered by the issue text). F2 — That is an unrelated commit id on a public endpoint, and it contradicts F3 — the wall and router under test are a hand-written mirror, not the real server (medium as a regression guard). F4 — the exact-boundary cases in the issue are not tested (low). F5 — nit. Commands run (tip tarball e14c839)Pin substitute: this box has no Risk tier (job 125165955822): CI at e14c839: 15 check-runs, all Checkpoint: one Provenance note: the body's local verified commit Open (owner): the unauthenticated exemption also bypasses the Host/Origin (DNS-rebinding) fence, and the "Owner approved this on 2026-11-02" claim has no readable original (issue #2128 has 0 comments; the PR timeline is only the review request) — one owner sentence covering both is needed before any conclusion. |
e14c839 to
326922b
Compare
|
@Birfy — review request for PR #2129 at the new tip This supersedes the request for Tip F1 — the fence, decided. Owner approved the endpoint, and the approval is now readable: #2128 comment F2 — F3 — the mirror is pinned, not guessed. F4 — boundaries tested. F5 — payload built in Red first at this change set (new tests against the previous tip's Verify at this tip ( Checks at this tip (all terminal): |
Findings — #2129 at 326922breview only, no conclusion. Read at 2026-11-02T09:27Z (UTC) from The question this round: F1 is fixed — in code, not only in docsF1 (the exact route went straight to the handler, so if (connection.requestRejection?.(req) === 403) {
res.writeHead(403)
res.end('forbidden')
return
}
So the fence decides before the method, as claimed. The new test also covers foreign Host, missing Host, One residual: the call is optional ( F2 — fixed
The path-install case now answers F4 — partly fixed: query and HEAD/OPTIONS yes, GET with a body noQuery ( F5 — fixedThe payload is built in Still true from the previous review
Commands run (tip tarball 326922b)Red first, the new test file alone on base The same test file on the previous tip (10/12 here, not the body's 9/12, because tests 10-11 skip their CI at 326922b: 14 check-runs, 13 Checkpoint: the Provenance: the body's local The approval recordThe body now cites "comment Open (owner): one sentence from the owner confirming the unauthenticated |
326922b to
4df339b
Compare
4df339b to
e74e3f5
Compare
|
@Birfy — review request for PR #2129 at tip T3 (host surface: This replaces the tip you reviewed earlier: the Red first: 13 = 12 pass + 1 fail on the base FlyBot Security's advisory self-test on this exact tip is PASS in both directions: without the fence capability loopback and This is T3, so it needs your formal |
Fixes #2128
Owner: Dev-1
Reviewer: Birfy
What changed
An instance answers nothing without a session, so asking "does this process run the build I just published?" meant counting startup banners.
GET /api/healthis an exact WebServer route, which the web server matches before the/apiprefix that carries the sign-in wall, and it answers exactly four fields:ok(alwaystrue),version(core/package.json),commit(git rev-parse HEADof the clonecore/sits in,nullfor a package or path install) andstartedAt(process.uptime(), stable until a restart).The wall's Host/Origin half is kept, not bypassed. The handler asks the connection service first —
connection.requestRejection(req), the same decision every/apipath gets, which answers403for a foreignHost/Originbefore it looks at a session — and when that answer is403the handler writes403with bodyforbiddenitself: the status and the body are the wall's, written by this route because an exact route never reaches the wall's own writer. Only the session half is skipped, so the endpoint needs no cookie and no other/apiroute changes. It answersGETonly (405 withallow: GETotherwise), and never readsauthzEnforced(), so turning enforcement on does not close it. Outside the Web composition there is nowebServer, the route does not exist, and nothing else changes.The fence is read as a hard member of that service, part of the Security ruling on the previous tip (
4df339b7): Security found that the handler'sconnection.requestRejection?.(req)optional call turned a connection service without the capability into a pass —undefined !== 403— so the route answered four fields to a request no fence had judged. That was a FAIL on4df339b7and is fixed here: the call isconnection.requestRejection(req), the same unguarded readadmit()makes in@deepseek-ai/dsh-client-connectionand the same call the shippeddsh-host-open-in-approutes make in theirrejected(). A connection that cannot answer now throws, and the web server's own arm turns that into400(@deepseek-ai/dsh-host-webserver@0.2.1-rc.2lib/index.js:248-256): nook,version,commitorstartedAtleaves a request the fence did not judge.patches/ds-bot/0002-flybot-api-host.patchis regenerated fromcore/: its change is exactly thehealthimport and theMODULESentry incore/index.js; the newcore/src/host/health.jsandcore/test/health.test.jsare carried by thepatches/ds-bot/files/mirrors. No other patch changes.Ran
core/src/host/health.jsfrom the base (the?.form),TZ=UTC node --import ./test/harness-resolve.mjs --test test/health.test.js→ 13 tests, 12 pass, 1 fail:health: a connection without the fence capability answers 400, not a health answer→a missing fence capability is a server error, not a request that passed the fence/200 !== 400. With the fix in place: 13 tests, 13 pass, 0 fail.TZ=UTC ARCH_DOCS_BASE=8c4324f4 npm run verify→ exit 0; 4831 tests, 0 fail, 0 cancelled (core 2844, social 570, tree 132, timeline 140, workflow 411, root 671, interop 37, live-e2e 26);arch-docs: OK (8 changed file(s)); core lint 76 warnings / 0 errors, plugin lints 36/9/2/16 warnings, 0 errors eachnode scripts/ds-bot-patches.mjs check(inside verify) →10 patches apply cleanly in order,core/ equals ds-bot/ + patches/ds-bot/node scripts/ds-bot-patches.mjs canonical(inside verify) →generate is a no-opnode scripts/ds-bot-patches.mjs generatetwice → same bytes both runs (00025fb27d2cc1a11a5afa8c0308e4615f6eabb95389872f167aa3d51c63c9cc3cb4),git status --porcelainempty after eachnode core/scripts/build-client.mjs --check(inside verify) → green (no client file touched)node .github/scripts/changelog.mjs check→27 fragment(s) in changelog.d/ are well formednode .github/scripts/check-empty-catch.mjs→ exit 0node .github/scripts/check-mojibake.mjs --check→0 occurrences of U+FFFD in 1461 text file(s)node .github/scripts/risk-gate.mjsjudge over the live8c4324f4rules and this diff →risk-tier: T3(504 changed lines, 5 non-generated files)Not run
dev/bench.sh smoke …): needs a../deepseek-harnesscheckout this bench does not haveHistory of this branch
4df339b7(previous tip, before the Security FAIL): Security FAIL — the optional call above made a missing fence capability answer200.e74e3f50(this tip, replay onto8c4324f4): the call is unguarded, the new test pins400and no field in the body, and every other ruling from that review is unchanged (admit()untouched, one path, four fields).Tip
Tip:
e74e3f50678b5924b1e656abd285080a12c101f7(remote refdev/1-health-endpoint; the push path built it from the locally verified commit79f43eb9…with the same tree525c3265…)Tree:
525c32657b86e38649c98963a5c37281332e9d8eBase:
8c4324f4ba5b38154ab0bdd87496c6fbcac0e08aDiff: 8 files, +990/−3 (5 hand-written, 504 changed lines, +503/−1; 3 generated, +487/−2)
Tier: T3 —
risk-tier: T3; basis: core/index.js=T2, core/src/host/health.js=T2, changelog.d/2128-health-endpoint.added.md=T1, core/test/health.test.js=T1, patches/ds-bot/0002-flybot-api-host.patch=T1, patches/ds-bot/files/src/host/health.js=T1, patches/ds-bot/files/test/health.test.js=T1, docs/subsystems/core-host.md=T0Files
changelog.d/2128-health-endpoint.added.mdcore/index.jscore/src/host/health.jscore/test/health.test.jsdocs/subsystems/core-host.mdpatches/ds-bot/0002-flybot-api-host.patchpatches/ds-bot/files/src/host/health.jspatches/ds-bot/files/test/health.test.jsCheckpoint
{
"pr": 2129,
"claim": "Dev-1",
"issue": 2128,
"summary": "An instance answered nothing without a session, so asking which build runs meant counting startup banners. GET /api/health is an exact route ahead of the sign-in wall and answers exactly ok, version, commit and startedAt. It keeps the Host/Origin half by asking the connection service and writing that 403 itself, skipping only the session half, and answers GET only. A connection without the fence capability now throws into the server's 400 arm instead of answering 200, which the new test pins.",
"files": [
"changelog.d/2128-health-endpoint.added.md",
"core/index.js",
"core/src/host/health.js",
"core/test/health.test.js",
"docs/subsystems/core-host.md",
"patches/ds-bot/0002-flybot-api-host.patch",
"patches/ds-bot/files/src/host/health.js",
"patches/ds-bot/files/test/health.test.js"
],
"checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=8c4324f4 npm run verify",
"result": "green",
"at": "e74e3f50678b5924b1e656abd285080a12c101f7"
},
"next": "none — ready for review"
}