BoundBench

career-ops

Open-source AI job-search system: a prompt pack and Node scripts that run inside your AI coding CLI to scan job boards, score postings against your CV, tailor CVs and track applications.

github.com/career-ops-hq/career-ops · 2026-10-04 · a156d4d

Defense-in-depth score

2.1 / 10

Minimal

career-ops is mostly prompts that steer your AI coding CLI, plus well-engineered scripts. The scripts include SSRF-hardened job scanners and an apply helper that never submits. There is no mail transport, and plugins are pinned to exact commits and hash-locked. Safety in the agent loop itself rests on the host CLI and on instructions in AGENTS.md: untrusted job postings share a session with your CV, your shell and the network, and nothing in code stops a hijacked session from leaking data or acting. The biggest risks are prompt injection from postings, model-written house rules and inbox items that re-execute in every session, and a documented batch runner that launches Claude with --dangerously-skip-permissions on the host.

Key gaps (6)

  1. The agent runs with the user's full ambient authority and passes the whole environment to subprocesses and plugins, so a hijacked session holds everything the user holds. C1 · Identity & least privilege
  2. Self-update and plugin-enable consent is a --confirm CLI flag the agent can pass itself, so career-ops' own gates can be self-approved; the batch runner also defaults to --dangerously-skip-permissions. C2 · Approval gates
  3. Model-driven execution (scripts, Playwright, headless batch workers with permissions skipped) runs directly on the host as the user, with no isolation boundary. C4 · Code-execution isolation
  4. Untrusted job postings, pages and emails share a session with the user's CV/PII, shell and network access, guarded only by prompt instructions, so a successful injection can leak data and act unattended. C5 · Untrusted input blast radius
  5. Model-written modes/_custom.md and the append-anywhere agent inbox are re-loaded as binding instructions every session. C6 · Memory, context & configuration integrity
  6. Enabled plugins are imported into the career-ops process with the whole process.env reachable, so a malicious or compromised plugin gets everything the scripts hold. C7 · Third-party extensions

Criteria

C1 Identity & least privilege

Minimal 0.00 / 1.00

career-ops has no identity of its own. It runs inside your AI coding CLI as your OS user, and the scripts it tells the agent to run inherit your full environment. The job sources it scans are public and need no login, and no credential is required by default. But nothing narrows what the agent's shell session can reach: your git, cloud and SSH credentials stay reachable, and plugin code gets all of process.env. A hijacked session therefore holds everything you hold.

C2 Approval gates

Minimal 0.05 / 1.00

career-ops ships no approval gate of its own. In the interactive mode it relies on the host CLI's permission prompts. Those prompts are not part of this repository and are not credited here. Its own consent checks, for applying a self-update and for enabling a plugin, are passed by a --confirm command-line flag that the agent can add itself. The documented batch runner turns the host's prompts off by default with --dangerously-skip-permissions. What career-ops gets right is the reach of its own code: no script submits an application or sends email, and the updater keeps a backup branch with rollback.

C3 Tool & action scoping

Minimal 0.40 / 1.00

The network code career-ops owns is careful. Scanner providers use per-provider host allowlists, refuse redirects, and check resolved IP addresses against private ranges at DNS time. Plugin HTTP goes through an HTTPS host allowlist that re-checks redirects. The Playwright browser paths are weaker; their address guard does not cover every path. And the workflow drives everything through a general shell with write and network tools on by default. The opt-in web UI adds per-worker tool allowlists (read-only and no-network scopes for PDF and research), but its evaluation workers still get unrestricted Bash and WebFetch.

C4 Code-execution isolation

Minimal 0.15 / 1.00

Nothing career-ops runs is isolated. The scripts, the Playwright automation and the headless batch workers all run on the host as the user. The batch workers also run with the host CLI's permission prompts disabled. The shipped Docker setup is a compatibility option, not a sandbox: the container runs as root, mounts the whole project read-write, has open network access, and receives your API keys. The agent's own shell still runs on the host anyway.

C5 Untrusted input blast radius

Minimal 0.25 / 1.00

career-ops reads untrusted text all day: job postings, company pages, application forms and recruiter emails. The defence against injected instructions in that text is a strongly worded section of AGENTS.md telling the model to treat it as data, and a CI check that the warning text appears in every mode. Community plugin skill text is printed under an UNTRUSTED banner, but postings and pages reach the model unmarked. Those same sessions hold your CV and personal details and have network and shell access. Nothing in the code stops a hijacked session from leaking that data or acting on it.

C6 Memory, context & configuration integrity

Minimal 0.10 / 1.00

career-ops is built to remember. The model is told to write your lasting preferences and 'automations' into modes/_custom.md, and every mode loads that file as binding instructions. data/agent-inbox.md is a queue of requests that any script or tool can append to, and the agent runs the open items top to bottom. Neither file is validated, tagged with its source, or gated. A single injection that lands in either one fires in every later session. Separately, plugin enablement from workspace configuration is not integrity-protected.

C7 Third-party extensions

Minimal 0.38 / 1.00

Plugins are off by default. The community registry pins every plugin to an exact 40-character commit. Installation clones that commit with risky git transports disabled, runs a static audit, and records a sha256 hash of every file. Changed files load only if the version number changed; if allowed hosts or keys expand, the user must consent again. The weak points: a version bump re-pins quietly without fresh consent, enabling is a --confirm flag the agent can pass, and the consent flow is not tamper-resistant in other respects. Plugins also run inside the same Node process with full access to process.env.

C8 Secrets & sensitive-data protection

Minimal 0.30 / 1.00

No credential is required by default. Optional LLM API keys live in a plaintext, gitignored .env file in the project directory. Every script and subprocess can read them, and so can the agent through its shell. Some masking exists: plugin log output redacts the plugin's keys, one provider masks a URL token, and Gemini error messages strip the key. There is no telemetry anywhere. Your CV and personal details go to whichever model provider you chose, which is the tool's purpose.

C9 Audit & traceability

Minimal 0.25 / 1.00

career-ops keeps records of outcomes, not of agent actions. There is a status-change ledger (status-log.tsv), a scan history, per-worker stdout logs for batch runs, and the reports themselves. The detailed record of what the agent ran is the host CLI's transcript, which career-ops neither owns nor protects. All of these files sit in the project directory, where the agent can edit them. If the ledger write fails, the status change still happens and only a warning is printed.

C10 Limits & kill switch

Minimal 0.25 / 1.00

career-ops sets no session limit of its own. Its network fetches time out after 10 seconds, and the OpenRouter runner caps each model call at 15 seconds and 8,192 output tokens. The batch runner defaults to one worker, two retries, and a pause file. But a headless batch worker has no wall-clock, step or cost cap, and the interactive session runs as long as the host allows.