Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Always-public API path check has no refusal test, so a prefix-match regression opens gated routes

Closed Beginner friendly
#11,995 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
86/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
express, javascript

Research direction

Start with server/lib/apiAccessPolicy.js and its tests in server/lib/apiAccessPolicy.test.js, then read the auth gate tests in server/services/authGate.test.js. Add the listed exact-path and child-path cases, including a protected-install request without credentials. Run the relevant test files and confirm a prefix-match mutation fails in both; no production code should change.

Written by the indexing model from the issue text.

Description

effort:low model:light plan planner:fable-5-1 test-quality tests

Slice audited: external auth boundary tests (test-quality audit, 2026-10-18).

Problem

isAlwaysPublicApiPath in server/lib/apiAccessPolicy.js:16 is an exact Set lookup over ALWAYS_PUBLIC_API_PATHS, consumed by isPublicPath in server/services/authGate.js. Its tests only ever use it as a positive disjunct:

  • server/lib/apiAccessPolicy.test.js:33-38 folds it into the reachable() helper; no case asserts it returns false for anything.
  • server/services/authGate.test.js:87 ("passes /api/auth/login through") and :95 (travel guest) assert the public siblings pass; no case asserts a child or extension of a public path is still gated.

Mutation probe (scratch worktree): replaced the Set lookup with ALWAYS_PUBLIC_API_PATHS.some((p) => path.startsWith(p)) and ran every server suite importing apiAccessPolicy, authGate or systemHealth (69 files).

Test Files  69 passed (69)   Tests  1165 passed | 1 skipped (1166)

Impact

On a password-protected install, the mutation makes GET /api/system/health/details (system metrics, app and CoS status, server/routes/systemHealth.js:98) and POST/DELETE /api/system/health/warnings/:type/dismiss (a settings write, :111 and :131) reachable with no credential, because /api/system/health is public and they share its prefix. That is exactly the unauthorized LAN/tailnet caller the instance password exists to refuse, and the suite cannot see the regression. server/lib/sidecarAuthGate.js:92 keeps its own Set, so there is no second production site to change.

Fix (decided)

  • In server/lib/apiAccessPolicy.test.js, add a table case: every ALWAYS_PUBLIC_API_PATHS entry is true; /api/auth/status-extra, /api/auth/status/, /api/system/health/details, /api/system/health/warnings/x/dismiss, and /api/eidoverse/travel/guest/x are false.
  • In server/services/authGate.test.js, add one gate-level case: with a password set and no credential, GET /api/system/health/details answers 401 AUTH_REQUIRED while GET /api/system/health still passes.
  • No production code change.

Scope: small

Acceptance criteria

  • Replacing the Set lookup with a startsWith prefix match fails at least one case in each of the two files.
  • The gate-level case proves a public path's child is refused on a password-protected install.
  • No production code change.
Dominant language
JavaScript
Stars
38
Forks
32
Avg merge
34m
Merged PRs (30d)
993

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from atomantic/PortOS

All issues in atomantic/PortOS

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.