From oats-skills
Reviews security for oats meeting app changes touching Tauri invoke, file paths, OAuth, session tokens, capabilities, sidecar, and deep links. Run before opening a PR.
How this skill is triggered — by the user, by Claude, or both
Slash command
/oats-skills:oats-securityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
oats records meetings (highly sensitive audio + transcripts), holds an auth session, and
oats records meetings (highly sensitive audio + transcripts), holds an auth session, and
runs a native sidecar — so changes near the surfaces below deserve a deliberate security
pass. Use this alongside superpowers' requesting-code-review and the built-in
/security-review command. Default to suspicion: if a change touches a surface here,
walk its checklist before opening the PR.
invoke boundary — every #[tauri::command] in src-tauri/src/commands.rs
is reachable from any loaded webview (incl. the external OAuth page). Treat command
arguments as untrusted input.read_recording_audio /
note read-write take a path/id and hit std::fs::read / read_to_string /
create_dir_all. Path-traversal risk: a malicious id (../../) could escape
~/.ariso/recordings/. Confirm ids are validated and paths are built from
storage::recordings_dir(...), never concatenated from caller-supplied absolute paths.auth.googleSignIn → /oauth2/prepare-state (CSRF state),
an oauth external webview (WebviewUrl::External), result delivered via the
oauth-result event. Verify: state is generated server-side and checked; the external
window is scoped to the expected origin; the returned sessionToken is never logged or
emitted to other windows.http_client()
(AUTHORIZATION header). The @tauri-apps/plugin-store (settings.json) is
plaintext on disk — fine for prefs (backend, onboarded), not for secrets.
Confirm no token/secret is written to plugin-store; secrets belong in the OS keychain
or backend-managed session.src-tauri/capabilities/default.json is least-privilege
and should stay that way. Note the scoped opener:allow-open-url (only
x-apple.systempreferences:*). Don't broaden a permission or add a window without
justifying it; never add a wildcard URL/open scope.app.opener().open_url(...) and notification deep links
(meeting_notifications.rs carries a URL as the request id). Only open URLs whose
origin you control (the web.ari.ariso.ai web app). Validate scheme + host before
opening anything derived from server data or a notification payload.ariso-stt is spawned with --audio <path> etc. It uses
Command::new + .arg(...) (no shell), so keep it that way — never route sidecar
args through a shell string or interpolate untrusted data into one.DEFAULT_API_BASE_URL is compiled per feature; release builds
intentionally ignore env overrides (ARISO_DESKTOP_API_BASE_URL). Don't add a
runtime override path that would let an attacker repoint the API. Keep https:// in
non-local builds; http://localhost is dev-only.reqwest, telemetry, fetch) on a
code path reachable in Local mode breaks the product's core promise. Gate network I/O
behind the cloud backend explicitly.For a change touching any surface above, confirm:
invoke command validates and bounds every argument (esp. paths/ids)./security-review (or requested review) on the diff.When this surfaces a real finding, fix it via oats-tauri (backend) / oats-vue
(frontend) and re-verify. For runtime reproduction, use oats-debugging.
Blocks Edit/Write/Bash actions until Claude investigates importers, data schemas, and user instructions. Improves output quality by forcing concrete facts before edits.
npx claudepluginhub ariso-ai/oats --plugin oats-skills