[security-audit] INCONCLUSIVE on 2026-09-22
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start with the linked Actions run and transcript, then inspect audit-application.md and the generation of audit-status.txt. Determine why the run produced UNVERIFIABLE or an incomplete/no report; the work is complete when a subsequent audit writes a definitive PASS or FAIL.
Written by the indexing model from the issue text.
Description
Audit reached no usable verdict at 2026-09-22T09:33Z. This is not a security finding: the run ended without deciding. Run · Transcript
- A domain could not determine every check. audit-application.md returned
VERDICT: INCONCLUSIVE; read itsUNVERIFIABLEchecks. Those checks do not count as passing. - The audit wrote no verdict.
audit-status.txtwas absent, empty, or notPASS/FAIL, so the run ended without deciding. Start at the report's own markers:UNVERIFIABLEis a check the agent could not determine,_Incomplete …_heads a domain that was cut off mid-report, and a domain section reading_No report …_is one that never reported — which is what an expired wait deadline looks like.
Security audit
Supply chain
VERDICT: PASS
FAIL IF results
- PASS:
node website/scripts/generate-deps.jsrun against a clean tree afterpnpm install --frozen-lockfileproduces no diff inwebsite/src/data/dependencies-{npm,cargo,runtime}.json(66 npm deps, 13 direct + 478 transitive cargo deps, 1 runtime dep; verified twice, before and after a fresh frozen install). Disclosure -> FAIL IF #1. - PASS:
.github/workflows/ci.yml"Dependency disclosure is current" step (lines 39-46) runspnpm install --frozen-lockfile(line 25) thennode website/scripts/generate-deps.js, andexit 1s ongit diff --quiet -- website/src/data/failing. Disclosure -> FAIL IF #2. - PASS:
pnpm-workspace.yaml-> "assertWorkspaceCoverage" ran successfully as part of the generator (it throws on any unclassified/missing workspace package) and manual cross-check confirms all 11pnpm-workspace.yamlpackages are accounted for: 6 product roots (dor,dormouse/vscode-ext,dormouse-standalone/standalone,dormouse-lib/lib,dormouse-sidecar/standalone/sidecar,relay), 3 explicit exclusions (canopy,dormouse-website/website,dormouse-hosted/hosted — confirmed none of the three is depended on by any other workspace package viagrepfor their package names as dependency values), and 2 workspace-edge-only packages (dor-lib-common,remote-lib-common) reachable transitively from roots.doranddormouse-libare correctly listed as independent roots even thoughdor's files reach disk viascripts/stage-dor-cli.mjs(docs/specs/dor-cli.md-> "Bundling And PATH") rather than an npm dependency edge — confirmed neitherstandalone/package.jsonnorvscode-ext/package.jsonlistsdoras a dependency. Confirmedstandalone/src-tauri/tauri.conf.json'sbundle.resources: ["../sidecar/**/*"]is the sidecar's route onto disk. Disclosure -> FAIL IF #3 (root-completeness). - PASS: root
package.jsonhasdevEngines.runtime.version="24.18.0", an exactMAJOR.MINOR.PATCH; novolta.nodeorengines.nodefield present. Bundled runtime -> FAIL IF #1 and part of #3. - PASS:
standalone/src-tauri/build.rs'sbundle_node_runtime()unconditionally callsread_pinned_node_version+verify_node_versionbefore every bundle (line 42-43), which runs<node> --versionand fails the build on any mismatch (lines 207-224); the one deliberate skip ishost != target(lines 197-205). Checked.github/workflows/release.yml'sbuild-standalonematrix (lines 26-36): all three entries (ubuntu-22.04/x86_64-unknown-linux-gnu, macos-latest/aarch64-apple-darwin, windows-latest/x86_64-pc-windows-msvc) are host-native for their GitHub-hosted runners, so the skip path is never exercised in the release matrix. Bundled runtime -> FAIL IF #2. - PASS:
build-standalone(release.yml lines 46-48) andbuild-vscode(lines 191-193) both install Node viaactions/setup-nodewithnode-version-file: package.json; rootpackage.jsoncarries novolta.node/engines.nodealternate pin. Bundled runtime -> FAIL IF #3. - PASS:
pnpm-workspace.yamlline 40 setsminimumReleaseAge: 1440. Cooldown and alerts -> FAIL IF #1. - PASS:
.github/renovate.jsonline 3enabledManagersincludes bothnpmandcargo; lines 122-135 (packageRules) setminimumReleaseAgeforpatch(1 day),minor(3 days), andmajor(14 days) update types matching bothnpmandcargomanagers. Cooldown and alerts -> FAIL IF #2. - PASS:
.github/renovate.jsonhas avulnerabilityAlertsblock (lines 8-21) that explicitly sets"minimumReleaseAge": "1 day"(line 18) rather than omitting the key. Cooldown and alerts -> FAIL IF #3. - PASS (evidence via
GH_TOKEN=$AUDIT_PAT):gh api repos/diffplug/dormouse --jq .security_and_analysisreportssecret_scanning.status: enabledandsecret_scanning_push_protection.status: enabled;gh api repos/diffplug/dormouse/vulnerability-alerts -ireturnsHTTP/2.0 204 No Content(Dependabot alerts enabled, not the 404 that would indicate disabled). Cooldown and alerts -> FAIL IF #4 (all three clauses).
Qualitative findings
- INFO: Two file-tarball, non-registry
overridesinpnpm-workspace.yaml(pgstencil: file:vendor/pgstencil-0.1.0.tgz,@pgstencil/auth: file:vendor/pgstencil-auth-0.1.0.tgz), pinned by sha256 invendor/build.json. Traced withpnpm why: both resolve only intodormouse-hosted(hosted/package.jsondependencies), which is correctly excluded from disclosure perdocs/specs/security-supply-chain.md-> "Disclosure" (dormouse-hosted— "no installed desktop or selfhost artifact imports it") and perdocs/specs/security.md("Only the self-hosted remote-control deployment ships. Hosted account code is implemented with production provisioning pending"). No FAIL today. Worth a forward note:pgstencil@0.1.0's owndependencies(notdevDependencies) pull intestcontainers->dockerode->ssh2/cpu-features/protobufjs(all correctly absent from the npm disclosure since they never reach a product root), which is unusual for a library's runtime dependency tree and worth revisiting when Hosted goes to production andhostedpotentially becomes a disclosed root. - INFO: One GitHub-Releases-tarball (non-registry) resolution in
pnpm-lock.yaml:@diffplug/xterm-addon-webgl-sdf@0.20.0-sdf304.0(tarball: https://github.com/diffplug/xterm.js/releases/download/...), the project's own xterm.js fork perAGENTS.md->canopy. Traced withpnpm why: depended on only bycanopy, whichwebsite/scripts/generate-deps.js'sexcludedWorkspacePackagesanddocs/specs/security-supply-chain.md-> "Disclosure" both correctly exclude ("a Storybook-only rendering lab no shipped build imports"). No FAIL; this is the one first-party non-registry package and it never reaches a user's disk. - INFO:
node-ptyis the only production (shipped) dependency in the graph carryingallowBuilds: trueinpnpm-workspace.yaml(native addon, required for the sidecar/vscode-ext PTY) and it is correctly present in the current disclosure. Traced every otherallowBuilds-listed package (sharp,esbuild,@swc/core,@vscode/vsce-sign,keytar,cpu-features,protobufjs,ssh2,workerd) withpnpm why: all resolve exclusively through devDependencies or through the excludeddormouse-hosted/dormouse-websiteworkspaces (storybook, vsce packaging, wrangler/miniflare, testcontainers), never through a product root'sdependencies/optionalDependencies. No production dependency with an install script is undisclosed. - INFO (spot check, not exhaustive): sampled recent history via
gh pr list/gh pr diff. Two recent feature PRs added genuinely new production dependencies to product-root workspaces — PR #669 addedpicomatchtolib/package.json(rootdormouse-lib) and PR #613 addeddetect-libc+node-datachannel+ five@node-datachannel/*platform optionals tostandalone/sidecar/package.json(rootdormouse-sidecar) — and both PRs included the regeneratedwebsite/src/data/dependencies-npm.jsonin the same PR; all ofpicomatch,detect-libc,node-datachannel, and@node-datachannel/darwin-arm64are present with correct metadata in the current disclosure file. This corroborates the CI gate (Disclosure FAIL IF #2) working in practice, not just in principle. Routine Renovate dependency-bump PRs sampled (10+ over the last day of history) either updatedwebsite/src/data/dependencies-npm.jsonin the same PR when the package was disclosure-reachable (e.g.hono,tailwind-merge,yaml) or correctly omitted that update for dev-only/excluded-workspace bumps (wrangler,tsx,@types/node,@tauri-apps/cli, all confined todormouse-hosteddevDependencies or root devDependencies never reaching a product root's runtime graph) — no undisclosed production dependency found in the sample. - Caveat: this repository checkout is a shallow, single-commit clone (
git logshows only the tip commit), so no localgit diff/git logcomparison against "the last audit" was possible; the dependency-history review above relies entirely ongh pr list/gh pr diffagainst GitHub's API rather than local git history.
CI and secrets
VERDICT: PASS
FAIL IF results
- PASS — security.md: private vulnerability reporting is enabled.
gh api repos/diffplug/dormouse/private-vulnerability-reporting→{"enabled":true}. - PASS — security-ci.md "GitHub Actions Policies":
pull_request_targetappears as anon:trigger only in.github/workflows/tend-review.yaml(an exempttend-*.yamlfile); grepped every file under.github/workflows/*.y*mlfor the string, the only other hit is a comment inhosted-preview.ymlline 75, not a trigger. - PASS — security-ci.md "Admin-gating rulesets":
GET repos/diffplug/dormouse/rulesetsreturns exactly two active rulesets.Merge access(id 16757376):conditions.ref_name.include=["~DEFAULT_BRANCH"],rules=[{"type":"update"}]only,bypass_actors=[{"actor_id":5,"actor_type":"RepositoryRole","bypass_mode":"exempt"}]— sole bypass is admin.Tag operations(id 16757382):conditions.ref_name.include=["~ALL"],rules=[{"type":"creation"},{"type":"update"}], same sole admin bypass actor. - PASS — security-ci.md "dormouse-bot permission":
GET repos/diffplug/dormouse/collaborators/dormouse-bot/permission→permission:"write",role_name:"write",permissions.admin:false,permissions.maintain:false. Neithermaintainnoradminpresent. - PASS — security-ci.md environment ref-admission: enumerated
GET .../environments(7 total) and each one'sdeployment-branch-policies.hosted-preview(excepted by the rule) admitsmain+refs/pull/*/merge. Every other environment admits only refs covered by the two admin-only rulesets above:release-attest→v*tag;security-audit→mainbranch +v*tag;tend→mainbranch;hosted-production→mainbranch;hosted-release-tag→mainbranch;vscode-extension-publish→v*tag. - PASS — security-ci.md secret placement inventory. Enumerated
actions/secrets(repo level: exactlyCHROMATIC_PROJECT_TOKEN),actions/organization-secrets(empty), and each of the 7 environments' own secret listings:security-audit→{AUDIT_PAT, CLAUDE_CODE_OAUTH_TOKEN};tend→{CLAUDE_CODE_OAUTH_TOKEN, TEND_BOT_TOKEN};vscode-extension-publish→{OVSX_PAT, VSCE_PAT};release-attest→{} (0 secrets, 0 variables);hosted-preview/hosted-production/hosted-release-tag→{} (0 secrets each — Hosted production credentials are not yet provisioned, consistent with docs/specs/security.md's "production provisioning pending"). NoANTHROPIC_API_KEYanywhere. Matches the spec's normative table exactly. - PASS — security.md
default_workflow_permissions:gh api repos/diffplug/dormouse/actions/permissions/workflow→{"default_workflow_permissions":"read","can_approve_pull_request_reviews":false}. - PASS — security-ci.md non-agent-managed workflow write-permission bound. Read every workflow-level and job-level
permissions:block inci.yml(contents:read only),chromatic.yml(contents:read only),hosted-preview.yml(workflow contents:read; jobchangesadds pull-requests:read; no job grants write),hosted-production.yml(contents:read throughout, no job overrides), andrelease.yml(build-standalone/build-vscodejobs: contents:read + the explicitly allowedid-token:write/attestations:write;security-auditjob: contents:read + the explicitly allowedactions:write;publish-vscode: no job override, inherits contents:read). No non-agent-managed workflow has an effective write scope outside the two named exceptions. - PASS — security-ci.md agent-managed workflow permission bound (contents:write, pull-requests:write, issues:write, id-token:write, actions:read, or any read). Checked
security-audit.yaml(contents:read, actions:read, issues:write, id-token:write),workflow-audit.yaml(contents:read, issues:write, actions:read, pull-requests:read), and everytend-*.yamljob-level block (all combinations of contents:read/write, pull-requests:write, actions:read, issues:write). None exceeds the allowed set. - PASS — security-ci.md tend version floor: every
tend-*.yamlfile's generated header and itsmax-sixty/tend/claude@pin both read0.2.13, above the0.1.19floor. - PASS — security-ci.md unpinned-action bound inside
tend-*.yaml: everyuses:line in the ninetend-*.yamlfiles carries an explicit tag (actions/checkout@v7,astral-sh/setup-uv@v10.1.0,max-sixty/tend/claude@0.2.13) — none unpinned (no bare@main/no ref). - PASS — security-ci.md
pull_request_targetrestricted totend-*.yaml: confirmed above, onlytend-review.yaml(exempt) uses it. - PASS — security-ci.md Renovate cannot update
tend-*.yaml:.config/tend.yaml's... correction,.github/renovate.json'spackageRulesincludes{"matchManagers":["github-actions"],"matchFileNames":[".github/workflows/tend-*.yaml"],"enabled":false}. - PASS — security-ci.md
CHROMATIC_PROJECT_TOKENinsecrets.allowed:.config/tend.yaml→secrets.allowed: [CHROMATIC_PROJECT_TOKEN]. - PASS — security-ci.md
workflow-audit.yamlliveness:state: "active"; latest successful run2026-09-21T14:00:40Z, ~19h before the current audit time (2026-09-22T09:22:50ZUTC) — within 48h. - PASS — security-ci.md
workflow-audit.yamlgap-resistant window: read the workflow source —SINCEis drawn fromgh api .../workflow-audit.yaml/runs?status=successcreated_at(server-set), never from a pusher-controlled field; the fallback (25 hours ago) only applies when there is no prior successful run. - PASS — security-ci.md
.github/audit//.vscode/diff-window coverage:WINDOW=(.github/workflows/ .config/tend.yaml .github/audit/ .vscode/)is the single array; the commit list (git log ... -- "${WINDOW[@]}"),own_changes(), and both classifiers'WINDOW_NON_WORKFLOW=("${WINDOW[@]:1}")refusal all derive from it. - PASS — security-ci.md Hosted Deployments environment protections.
GET /environmentsshowshosted-preview,hosted-production,hosted-release-tagall havecan_admins_bypass:falseand nonemptyrequired_reviewers(nedtwigg, edgartwigg); branch policies restrict each tomain(hosted-previewalso admitsrefs/pull/*/merge, expected for PR previews per the workflow's own fork/ready checks). - PASS — security-ci.md
HOSTED_TAG_TOKENplacement:grep -rn HOSTED_TAG_TOKEN .github/shows exactly one reference,hosted-production.yml'stagjob, which runs in thehosted-release-tagenvironment; no repo/org-level secret listing contains it (all Hosted secrets are unprovisioned — 0 secrets in all three Hosted environments and at repo/org level, consistent with docs/specs/security.md's "production provisioning pending"). - PASS — security-ci.md Hosted preview/production workflow-graph bounds:
hosted-preview.yml'sdeployandcleanupjobs both gate ongithub.event.pull_request.head.repo.full_name == github.repository(fork exclusion);deployhasneeds: verify;cleanupchecks outref: refs/heads/main, never the PR ref;hosted-production.yml'stagjob hasneeds: deploy, anddeploy's last step (Verify live production revision and auth boundary) runs before that job's outputs are consumed. - PASS — security-ci.md VS Code extension release gating:
vscode-extension-publishenvironment has nonempty required reviewers,prevent_self_review:true,can_admins_bypass:false(from the environments API dump above).release.yml'spublish-vscodejob carriesenvironment: {name: vscode-extension-publish};grep -rn "VSCE_PAT|OVSX_PAT" .github/workflows/shows both secrets referenced only inside that job. - PASS — security-ci.md
release.ymldesktop-signing-in-CI bound:grepforsecrets.TAURI_SIGNING_PRIVATE_KEY/secrets.APPLE_SIGN_PASS/secrets.EV_SIGN_PINacross.github/workflows/returns nothing;release.yml's "Generate ephemeral Tauri updater key" step callstauri signer generate --ciand writes the key to a$RUNNER_TEMPfile, never a repo secret. - PASS — security-ci.md
sign-and-deploy.shthree-part bound:check_gh_attestation_support+gh attestation verify(attestations),check_sha256_manifest(SHA-256 manifests), andjsign --storetype PIV(PIV-backed Windows signing) are all present inscripts/sign-and-deploy.sh. - PASS — security-ci.md signing-credential argv bound:
TAURI_SIGNING_PRIVATE_KEYis passed only via an env-var prefix (TAURI_SIGNING_PRIVATE_KEY="$TAURI_SIGNING_PRIVATE_KEY" ... tauri signer sign), never on thetauri signer signargv;EV_SIGN_PINreachesjsignonly via--storepass env:EV_SIGN_PIN(a reference), never a literal value on argv. (APPLE_SIGN_PASSremains argv-only, which is the spec's own accepted/known gap, not a new finding.) - PASS — security-audit.md release-gate wiring:
.github/workflows/security-audit.yamlexists, is not disabled, and is triggered byschedule+workflow_dispatch;release.yml'ssecurity-auditjob doesgh workflow run security-audit.yamlthengh run watch "$run_id" --exit-status;publish-vscodedeclaresneeds: [build-standalone, build-vscode, security-audit]. - PASS — security-audit.md domain-ownership:
node scripts/spec-lint.mjs→spec-lint: OK (35 specs, 69 files checked), which enforces everydocs/specs/security*.mdis claimed by exactly one domain's**Scopeblock and that every named scope file exists. - PASS — security-audit.md dedicated
application-securitysubagent:.github/audit/orchestrator.md§1 spawns exactly three Task-tool subagents (supply-chain,ci-and-secrets,application-security) concurrently in one message;application-security.mdis a separate file, not merged into either mechanical domain's prompt. - PASS — security-audit.md model floor:
.github/workflows/security-audit.yaml'sclaude_argssets--model sonnetas the session default and overridesapplication-securityto"model":"opus"inside--agents;scripts/security-audit-local.sh'srun_domain()setsmodel_args="--model sonnet"and overrides to"--model opus"only forapplication-security. Both agree. - PASS — security-audit.md prompt-file/local-runner consistency:
.github/audit/contains_preamble.md,orchestrator.md,supply-chain.md,ci-and-secrets.md,application-security.md— every filesecurity-audit.yaml's--agentsand the orchestrator prompt name;scripts/security-audit-local.shloops over the same five basenames and errors out if any is missing. - PASS — security-audit.md domain qualitative-scope coverage:
application-security.mdstates it is "the catch-all domain... defined by subtraction, not by a list" over whatsupply-chain.mdandci-and-secrets.mdexplicitly claim, and instructsls -Arecomputation rather than trusting any stale enumeration — this makes full top-level coverage structural rather than a maintained list. - PASS — security-audit.md orchestrator wait/merge/verdict mechanics, verified by reading
.github/audit/orchestrator.mdand runningnode --test scripts/security-audit.test.mjs(41/41 passing) andnode --test scripts/workflow-audit.test.mjs(6/6 passing): non-turn-ending Bashuntilloop with a persisted$RUNNER_TEMP/audit-deadline, self-breaking under the Bash cap (BASH_DEFAULT_TIMEOUT_MS: "600000"insecurity-audit.yaml, above the loop's 540s break); orchestrator prompt forbids ending the turn beforeaudit-report.mdexists; merge/verdict treat the<!-- END OF REPORT -->sentinel, not fragment existence, as "reported." - PASS — security-audit.md reporting-step guards (read
.github/workflows/security-audit.yaml's "Surface result, file or close issue" step and confirmed by the same test suite): the missing-fragment loop and the no-sentinel/verdict-parsing loop both run unconditionally (not gated on$STATUS); issue prose is emitted as one independent note per condition (DISSENTING,MISSING_FRAGMENTS,UNREADABLE_VERDICTS,UNFINISHED,INCONCLUSIVE_DOMAINS,FILE_STATUS=MISSING), never a combination-keyed block; only exactVERDICT: PASSis accepted as passing,VERDICT: FAIL(with any suffix) is recognized as dissent and forcesSTATUS=FAIL,VERDICT: INCONCLUSIVEand any unrecognized first line are both tracked as non-passing; only literalPASS/FAILfile contents are honored forFILE_STATUS, anything else becomesMISSING. - PASS — security-audit.md redaction fail-closed bound: the
Redact secrets from agent outputstep's Node script coversaudit-report.md, all three$AUDIT_FRAGMENTS, and the transcript file in one argv list, and its shell wrapper (|| { rm -f ...; exit 1; }) deletes that same sink set on any script error. - PASS — security-audit.md
AUDIT_PATprovisioning gate: theVerify AUDIT_PAT is provisionedstep runs after checkout/setup-node/install and before the audit step, exits 1 and writesFAILtoaudit-status.txtwhen the secret is empty. - PASS — private vulnerability reporting: see first entry above (security.md scope).
Qualitative findings
No BLOCKER or WARNING findings in the ci-and-secrets domain (.github/, .config/, .claude/, .vscode/, scripts/, website/public/, and code touching secrets).
- INFO:
.vscode/tasks.jsonand.vscode/launch.jsonwere inspected forrunOn: "folderOpen"or similar checkout-time execution (the risk.github/audit/ci-and-secrets.mdcalls out by name) — neither file defines any such trigger;tasks.jsonhas one manualbuild-dormouse-vscodetask with norunOptions. - INFO:
.claude/settings.jsongrants a small, benignBash(...)allowlist (test/build/screenshot commands) and defines nohooksblock, so nothing there executes automatically on session start or checkout. - INFO: eight untracked
frag-*.mdscratch files and onedormouse.ymlsit in the repo root during this run.dormouse.ymlis a tracked, legitimatedor toolconfig unrelated to the audit. Thefrag-*.mdfiles are untracked working-directory artifacts (matching theapplication-securitydomain's per-topic scratch-file naming) from the concurrently runningapplication-securitysubagent sharing this checkout — not a repository or workflow issue, and outside this domain's scope to characterize further. - INFO:
release-attestandtendenvironments havecan_admins_bypass:true(unlike the Hosted and VS Code publish environments, which requirefalse). Neitherdocs/specs/security-ci.mdnordocs/specs/security-audit.mdstates a bypass requirement for these two environments specifically, andrelease-attestholds no secrets whiletendsends itsGITHUB_TOKEN-adjacent secrets through admin-gatedmain-only deployment anyway — so this is not aFAIL IFviolation, only a documentation gap worth naming since the spec is explicit about bypass beingfalseeverywhere it does state a requirement.
Application security
VERDICT: INCONCLUSIVE
FAIL IF results
Scope: docs/specs/security-local.md, docs/specs/security-remote.md,
docs/specs/security-hosted.md, plus the catch-all remainder of the tree.
Every FAIL IF in scope was decomposed to its individual clauses and each
clause given its own verdict against code, with an absolute path and line
number or command output recorded at the time of determination.
377 clause verdicts: 375 PASS, 0 FAIL, 2 UNVERIFIABLE (both in
security-hosted.md, both external-to-repo by design). The per-clause
evidence lines are grouped below by spec section; the bracketed number is how
many clauses that bullet was decomposed into.
security-local.md — Terminal output / Browser panes / dor control socket (31 clauses, all PASS)
- PASS — terminal-output/osc52 [4] —
isKnownUnsupportedIterm2Oscstill consumes OSC 52/50/1337 and everypty:dataparse site runsTerminalProtocolParserfirst —lib/src/lib/terminal-protocol.ts - PASS — terminal-output/bounds [9] —
TITLE_LIMIT/BODY_LIMIT/COMMAND_LINE_LIMIT/sanitizeTextpresent and applied,COMMAND_LINE_LIMITbinds after the\xNNunescape with a 4x pre-bound;MAX_CWD_LENGTH/boundedCwdValueinlib/src/lib/terminal-state.ts; OSC-incomplete cap 16,384 atterminal-protocol.ts:209-212; OSC 99 pending map capped 64 with a 60 s TTL at:83-84,:426-448 - PASS — terminal-output/osc8 [6] —
linkHandler(lib/src/lib/terminal-lifecycle.ts:164) always routes through the confirmation;classifyDisplayMatchdeceptive verdict renders no open action (ExternalLinkModal.tsx), andExternalLinkModalHost.tsx:24-27rejects a deceptive confirmation host-side - PASS — browser/shim-target [6] —
iframeShim/normalizeEmbedderOriginsinlib/src/host/iframe-proxy-rewrite.tstarget only the proxy origin plus the validated innermost origin, relay no nestedlocation, no foreign-origin and no unregistered message, and the proxy uses no unvalidated chain - PASS — browser/vscode-token [3] —
isHostMessageruns before any dispatch inlib/src/lib/platform/vscode-adapter.ts:154-158; token minted per serve and attached only byWebviewChannel.postinvscode-ext/src/webview-messaging.ts - PASS — dor/control-dir [5] —
ensureControlDirrequires real directory, non-symlink, this uid, exactly0700before bind (standalone/sidecar/dor-control-server.js:88-96);resolveControlSocketPathyieldsnullotherwise, and both hosts then never export the control env (standalone/sidecar/main.js:86-124,vscode-ext/src/pty-host.js:18-76) - PASS — dor/proofs [4] — raw token never written to a socket; both sides use SHA-256-then-
timingSafeEqualinproofMatches(dor-control-server.js:19-34,dor/src/control-client.ts:70-78); 24 CSPRNG bytes per host process
security-local.md — Loopback listeners, file viewer, persisted state, Dor Tools (74 clauses, all PASS)
- PASS — loopback/lint-inventory [1] —
node scripts/loopback-lint.mjsgreen; every non-test listener it prints inspected, plus a manual sweep forcreateServer/.listen(/serve(/WebSocket. The two non-test listeners outside the named bullets are guarded:scripts/direct-interop/run.mjs:169,181(isAuthorized+isOwnOrigin, per-run token) andhosted/server/dev.ts:26,37(allowedDevRequeston request and upgrade) - PASS — iframe/origin-rewrite [3] —
Originrewritten to the upstream's own only for own-origin callers, onhandleRequestandhandleUpgrade; a foreignOriginis forwarded untouched, not blocked - PASS — iframe/cookies [4] —
CookieandSet-Cookiestripped on HTTP and on WebSocket handshakes, refused upgrades included - PASS — iframe/host-check [2] —
Hostmust name the grant's own port on both paths - PASS — frame-ancestors [5] — upstream XFO/CSP replaced with exactly
frame-ancestors 'self' <validated chain>, no other source admitted, shim targeted only at the proxy origin and the chain's innermost origin; with no usable chain the upstream headers are preserved and nothing is injected (lib/src/host/iframe-proxy.ts:365-371) - PASS — idle-timer [3] — a foreign
Origindoes not refresh a grant's idle timer; an absentOrigindoes - PASS — stream-relay [5] — grant single-use, TTL-bounded, pinned to one target port,
Origindropped rather than rewritten - PASS — browser-dev/gates [6] — all four gates present (per-run token, loopback
Host,application/jsonon every non-GET, exact-origin ACAO), the first three in the pre-routing gate; Vite server denies cross-origin reads of token-bearing modules and keeps its DNS-rebindingHostcheck - PASS — file-viewer [20] — fresh 256-bit URL capability compared by SHA-256 then
timingSafeEqualincluding malformed lengths, case-insensitive loopbackHost, absent-or-same-listenerOrigin, GET/HEAD only,allowsFileViewerRequestgating every route, no foreign CORS, no caching, no capability in a referrer; grant construction permits regular files only, rejects escaping symlinks, bounds static dependency discovery, retains descriptors, and the viewer's CSP is own-origin plus inline script/style and data images - PASS — persisted/atomic-writes [5] —
write_file_atomically+restrict_to_ownerinstandalone/src-tauri/src/lib.rsrestrict directory and file on every platform arm (0700/0600unix; one-ACE protected DACL on Windows), mode reaching the temp file before any bytes; callers enumerated from the file - PASS — notepad/settings-sync [1] — no
setKeysForSync(call anywhere invscode-ext/src/, soNOTEPAD_ARCHIVE_KEYcannot be opted in - PASS — terminal-context-dirs [5] — context arguments validated as existing absolute directories and passed as one canonical argv element with no shell interpretation (
standalone/sidecar/pty-core.js,vscode-ext/src/message-router.ts) - PASS — dor-tools [14] — repo-local named Tools inert until chrome-granted trust (no trust-grant verb on the control socket, pending approval spawns nothing), inputs stay argv until the renderer quotes them, C0/DEL rejected in argv, substituted argv and local-file targets including after symlink canonicalization, grant key derived in the host, config reads bounded and repo-config symlinks refused
security-remote.md — Trust boundary (70 clauses, all PASS)
- PASS — burrow-final-authority [10] —
#onConnectionTransportconsumes its own challenge and verifies withverifyPresenceProofagainst a binding built from the Burrow's ownburrowId, connection id, challenge and handshake hash, then requires one activeBurrowAclRecordcarrying account + passkey credential + key hash + IK-authenticated static, all before any session — no Relay-supplied claim substitutes for any of them - PASS — local-confirmation-mints [4] —
BurrowAcl.approve(remote-lib-common/src/security/acl.ts:145) has exactly one production caller,BurrowRuntime.#approvePairing(lib/src/remote/burrow/burrow-runtime.ts:1161-1201); comparison constant-time, single-attempt latch at:1136so it happens exactly once per ceremony, matched against the immutablepairingId - PASS — expected-code-never-leaves [3] —
PairingQueueItemis the four-field projection atlib/src/host/remote/service.ts:705-710and the type atservice-protocol.ts:90-97; no invitation private half crosses - PASS — pending-maps-bounded [6] —
MAX_PENDING_PAIRINGSon both the runtime map and the mirrored service queue with oldest-first eviction,MAX_PENDING_CONNECTION_HANDSHAKES,MAX_TOKENS_PER_BURROW,MAX_CLIENT_ID_LENGTHapplied at the frame boundary before any map is touched, and a failed decrypt allocating nothing (burrow-runtime.ts:1020-1024,:1308-1311)
Truncated to fit: the full body is 64243 characters. The untruncated audit-report.md is in this run's audit-transcript artifact (download).
- Dominant language
- TypeScript
- Stars
- 5
- Forks
- 1
- Avg merge
- 17h 45m
- Merged PRs (30d)
- 235
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from diffplug/dormouse
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
-
Difficulty 4/5 3-5 days Newbie friendliness 25/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
All issues in diffplug/dormouse
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
safetrustcr/dApp-SafeTrust#426 ·
-
area:workflow bug ready-for-agent
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
fil-donadoni/tolaria#4409 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Fission-AI/OpenSpec#1960 ·
-
Add dependabot Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
corsairdev/corsair#1764 ·