Skip to content

[pull] main from unohee:main#3

Merged
pull[bot] merged 3 commits into
danielabelski:mainfrom
unohee:main
Apr 20, 2026
Merged

[pull] main from unohee:main#3
pull[bot] merged 3 commits into
danielabelski:mainfrom
unohee:main

Conversation

@pull

@pull pull Bot commented Apr 20, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

unohee added 3 commits April 20, 2026 21:53
Single-author project; sponsorships keep the updates coming. Adds a
compact Ko-fi badge in the existing badge row and a dedicated Sponsor
section above the License footer so visitors know where to contribute.
* ci: set minimal workflow permissions on CI pipeline

Adds a top-level `permissions: contents: read` to .github/workflows/ci.yml
so every job runs with the least-privileged GITHUB_TOKEN. Resolves
CodeQL `actions/missing-workflow-permissions` alerts 1-5.

* fix(web): strict CORS origin check and sanitized error responses

- Replace `origin.startsWith('http://tauri.localhost')`-style checks with
  URL-parsed hostname matching. Prefix comparison admitted hosts like
  `http://tauri.localhost.evil.com`; the new guard compares hostnames
  exactly and validates the Tailscale CGNAT range by octet.
- Stop sending raw `String(err)` in JSON responses. `safeErrorMessage()`
  returns only `err.message` (or a generic string), so stack traces and
  non-Error object details no longer leak to the dashboard client.

Resolves CodeQL `js/incomplete-url-substring-sanitization` (#20, #21)
and `js/stack-trace-exposure` (#10#19).

* fix(automation): harden regex, shell, and logging inputs

- longRunningMonitor: compile user-supplied completion patterns via
  `safeCompileRegex()` (length cap + try/catch) instead of `new RegExp()`
  directly, and reject malformed `checkCommand` on registration. The
  bash invocation is still intentional — dashboard operators need to
  compose shell probes — so it is annotated accordingly rather than
  rewritten.
- scheduler: invoke `claude` via spawn argv instead of
  `bash -c "cd $path && claude -p \"$(cat $file)\" ..."`. The child
  process already gets `cwd`, so the extra shell layer (and the
  metacharacter-sensitive string interpolation) is unnecessary.
- pairPipeline/longRunningMonitor: move tainted values out of the
  `console.*` first argument so they can never be interpreted as
  `util.format` specifiers.

Resolves CodeQL `js/regex-injection` (#6, #7), `js/command-line-injection`
(#9), and two `js/tainted-format-string` alerts (#22, #23).

* fix(knowledge): defend graph file paths and untaint log calls

- store.ts: resolve every `<STORE_DIR>/<slug>.json` path through
  `resolveGraphPath()` and reject anything that escapes STORE_DIR.
  `toProjectSlug()` already strips non-alnum chars, so this is
  defense-in-depth for callers that forget to sanitize.
- store.ts / index.ts: pass slugs and project paths as separate
  `console.*` arguments instead of interpolating them into the first
  argument, so `util.format` never sees tainted specifiers.

Resolves CodeQL `js/path-injection` (#28) and the remaining
`js/tainted-format-string` alerts (#24#27).

* fix(monitor): argv-only checkCommand and regex sanitizer

BREAKING CHANGE: LongRunningMonitor.checkCommand is now `string[]`
(argv) instead of a shell string. Pipes, redirects, and substitutions
no longer work out of the box — wrap shell logic in a script and call
the script via argv.

- Replace `execFile('bash', ['-c', command])` with
  `execFile(program, args, { shell: false })`. Shell metacharacters in
  argv elements are inert because no shell interprets them, which
  eliminates the underlying command-injection surface and resolves
  CodeQL alert `js/command-line-injection`.
- Validate every argv token against a control-character-free allowlist
  (`ARGV_SAFE`) and bound length at register time and inside
  `executeCheck`. Legacy persisted monitors with string checkCommand
  are skipped at load with a warning rather than crashing the service.
- Zod schema (`LongRunningMonitorConfigSchema.checkCommand`) and the
  `POST /api/monitors` handler now require a non-empty string array,
  with a clearer 400 error pointing at the new shape.
- Regex sanitizer: `safeCompileRegex()` additionally rejects any input
  containing control characters via an ALLOWED_REGEX_CHARS allowlist.
  This doubles as a CodeQL sanitizer for `js/regex-injection`.
- Refresh `config.example.yaml` monitor example to argv form with a
  note about shell semantics.

Resolves the two new alerts (#29 `js/regex-injection`,
#30 `js/command-line-injection`) flagged on PR #46.

* fix(monitor): constrain checkCommand program to an allowlist

Argv-only invocation alone still let `execFile` spawn any binary
reachable from `PATH`, which CodeQL correctly flags as a
command-injection sink. Gate the program before it reaches `execFile`:

- Bare names must be in ALLOWED_PROGRAMS (curl, wget, ssh, jq, grep,
  awk, sed, cat, tail, head, nvidia-smi, kubectl, docker, podman).
  Extending the list is a deliberate code change, not a config change.
- Absolute paths / `~/...` must resolve under a trusted prefix
  (`/usr/local/bin/`, `/usr/local/sbin/`, `/opt/`, `$HOME/bin/`,
  `$HOME/.local/bin/`, `$HOME/scripts/`, `$HOME/.openswarm/monitors/`).
- `..` is rejected outright to prevent traversal tricks against the
  prefix checks.
- Validation runs both inside `isValidArgv` and again at the call site
  in `executeCheck`, so the program value flowing into `execFile` is
  always vetted — this is what CodeQL needs to see as a sanitizer.

Resolves the remaining CodeQL alert #31 `js/command-line-injection`
on PR #46.
Higher placement means visitors see the Ko-fi link before diving into
feature docs. Removed the duplicate block above License; the tagline
and intro paragraph still follow immediately after so the top of the
page reads naturally.
@pull pull Bot locked and limited conversation to collaborators Apr 20, 2026
@pull pull Bot added the ⤵️ pull label Apr 20, 2026
@pull pull Bot merged commit 422a06f into danielabelski:main Apr 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant