Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

[security-audit] FAIL on 2026-09-25

Ouverte
#797 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
35/100
Type d'issue
Bug
Clarté
À clarifier
Activité
Active
Stack technique
github-actions, node.js, typescript
Domaine
backend, ci-cd, security

Piste de recherche

Start with the failing audit-application.md section and the linked GitHub Actions run and transcript. Read the cited install-macos.sh, install-linux.sh, burrow-runtime.ts, relay/src/app.ts, and the relevant security specifications to understand the warnings. Done means rerunning the security audit and confirming audit-application.md no longer reports a failing verdict.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

security-audit-failure

Audit failed at 2026-09-25T10:02Z. Run · Transcript

  • A domain returned FAIL. audit-application.md opened with VERDICT: FAIL — read that domain's section first. A domain's own verdict outranks the merged one.
Lines that decided this verdict

Lifted out of the fragments so truncation cannot cut them. Each domain's full section follows for as far as the body reaches.

  • audit-supply-chain.md: VERDICT: PASS
  • audit-ci-secrets.md: VERDICT: PASS
  • audit-application.md: VERDICT: FAIL
  • audit-hosted.md: VERDICT: PASS
  • audit-application.md: - WARNING (see qualitative findings) — tsip="$(ts ip -4 2>/dev/null | head -1 || true)" is a literal instance of the banned shape on Tailscale CLI output [macos] install-macos.sh:902; [linux] install-linux.sh:1131
  • audit-application.md: - WARNING — burrowToken travels in a URL query string on every Burrow relay connection: ?${WS_TOKEN_PARAM}=${encodeURIComponent(this.#enrollment.burrowToken)} (/home/runner/work/dormouse/dormouse/lib/src/remote/burrow/burrow-runtime.ts:771), validated from c.req.query(WS_TOKEN_PARAM) (/home/runner/work/dormouse/dormouse/relay/src/app.ts:1296). docs/specs/relay.md:327 justifies query-param WS auth with "browsers cannot set WebSocket headers" — true for /ws/client, but the `/ws/b
  • audit-application.md: - WARNING — head -1 on Tailscale CLI output, at a site the rationale's own scoping says the rule binds. tsip="$(ts ip -4 2>/dev/null | head -1 || true)" at /home/runner/work/dormouse/dormouse/deploy/local/install-macos.sh:902 and /home/runner/work/dormouse/dormouse/deploy/local/install-linux.sh:1131 is an inline command substitution whose value drives a manage verify decision, which is exactly the shape docs/specs/security-remote.md:197 names and `docs/specs/security-remote.rationa
  • audit-application.md: #### WARNINGs (7, none a boundary crossing)

Security audit

Supply chain

VERDICT: PASS

FAIL IF results
  1. FAIL IF node website/scripts/generate-deps.js changes the three disclosure JSON files after pnpm install --frozen-lockfile. PASS. Ran pnpm install --frozen-lockfile (lockfile up to date, no changes), then node website/scripts/generate-deps.js (wrote 66 npm deps, 12 direct + 478 transitive cargo deps, 1 bundled runtime). git status --porcelain website/src/data/ and git diff website/src/data/ are both empty — no diff produced.

  2. FAIL IF .github/workflows/ci.yml stops running the generator under the --frozen-lockfile precondition or stops failing on a diff. PASS. ci.yml lines 24-25 run pnpm install --frozen-lockfile; the "Dependency disclosure is current" step (lines 39-46) runs node website/scripts/generate-deps.js then git diff --quiet -- website/src/data/, exit 1 on a diff.

  3. FAIL IF the disclosure omits a shipped workspace's graph or excludes a shipped package. PASS. Derived independently from pnpm-workspace.yaml's 11 packages against each package.json's declared name: productDependencyFilters = dor, dormouse (vscode-ext), dormouse-standalone, dormouse-lib (lib), dormouse-sidecar (standalone/sidecar), relay (6 roots); excludedWorkspacePackages = canopy, dormouse-website (website), dormouse-hosted (hosted) (3 exclusions, each installs no artifact — canopy is Storybook-only, website runs in a visitor's browser, hosted runs on Workers/browser only). The remaining 2 packages, dor-lib-common and remote-lib-common, are workspace edges reached via runtime dependencies (not devDependencies) from roots: dor-lib-common from dor and lib's package.json dependencies; remote-lib-common from lib and relay's dependencies. All 11 workspace packages accounted for by root, exclusion, or reachable edge — matches what assertWorkspaceCoverage in website/scripts/dependency-workspaces.js enforces at generation time (verified it throws on unclassified/duplicate/stale names and on a reachable exclusion; website/scripts/dependency-workspaces.test.js covers these cases).

  4. FAIL IF root package.json is missing devEngines.runtime.version, or its value is not an exact MAJOR.MINOR.PATCH. PASS. package.json -> devEngines.runtime.version = "24.18.0", matches ^\d+\.\d+\.\d+$.

  5. FAIL IF standalone/src-tauri/build.rs no longer runs --version on the bundled binary and fails the build on mismatch, or the check is skipped for a release-matrix configuration other than the permitted host!=target skip. PASS. verify_node_version (build.rs:191-227) runs node_source --version, compares trimmed output against read_pinned_node_version's parse of devEngines.runtime.version, and returns Err (failing the build via .expect(...) in bundle_node_runtime) on mismatch. The only skip is host != target (build.rs:197-205), which only warns and returns Ok. .github/workflows/release.yml's build-standalone matrix (lines 26-36) has exactly three entries — ubuntu-22.04/x86_64-unknown-linux-gnu, macos-latest/aarch64-apple-darwin, windows-latest/x86_64-pc-windows-msvc — each platform runner native to its own target, so host == target for every entry the release matrix builds and the skip path is never exercised in CI today.

  6. FAIL IF the build-standalone job does not install the pinned runtime via node-version-file: package.json, or root package.json gains a volta.node or engines.node field. PASS. release.yml lines 46-48 use actions/setup-node with node-version-file: package.json. package.json has no volta key and no engines key (grepped both; only devEngines.runtime present).

  7. FAIL IF pnpm-workspace.yaml is missing minimumReleaseAge: 1440. PASS. pnpm-workspace.yaml:44 sets minimumReleaseAge: 1440 (1440 minutes = 24 hours).

  8. FAIL IF .github/renovate.json is missing npm or cargo from enabledManagers, or is missing minimumReleaseAge package rules for those managers. PASS. enabledManagers = ["github-actions", "npm", "cargo"]. packageRules includes three rules matching matchManagers: ["npm", "cargo"] with matchUpdateTypes patch/minor/major set to minimumReleaseAge "1 day"/"3 days"/"14 days" respectively.

  9. FAIL IF .github/renovate.json has no vulnerabilityAlerts block, or that block does not explicitly set minimumReleaseAge. PASS. vulnerabilityAlerts block present with "minimumReleaseAge": "1 day" set explicitly (and a comment explaining why omitting it would silently drop the cooldown to null).

  10. FAIL IF secret scanning or push protection is disabled, or Dependabot alerts are off. PASS, all three clauses. GH_TOKEN=$AUDIT_PAT gh api repos/diffplug/dormouse --jq .security_and_analysis (200) -> secret_scanning.status: "enabled"; secret_scanning_push_protection.status: "enabled". GH_TOKEN=$AUDIT_PAT gh api repos/diffplug/dormouse/vulnerability-alerts -i -> HTTP/2.0 204 No Content (Dependabot alerts on). Note (not part of this FAIL IF): dependabot_security_updates.status is "disabled" — automatic Dependabot PRs are off, but the spec does not require them; Renovate's vulnerabilityAlerts block (checked above) is the path this repo uses instead.

Qualitative findings

Scope worked: lib/package.json added ws (^8.21.3) to its runtime dependencies (plus @types/ws, playwright-core to devDependencies) since the last successful audit (comparing head commit 8836c754 from the 2026-09-24 09:19 UTC PASS run against current main, via gh api repos/diffplug/dormouse/compare/...). This is a genuine new production dependency on a disclosed root (dormouse-lib). Verified it is legitimately used (lib/src/host/agent-browser-host.ts, lib/src/host/browser-viewer.ts, lib/src/host/browser-host.ts — Node-side host modules bundled into both hosts) and is already correctly disclosed: the FAIL-IF-1 regeneration above produced no diff, confirming dependencies-npm.json already reflects it. No lockfile change was needed since ws was already resolved elsewhere in the graph. This is exactly the class of change the CI regeneration gate (FAIL IF 2) exists to catch per the rationale's ws/hono history, and it passed cleanly this time. INFO, not a finding.

Non-registry lockfile resolutions: grepped pnpm-lock.yaml for tarball:/http(s):// resolutions outside the npm registry. Found three kinds: (1) @diffplug/xterm-addon-webgl-sdf, a GitHub-release tarball, is canopy's dependency only — canopy is in excludedWorkspacePackages (Storybook-only lab, docs/specs/webgl-text.md documents the fork pipeline) and is not reachable from any product root (confirmed under check 3), so it correctly never reaches the disclosure or a user's machine. (2) pgstencil / @pgstencil/auth, resolved via file:vendor/*.tgz per pnpm-workspace.yaml's overrides, belong to hosted/dormouse-hosted, which is also excluded — pgstencil provenance is the hosted domain's scope (docs/specs/security-hosted.md), not this one. (3) nodejs.org/unofficial-builds.nodejs.org tarball URLs under the root node: runtime:24.18.0 devEngines entry are pnpm's own runtime-provisioning URLs for the pinned Node version already covered by the Bundled Runtime checks above. None of the three represent an undisclosed package reaching a user's machine. INFO.

Install scripts in production dependencies: pnpm-workspace.yaml's allowBuilds map permits native builds for workerd, @swc/core, esbuild, node-pty, and sharp, and blocks them for cpu-features, protobufjs, ssh2, @vscode/vsce-sign, and keytar. Traced each allowed package with pnpm why against the six product roots' direct dependencies (not devDependencies): only node-pty is a direct runtime dependency of a shipped root (dormouse / vscode-ext and dormouse-sidecar), which is expected (native PTY addon) and already disclosed. esbuild, @swc/core, and workerd only reach dormouse-hosted / build tooling (wrangler, storybook, argos-ci), which is excluded from the shipped graph. sharp is pulled in as a dependencies-declared transitive of ascii-splash under dormouse-website (excluded — browser-only, and sharp's native binary cannot run in a browser regardless, so it is a build-time-only artifact) and otherwise only as devDependencies of dormouse-hosted/dormouse-lib tooling. No allowed-build package reaches a shipped root through an undisclosed path. INFO.

Any package reachable but undisclosed: none found. The root-completeness derivation (check 3) accounts for all 11 workspace packages, and the clean generate-deps.js diff (check 1) confirms the generated disclosure matches what the roots currently resolve to.

CI and secrets

VERDICT: PASS

FAIL IF results
  • FAIL IF pull_request_target appears outside tend-*.yaml (security-ci.md "GitHub Actions Policies"): PASS. Grep of .github/workflows/** shows pull_request_target only as an on: trigger in tend-review.yaml (agent-managed, exempt) and as a code comment in hosted-preview.yml:75 ("Never expose deployment credentials to fork code or pull_request_target"), which is not a trigger.
  • FAIL IF a non-agent-managed workflow has effective write permissions other than id-token: write/attestations: write or the security-audit job's actions: write (security-ci.md "GitHub Actions Policies"): PASS. argos.yml, ci.yml, hosted-preview.yml, hosted-production.yml declare only workflow-level contents: read (job changes in hosted-preview.yml additionally scopes pull-requests: read, a read permission). release.yml is workflow-level contents: read; its build-standalone/build-vscode jobs add id-token: write+attestations: write (the documented exception, gated on the release-attest environment admitting only admin-gated v* tags), its security-audit job adds only actions: write (the documented exception), and publish-vscode has no job-level permissions block, so it inherits workflow-level contents: read.
  • FAIL IF every uses: ref in a non-tend-*.yaml workflow is not pinned by commit SHA: PASS. Scanned every uses: line in argos.yml, ci.yml, hosted-preview.yml, hosted-production.yml, release.yml, security-audit.yaml, workflow-audit.yaml — every ref is a 40-hex-character commit SHA with a version comment. tend-*.yaml files use tag pins (max-sixty/tend/[email protected], actions/checkout@v7, astral-sh/[email protected]), consistent with the documented exemption.
  • FAIL IF an agent-managed workflow job's effective GITHUB_TOKEN permissions exceed contents: write, pull-requests: write, issues: write, id-token: write, actions: read, or any read scope: PASS. Checked every permissions: block (workflow- and job-level) in all tend-*.yaml, workflow-audit.yaml, and security-audit.yaml — every declared scope is within the allowed set (contents: write, pull-requests: write/read, issues: write, actions: read, id-token: write).
  • FAIL IF default_workflow_permissions is not read or can_approve_pull_request_reviews is not false: PASS. GET repos/diffplug/dormouse/actions/permissions/workflow returns {"default_workflow_permissions":"read","can_approve_pull_request_reviews":false}.
  • FAIL IF private vulnerability reporting is disabled: PASS. GET repos/diffplug/dormouse/private-vulnerability-reporting returns {"enabled":true}.
  • FAIL IF either admin-gating ruleset is missing or weakened (security-ci.md "Automated Maintainer (tend)"): PASS, both clauses. GET .../rulesets/16757376 ("Merge access"): target: branch, conditions.ref_name.include: ["~DEFAULT_BRANCH"], rules: [update, deletion, creation], bypass_actors: [{actor_id:5, actor_type:RepositoryRole, bypass_mode:exempt}] — matches spec exactly (target, all three blocked operations, sole admin bypass actor). GET .../rulesets/16757382 ("Tag operations"): target: tag, conditions.ref_name.include: ["~ALL"], rules: [creation, update], same sole admin bypass actor — matches spec exactly.
  • FAIL IF dormouse-bot holds maintain or admin: PASS. GET repos/diffplug/dormouse/collaborators/dormouse-bot/permission returns permission: "write", role_name: "write" — neither maintain nor admin.
  • FAIL IF any GitHub environment except hosted-preview admits a ref not admin-gated by Tag operations/Merge access: PASS for every non-hosted-preview environment. Enumerated all 7 environments (GET .../environments) and each one's deployment-branch-policies: hosted-production admits only main (branch, covered by "Merge access" which blocks all non-admin update/creation/deletion on ~DEFAULT_BRANCH); hosted-release-tag admits only main (same); release-attest admits only tag pattern v* (covered by "Tag operations", ~ALL tags, admin-only creation/update); security-audit admits main and tag v* (both covered); tend admits only main (covered); vscode-extension-publish admits only tag v* (covered). hosted-preview (the named exception) admits main and refs/pull/*/merge — checked instead against "Hosted Deployments" below.
  • FAIL IF a Hosted environment lacks branch restrictions, required reviewers, or disabled administrator bypass (security-ci.md "Hosted Deployments"): PASS, all three environments. hosted-preview: admits main + refs/pull/*/merge, required_reviewers = [nedtwigg, edgartwigg], prevent_self_review: false (self-review is explicitly allowed by spec), can_admins_bypass: false. hosted-production: admits only main, same two reviewers, can_admins_bypass: false. hosted-release-tag: admits only main, same two reviewers, can_admins_bypass: false.
  • FAIL IF Hosted credentials appear at repository/org scope, or production credentials appear in hosted-preview: PASS. Repo-level secrets are exactly ARGOS_TOKEN, CHROMATIC_PROJECT_TOKEN (0 Hosted-related names); org-level secrets: 0 entries. hosted-preview's environment secrets (CLOUDFLARE_API_TOKEN, NEON_API_KEY, PREVIEW_AUTH_SECRET) are distinct, environment-scoped GitHub secret objects from hosted-production's own CLOUDFLARE_API_TOKEN — GitHub environment secrets are never shared across environments by name, so no production secret value can be present in hosted-preview through GitHub's placement mechanism; this is the limit of what "inspect GitHub secret placement" can determine (the underlying token's actual Cloudflare/Neon privilege scope is not GitHub-readable).
  • FAIL IF HOSTED_TAG_TOKEN appears outside hosted-release-tag, or that environment is used by a job other than tag in hosted-production.yml: PASS. HOSTED_TAG_TOKEN does not appear in any repo secret, org secret, or any other environment's secret listing (in fact hosted-release-tag's own secret listing is currently empty — 0 entries — a provisioning gap, not a placement violation). grep of .github/workflows/** shows hosted-release-tag referenced only once, as the environment: of the tag job in hosted-production.yml, and HOSTED_TAG_TOKEN referenced only in that same job.
  • FAIL IF a Hosted preview deploy accepts a fork or a failing verification, preview cleanup checks out a PR ref rather than main, or a Hosted production tag can run before live verification succeeds: PASS. hosted-preview.yml's deploy job requires needs: verify and its if: excludes forks (github.event.pull_request.head.repo.full_name == github.repository); cleanup checks out refs/heads/main explicitly, not the PR ref. hosted-production.yml's tag job has needs: deploy, and deploy itself runs the live smoke check (production.mjs smoke) as its last step before finishing, so tag cannot start until that verification succeeds.
  • FAIL IF .config/tend.yaml does not set merge: restricted, or any tend-*.yaml passes another merge:: PASS. .config/tend.yaml sets merge: restricted; every tend-*.yaml that embeds a merge: key (tend-ci-fix.yaml, tend-mention.yaml, tend-nightly.yaml, tend-notifications.yaml, tend-review-runs.yaml, tend-review.yaml, tend-triage.yaml, tend-weekly.yaml) passes merge: restricted, none other.
  • FAIL IF CHROMATIC_PROJECT_TOKEN or ARGOS_TOKEN is missing from secrets.allowed in .config/tend.yaml: PASS. .config/tend.yaml's secrets.allowed lists exactly CHROMATIC_PROJECT_TOKEN and ARGOS_TOKEN.
  • FAIL IF Renovate's github-actions manager can update .github/workflows/tend-*.yaml: PASS. .github/renovate.json packageRules has a rule with matchManagers: ["github-actions"], matchFileNames: [".github/workflows/tend-*.yaml"], enabled: false.
  • FAIL IF any tend-*.yaml pins max-sixty/tend below 0.1.19: PASS. Every tend-*.yaml's max-sixty/tend/[email protected] (>= 0.1.19).
  • FAIL IF any tend-*.yaml workflow uses an unpinned action reference: PASS. All uses: refs in tend-*.yaml are tag pins with an explicit version (actions/checkout@v7, astral-sh/[email protected], max-sixty/tend/[email protected]) — none is @main or bare/unversioned.
  • FAIL IF .github/workflows/workflow-audit.yaml starts deriving its lower bound from anything the pusher controls: PASS. SINCE is read from gh api .../actions/workflows/workflow-audit.yaml/runs?status=success&per_page=1 --jq '.workflow_runs[0].created_at' (server-set), falling back to 25 hours ago only when no prior successful run exists; no pusher-controlled timestamp (e.g. committer date, --since) is used.
  • FAIL IF .github/audit/ or .vscode/ is outside any consumer of workflow-audit.yaml's diff window: PASS. WINDOW=(.github/workflows/ .config/tend.yaml .github/audit/ .vscode/) is the single definition; WINDOW_NON_WORKFLOW=("${WINDOW[@]:1}") is derived from it (not hand-duplicated); COMMITS (git log … -- "${WINDOW[@]}"), own_changes(), is_clean_merge(), is_renovate_pin_bump()'s refusal, and is_tend_regen()'s refusal all reference WINDOW/WINDOW_NON_WORKFLOW rather than a separately hand-maintained list.
  • FAIL IF .github/workflows/workflow-audit.yaml is missing, disabled, or has not produced a successful run in the last 48 hours: PASS. GET .../actions/workflows/workflow-audit.yaml shows state: active; the 5 most recent runs are all conclusion: success, most recently 2026-09-24T12:41:20Z (within 48h of the audit's run time, 2026-09-25).
  • FAIL IF vscode-extension-publish lacks nonempty required reviewers, prevent_self_review: true, or can_admins_bypass: false: PASS. Environment API shows required_reviewers = [nedtwigg, edgartwigg] (nonempty), prevent_self_review: true, can_admins_bypass: false.
  • FAIL IF release.yml is missing the vscode-extension-publish environment on the VS Code publish job, or VSCE_PAT/OVSX_PAT are referenced from a job not bound to that environment: PASS. publish-vscode job declares environment: {name: vscode-extension-publish}. Repo-wide grep shows VSCE_PAT/OVSX_PAT referenced only at release.yml:347 and :359, both inside that same job.
  • FAIL IF release.yml uses production desktop signing secrets in CI, or stops generating an ephemeral Tauri updater key for unsigned CI artifacts: PASS. build-standalone runs "Generate ephemeral Tauri updater key" (tauri signer generate --ci --write-keys … --force) and exports it as TAURI_SIGNING_PRIVATE_KEY; repo-wide grep of .github/workflows/ finds no reference to APPLE_SIGN_PASS, EV_SIGN_PIN, or a non-ephemeral TAURI_SIGNING_PRIVATE_KEY.
  • FAIL IF scripts/sign-and-deploy.sh stops verifying GitHub artifact attestations, stops verifying SHA-256 manifests, or stops using PIV-backed Windows signing: PASS. verify_downloaded_artifact() calls gh attestation verify with --cert-identity/--cert-oidc-issuer/--source-ref/--source-digest, and check_sha256_manifest() runs sha256sum -c/shasum -a 256 -c; sign_windows() calls jsign --storetype PIV.
  • FAIL IF TAURI_SIGNING_PRIVATE_KEY is passed on a command line, or EV_SIGN_PIN is passed literally to jsign --storepass: PASS. TAURI_SIGNING_PRIVATE_KEY is exported as an env var before tauri signer sign "$bundle" (never appears as a flag value); jsign --storepass env:EV_SIGN_PIN passes the literal string env:EV_SIGN_PIN (an indirection token jsign itself resolves from its environment), not the PIN value. APPLE_SIGN_PASS is passed as xcrun notarytool --password "$APPLE_SIGN_PASS" (argv) — this is the documented, accepted "Known gap" in security-ci.md, not a FAIL IF violation.
  • FAIL IF .github/workflows/security-audit.yaml is missing/disabled, or the gh workflow run dispatch / gh run watch --exit-status / publish-vscode's needs: edge is gone (security-audit.md release-gate check): PASS. GET .../actions/workflows/security-audit.yaml shows state: active. release.yml's security-audit job runs gh workflow run "$workflow" … --ref "$tag" then gh run watch "$run_id" … --exit-status; publish-vscode declares needs: [build-standalone, build-vscode, security-audit].
  • FAIL IF a docs/specs/security*.md spec is in no domain's scope, in two, or a scope names a nonexistent file (security-audit.md "Domains"): PASS. Manually cross-checked each domain file's **Scope** bullet list against the 7 non-rationale docs/specs/security*.md files: ci-and-secrets claims security.md, security-ci.md, security-audit.md; application-security claims security-local.md, security-remote.md; hosted claims security-hosted.md; supply-chain claims security-supply-chain.md — exactly one claimant each, no orphan, no dangling path. node scripts/spec-lint.mjs (which mechanically enforces this as "check 16") independently confirms: spec-lint: OK (35 specs, 71 files checked).
  • FAIL IF the audit stops fanning out to dedicated application-security/hosted subagents, or either scope is merged into a context also carrying another domain: PASS. .github/audit/orchestrator.md §1 spawns exactly supply-chain, ci-and-secrets, application-security, hosted as four separate subagent_type Task calls in one message; each domain file (.github/audit/*.md) has its own single-domain **Scope** block, none combined.
  • FAIL IF application-security/hosted does not run on a stronger model than the mechanical domains, in both security-audit.yaml's claude_args and scripts/security-audit-local.sh: PASS. security-audit.yaml's claude_args sets --model sonnet as the session default and the --agents JSON overrides "model":"opus" for exactly application-security and hosted. scripts/security-audit-local.sh's run_domain() sets model_args="--model sonnet" by default and overrides to --model opus for application-security|hosted via the same case statement.
  • FAIL IF .github/audit/ is missing a prompt file the workflow names, or security-audit-local.sh stops running from those same files: PASS. All six files (_preamble.md, orchestrator.md, supply-chain.md, ci-and-secrets.md, application-security.md, hosted.md) exist; security-audit-local.sh loops over exactly this set at startup (for f in _preamble orchestrator supply-chain ci-and-secrets application-security hosted) and errors out if any is missing, then run_domain() reads _preamble.md + $domain.md via cat, matching the workflow's --agents prompt pointers.
  • FAIL IF tend regeneration materializes anything except regular .config/tend.yaml and workflow YAML blobs from the audited commit: PASS. is_tend_regen() in workflow-audit.yaml (lines 268-273) walks git ls-tree -r "$sha" -- .config/tend.yaml .github/workflows/ and returns failure (1) unless every entry's mode is 100644 or 100755 (rejecting symlinks/submodules) and every path is exactly .config/tend.yaml or matches .github/workflows/[^/]+\.ya?ml$.
  • FAIL IF the orchestrator prompt stops requiring a non-turn-ending wait — a Bash until loop over the fragments' sentinels, breaking on its own sub-cap, re-issued under a bounded 32-minute deadline persisted to a file: PASS. .github/audit/orchestrator.md §2 defines DEADLINE_FILE="$RUNNER_TEMP/audit-deadline" seeded to now + 1920 (32 min) only if absent, an until … finished … loop over all four fragment sentinels with CALL_END breaking at 540s so the call always prints an answer, and explicit instructions to re-issue the block verbatim (reading back the same DEADLINE_FILE) on STILL WAITING. security-audit.yaml's BASH_DEFAULT_TIMEOUT_MS: "600000" sets the cap this loop assumes, and timeout-minutes: 40 on the job exceeds the 32-minute wait deadline plus setup overhead.
  • FAIL IF the prompt permits ending the turn without audit-report.md: PASS. .github/audit/orchestrator.md §4 states verbatim: "Never end your turn while audit-report.md does not exist... If you have nothing left to wait on, merge §3 with whatever fragments exist and let its markers say the rest."
  • FAIL IF a domain prompt lets findings be held for a write-up at the end, lets a domain that delegates end its turn or background its wait loop, or the wait/merge/verdict treats existence rather than the sentinel as reported: PASS. .github/audit/_preamble.md requires fragments to be opened before the first check and appended to "as you determine them — never buffered... for one write-up at the end", and requires any delegating domain to "block for your delegates — never end your turn to wait", explicitly forbidding run_in_background. Both the orchestrator's wait loop (finished()) and merge step (emit()) test for the literal <!-- END OF REPORT --> sentinel via [ -s "$1" ] && [ "$(... | tail -n1)" = "<!-- END OF REPORT -->" ], not mere file existence.
  • FAIL IF the orchestrator can report PASS while a subagent left no report fragment, nor FAIL unless some domain actually returned one: PASS. .github/audit/orchestrator.md §4: "write no status file at all" whenever any domain is missing/empty/unreadable/unsentineled, and "PASS requires all four domains to pass"; FAIL requires "any subagent returned FAIL" — a real domain verdict. security-audit.yaml's reporting step independently re-derives this from the fragments themselves (MISSING_FRAGMENTS, UNFINISHED, UNREADABLE_VERDICTS, INCONCLUSIVE_DOMAINS loops, none gated on $STATUS) rather than trusting the orchestrator's own audit-status.txt, so a prompt failure alone cannot produce a false PASS.
  • FAIL IF the Redact secrets from agent output step is removed, stops covering any sink that is later published, or stops failing closed: PASS. The step is if: always(), runs before the artifact-upload and reporting steps, redacts AUDIT_PAT and CLAUDE_CODE_OAUTH_TOKEN from $TRANSCRIPT, audit-report.md, and every file in $AUDIT_FRAGMENTS (all four domain fragments — the identical set named in the job-level env: and consumed by the reporting step's guard loops and the artifact upload's path:), and on any Node error runs rm -f "$TRANSCRIPT" audit-report.md $AUDIT_FRAGMENTS; exit 1 — deleting rather than shipping an unredacted sink.
  • FAIL IF the reporting step writes issue prose per combination of conditions rather than one note per condition that holds: PASS. The NOTES block in the "Surface result" step is five independent if [ -n "${VAR:-}" ] blocks (DISSENTING, MISSING_FRAGMENTS, UNREADABLE_VERDICTS, UNFINISHED, INCONCLUSIVE_DOMAINS) plus one for FILE_STATUS = MISSING, each appending its own line independently — no combinatorial branching.
  • FAIL IF either fragment guard is gated on the status at all: PASS. Both for f in $AUDIT_FRAGMENTS loops (the missing-fragment check and the sentinel/verdict-line check) run unconditionally, before the STATUS escalation block; the code comments explicitly note "Both loops now run UNCONDITIONALLY."
  • FAIL IF the reporting step accepts any domain verdict other than exact VERDICT: PASS as passing, fails to recognize a VERDICT: FAIL prefix as dissent, ignores an inconclusive domain, accepts a fragment with no completion sentinel as finished, or accepts status text other than literal PASS/FAIL: PASS. The verdict case matches 'VERDICT: FAIL'* (prefix, so "FAIL" plus explanation still dissents) into DISSENTING, only the exact string 'VERDICT: PASS' as passing, 'VERDICT: INCONCLUSIVE' into INCONCLUSIVE_DOMAINS, and everything else into UNREADABLE_VERDICTS; the sentinel test (tail -n1 after stripping blank lines) is a separate, unconditional check that flags UNFINISHED regardless of the verdict line. FILE_STATUS is parsed with case "${FILE_STATUS:-}" in PASS|FAIL) ;; *) FILE_STATUS=MISSING ;; esac — only the literal strings pass through.
  • FAIL IF the step that verifies AUDIT_PAT is provisioned before the audit runs is removed or bypassed: PASS. security-audit.yaml's "Verify AUDIT_PAT is provisioned" step runs after checkout/setup-node/install and before the "Audit against the security specs" step, checks [ -n "$AUDIT_PAT" ], and on failure writes audit-report.md/audit-status.txt and exit 1 (job fails, no audit step runs).
Qualitative findings

Truncated to fit: the full body is 336081 characters. The untruncated audit-report.md is in this run's audit-transcript artifact (download).

Langage dominant
TypeScript
Étoiles
5
Forks
1
Merge moyen
16 h 9 min
PR mergées (30 j)
269

Préparer son environnement

Nous n'avons pas encore vérifié les fichiers d'installation de ce projet. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de diffplug/dormouse

Toutes les issues de diffplug/dormouse

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.