* fix: harden agentctl bind, git clone args, and powershell sound escaping
Three LOW-severity defense-in-depth hardening fixes with PoC + regression tests:
- notifications: escapePowerShell now neutralizes backtick and `$` in addition
to `"`, defusing `$(...)` sub-expression and `$var` injection through an
operator-supplied SoundFile path interpolated into the powershell `-c` script.
- office/skills: git clone for git-sourced skills now passes a `--`
end-of-options separator before the source locator (matching configloader),
so a `-`-prefixed locator can never be parsed as a git flag.
- agentctl: new Config.ListenHost() binds the control server and per-instance
listeners to loopback only when no AuthToken is configured (auth disabled),
so the unauthenticated command/shell/process routes are never reachable
beyond localhost. The normal nonce-handshake flow (incl. Docker) always has
a token and keeps binding all interfaces.
* test: make PoC tests flip and drop indexOf coupling
Address review feedback on the security-hardening PoCs:
- system_provider PoC now demonstrates the PowerShell sub-expression injection
against a legacyEscapePowerShell copy of the unfixed function and asserts the
current escaper defuses it, so the PoC genuinely flips instead of passing
trivially against fixed code (a substring match on `$(` matched the escaped
form too).
- materialization PoC + regression test use stdlib slices.Index instead of a
custom indexOf defined in the PoC file, removing the coupling where deleting
the PoC file would break the regression test.
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
* fix: prevent AppleScript injection RCE in macOS notifications
buildAppleScript escaped only the double-quote in notification title/body
and interpolated the result into an `osascript -e` string literal. A raw
trailing backslash defeated that escaping: `\"` became `\\"`, which
AppleScript reads as an escaped backslash plus a real closing delimiter,
so the `display notification "..."` literal terminated early and any
following text (e.g. `do shell script`) executed on the host.
Notification title/body come verbatim from untrusted external-integration
issue titles (Sentry/Linear/Jira) with no sanitization, so an attacker who
can raise an issue in a connected workspace could achieve RCE on the macOS
host when the office session reached WAITING_FOR_INPUT.
Replace string interpolation with argv passing: title/body are delivered as
`run` handler arguments (item 1/2 of argv) and never touch the AppleScript
source, so no escaping is required. Add a proof-of-concept test documenting
the legacy breakout and a regression guard asserting the fixed builder never
leaks attacker text into script fragments.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: terminate osascript option parsing before notification argv
Passing untrusted title/body as trailing arguments still let a title that
looks like an osascript flag be consumed as an option: a title of "-e" would
turn the body into another script fragment, reopening the AppleScript
injection. Add a `--` option terminator before title/body so untrusted text
always lands in argv. Extend the regression tests to cover the flag-like
title vector.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: prove single-line AppleScript payload is host RCE, not just DoS
Add a single-line (Jira/Linear, no newline) PoC alongside the multi-line
Sentry payload. A newline statement separator is only needed for a SECOND
statement; the single-line payload instead injects an expression
`& (do shell script (...))` into the display-notification body argument, so
the command executes as a side effect while the line stays one valid
statement. Both shapes are host code execution. Extend the regression guard
to prove the argv fix neutralizes both.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>