Back to skill

Security audit

simplepractice-fpx

Security checks for vulnerabilities and agentic risk

Overview

The skill is openly focused on reading a user’s SimplePractice portal data, but it handles medical session credentials and includes an optional browser-capture setup that grants broader access than the shown workflow needs.

Install only if you are comfortable giving local tools access to your own SimplePractice session and medical portal data. Prefer the magic-link curl flow over browser cookie capture when possible, restrict use to your own account or an authorized dependent account, keep the cookie jar private, remove the fpx profile after use, and avoid the unpinned global CLI path unless you have independently verified the package and extension.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:130
Finding
Browser integration requests credential-access capabilities beyond functional requirements<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:130-145` **Vulnerability Type**: Excessive browser credential and storage access **Risk Level**: Medium ### Vulnerable Code ```sh fpx profile declare simplepractice \ --cookie simplepractice-session --cookie client-portal-session \ --local-storage client-portal-session --local-storage stored-email \ --capture-header cookie@$SP_HOST fpx get "https://$SP_HOST/" -p simplepractice >/dev/null # prints a pair code → approve in Transporter ``` The later workflow consumes only the `simplepractice-session` cookie: ```sh SESSION=$(fpx cookies simplepractice-session -p simplepractice \ --storage-subdomain "${SP_HOST%%.*}" | jq -r '.["simplepractice-session"]') printf '#HttpOnly_%s\tFALSE\t/\tTRUE\t0\tsimplepractice-session\t%s\n' "$SP_HOST" "$SESSION" > "$SP_JAR" chmod 600 "$SP_JAR" ``` ### Technical Analysis The browser profile is granted access to two cookies, two local-storage values, and the complete `Cookie` request header for the selected portal host. However, the documented extraction procedure only reads `simplepractice-session`. The following capabilities therefore exceed the demonstrated minimum requirements: - Access to the `client-portal-session` cookie - Access to the `client-portal-session` local-storage value - Access to the `stored-email` local-storage value - Capture of the complete `Cookie` header Full Cookie-header capture is especially broad because it may expose every cookie sent to the host, including credentials or state values unrelated to this Skill. The local-storage grant also exposes identifying information through `stored-email`. Because the Skill handles a medical portal, these grants cross a particularly sensitive trust boundary. Any compromised, malicious, or defective browser extension or CLI component operating under the approved profile could read more authentication and personal information than the stated cookie-seeding operation requires. # ...[truncated 1399 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Apply strict least privilege to the browser profile: 1. Declare only the cookie that the workflow actually consumes: ```sh fpx profile declare simplepractice \ --cookie simplepractice-session ``` 2. Remove both local-storage grants unless a documented, tested workflow specifically requires them. 3. Remove `--capture-header cookie@$SP_HOST`; direct access to the named session cookie is sufficient for the shown procedure. 4. If compatibility with alternative portal configurations requires another cookie or storage key, place it in a separate opt-in procedure rather than granting it by default. 5. Clearly document that pairing grants browser credential access and that users should remove the profile after exporting the required cookie. 6. Recommend revoking the portal session after use and storing the generated cookie jar only with mode `0600`, as the Skill already partially instructs. 7. Avoid displaying, logging, or placing session values in shell history, command-line arguments, or shared temporary locations. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:126
Finding
Unpinned globally installed dependency receives access to medical portal credentials<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:126` **Vulnerability Type**: Unpinned third-party global dependency **Risk Level**: Medium ### Vulnerable Code ```sh Requires the **Transporter** extension and `npm i -g @fetchproxy/cli`. ``` ### Technical Analysis The installation command retrieves the current release of `@fetchproxy/cli` from the configured npm registry and installs it globally without: - Pinning a reviewed package version - Verifying package integrity - Using a lockfile - Constraining installation to the project or an isolated environment An npm package may execute lifecycle scripts during installation and arbitrary code when invoked. Global installation increases exposure beyond this Skill's directory. The resulting CLI is subsequently paired with a browser extension and granted access to authentication cookies, local-storage values, and request headers for a medical portal. The effective code executed by users can therefore change after the Skill has been reviewed. If the package, publisher account, registry path, or a future release is compromised, the newly installed code could execute with the user's local privileges and gain access to sensitive browser session material. ### Attack Path 1. An attacker compromises the npm package, its publisher account, its dependency chain, or a future package release. 2. The user follows the Skill and runs `npm i -g @fetchproxy/cli`. 3. npm retrieves the latest compromised release because no version or integrity value is specified. 4. Malicious code executes through an installation lifecycle script or when the `fpx` command is invoked. 5. The user pairs the tool with the Transporter extension and approves access to portal credentials. 6. The compromised component reads session material and may transmit it to attacker-controlled infrastructure. 7. A reusable bearer session may then be used to access the medical portal with the user's current portal privileges. The audit found no ...[truncated 829 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the CLI to a specific, reviewed version instead of installing the latest release: ```sh npm install --global @fetchproxy/cli@<reviewed-version> ``` 2. Publish and verify the expected npm integrity digest or package archive checksum through a trusted channel. 3. Document the official package publisher, registry URL, browser-extension publisher, and expected extension identifier so users can detect spoofed packages. 4. Prefer a project-local or isolated installation over a global installation, such as a locked helper project or disposable environment. 5. Review transitive dependencies and npm lifecycle scripts for the pinned release. 6. Configure npm to reject unexpected lifecycle scripts where compatible with the package. 7. Update the pinned version only after reviewing release changes and refreshing integrity metadata. 8. Reduce the browser capabilities granted to the dependency as described in the separate least-privilege finding. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
> This is protected health information — your own therapy/medical record.
> Treat the cookie jar as a credential: it is a full-access bearer token for
> the portal. Keep it `chmod 600`, out of git, and off shared machines.

## Your practice subdomain
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
export SP_API="https://$SP_HOST/client-portal-api"
export SP_JAR="$HOME/.simplepractice-cookies"

# curl creates a cookie jar world-readable (644). This one holds a live
# session for a medical record, so create it 0600 BEFORE curl ever writes it.
[ -e "$SP_JAR" ] || ( umask 077; : > "$SP_JAR" )
chmod 600 "$SP_JAR"
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# curl creates a cookie jar world-readable (644). This one holds a live
# session for a medical record, so create it 0600 BEFORE curl ever writes it.
[ -e "$SP_JAR" ] || ( umask 077; : > "$SP_JAR" )
chmod 600 "$SP_JAR"
```

## The four headers — all of them, on every call
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# curl creates a cookie jar world-readable (644). This one holds a live
# session for a medical record, so create it 0600 BEFORE curl ever writes it.
[ -e "$SP_JAR" ] || ( umask 077; : > "$SP_JAR" )
chmod 600 "$SP_JAR"
```

## The four headers — all of them, on every call
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
## The four headers — all of them, on every call

```sh
sp() { curl -s -b "$SP_JAR" -c "$SP_JAR" \
  -H 'Api-Version: 2026-05-25' \
  -H 'Application-Build-Version: 0.0.0' \
  -H 'Application-Platform: web' \
Confidence
96% confidence
Finding
The skill defines a reusable curl helper that sends an authenticated session cookie to a remote SimplePractice endpoint on every invocation. Because the cookie grants full access to protected health information, any misuse of the helper, hostile parameter injection via "$@", or use against an attacker-controlled host could transmit highly sensitive data or credentials off-box.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
`jq 'select(.attributes.hasDocumentPdf)'` are BOTH true for `"false"`.
  Compare against the string: `select(.attributes.hasDocumentPdf == "true")`.
  A card's `isDefault` is the same — so do not assume a JSON boolean anywhere
  in this API without checking the value you actually get back.
- `billing-items` is polymorphic: `.data[].type` tells you which of
  invoice / statement / superbill / receipt / payment a row actually is, and
  the attribute set differs per type. `.meta.endBalance` accompanies every
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This reference materially enables authenticated extraction of highly sensitive client-portal data, including appointments, billing artifacts, identity details, documents, and saved-card metadata, and it also documents auth flows and session handling in operational detail. While the content appears intended as legitimate interoperability documentation, it lacks strong privacy, authorization, and account-impact guardrails, making misuse easier for anyone with access to a session cookie, magic link, or delegated login.

Static analysis

No suspicious patterns detected.