# Shoulder Transparency Report **Product:** Shoulder **Version:** v0.0.1 - Commit `6e508346` (Beta Release line) **Report Date:** 2026-05-15 **Security Contact:** security@shoulder.dev --- ## Table of Contents 1. [Executive Summary](#1-executive-summary) 2. [Product Overview](#2-product-overview) 3. [Data Handling and Privacy Commitments](#3-data-handling-and-privacy-commitments) 4. [Network Behavior](#4-network-behavior) 5. [Filesystem Behavior](#5-filesystem-behavior) 6. [Execution and Safety Boundaries](#6-execution-and-safety-boundaries) 7. [Logging, Diagnostics, and Crash Reporting](#7-logging-diagnostics-and-crash-reporting) 8. [Security Measures](#8-security-measures) 9. [Configuration Controls](#9-configuration-controls) 10. [Verification Notes](#10-verification-notes) --- ## 1) Executive Summary **What Shoulder Is:** Shoulder is a local-first static security scanner for source code and software supply chains. It detects application vulnerabilities through taint-flow analysis, pattern matching, and security-control validation; it scores third-party dependencies, Dockerfiles, GitHub Actions references, and MCP server entries against Shoulder's supply-chain intelligence; and it produces a single "trust" verdict the user (or an AI coding assistant) can act on before merging, installing, or running code. Supported languages include JavaScript/TypeScript, Python, Go, plus Dockerfile and Kubernetes/GitHub Actions YAML. Shoulder ships as a native CLI (`shoulder` / legacy `shouldersec`) and is also distributed via the `@shoulderdev/cli` npm package, which downloads the matching native binary on install. **Privacy Posture:** All source-code analysis — parsing, AST/CFG/DFG graph construction, taint propagation, rule evaluation, and finding generation — runs entirely on the user's machine. Source code, scan findings, and analysis intermediates do not leave the host. Network use is limited to (a) optional update checks and (b) opt-in supply-chain features that send package metadata (ecosystem, name, version) to Shoulder's APIs to receive trust verdicts and vulnerability data. No usage telemetry is transmitted. A local-only metrics database can be disabled. The default trust scan (no Dockerfile, no GitHub Actions, no lockfile, no `--ecosystem`) makes **zero application-level outbound connections**, independently confirmed by external syscall tracing. ### Key Guarantees - Source code, scan findings, and code-graph artifacts are never transmitted off the machine. - No usage analytics, behavioral telemetry, or external crash reporting. - Source files in the scanned project are read-only — Shoulder does not modify or delete them. Confirmed by zero destructive syscalls hitting the scan target across all four traced scenarios. - Update checks are HTTPS, version-only metadata, and disabled by setting `SHOULDER_DISABLE_UPDATES=1`. - Supply-chain APIs receive only package coordinates (ecosystem, name, version, optional manifest spec) and the project's license policy — never source code. - The local gRPC and MCP integration servers bind to localhost only — no `listen()`/`bind()` to non-local interfaces observed in any traced scenario. - API base URLs are overridable (`SHOULDER_API_URL`, `SHOULDER_INTEL_URL`) for air-gapped or self-hosted deployments. - Privileged syscalls (`setuid`, `setgid`, `capset`, `ptrace`) are not invoked in any traced scenario. ### Key Limitations - Update checks run by default; users who require zero outbound traffic must opt out explicitly. - Supply-chain trust and package-vulnerability commands (`trust --ecosystem`, `trust deps`, `packages`, `decide`) require network access by design; they cannot produce verdicts offline. - Scanning a project that contains a `Dockerfile`, a `.github/workflows/*.yml`, or a lockfile under `--ecosystem` triggers contacts to `api.shoulder.dev` and/or `intel.shoulder.dev`. Both are documented and bucketed in §4. - The local gRPC server (used for IDE / MCP integration) does not use TLS — it binds to `localhost` and is not intended for network exposure. - No formal third-party security audit has been published for this codebase. --- ## 2) Product Overview ### Primary Functions 1. **Static Application Security Testing (SAST):** Detects vulnerabilities by tracing taint flow from untrusted sources to dangerous sinks, plus rule-based pattern matching against a TreeSitter-built code graph. 2. **Security Control Validation:** Verifies presence of authentication middleware, rate limiting, secure headers, CSRF protection, and similar configuration controls. 3. **Supply-Chain Trust & Vulnerability Scanning:** Sends package coordinates to Shoulder's APIs and returns trust decisions, CVE data, license findings, version recency, and end-of-life data for project dependencies, Dockerfile base images, GitHub Actions references, and MCP server entries. 4. **Test Impact Analysis:** Statically maps changed code to affected tests using the code graph. 5. **Capability Scanner:** Classifies packages and source trees by the *capabilities* they exhibit (lifecycle scripts, native binaries, exfil patterns, etc.) and correlates capabilities into supply-chain risk signals. ### Supported Languages & Frameworks | Language | Frameworks | |-----------------------|------------------------------------------------------------------| | JavaScript/TypeScript | Express, Fastify, Koa, Next.js, NestJS, tRPC | | Python | Flask, Django, FastAPI | | Go | Gin, Chi, Echo, Fiber, Gorilla, net/http | | Configuration | Dockerfile, Kubernetes YAML, GitHub Actions | ### Deployment Modes | Mode | Description | |------------------|-----------------------------------------------------------------------------| | **CLI (default)**| One-shot scan via `shoulder scan ` / `shoulder trust ` | | **npm wrapper** | `@shoulderdev/cli` npm package; postinstall downloads the matching native binary from a release asset | | **Serve mode** | Long-running localhost gRPC server for incremental rescans | | **MCP server** | Model Context Protocol server (stdio JSON-RPC) for AI-assistant tooling | | **LSP server** | Language Server Protocol provider for editor diagnostics | | **Test impact** | Git-aware test selection for CI | | **Trust / Trust-Diff / Trust-Deps** | Supply-chain trust verdicts at project, diff, and individual-package granularity | ### Typical Scan Workflow 1. User runs `shoulder trust .` (or `shoulder scan .`) from the project root. 2. The scanner walks the project, parses files with TreeSitter, and builds an in-memory code graph (AST + CFG + DFG). 3. The taint analyzer propagates from configured sources to sinks; rules emit findings. 4. If supply-chain inputs are present (Dockerfile, GitHub Actions, lockfile, or explicit `--ecosystem`), package coordinates are sent to Shoulder's APIs and verdicts returned. 5. Results are rendered to console, JSON, or SARIF and written to stdout or `--output`. 6. Findings, source content, and graph artifacts remain local. No portion of the source is uploaded. --- ## 3) Data Handling and Privacy Commitments ### Types of Input Data Processed | Data Type | How Processed | Where Stored | |--------------------------|------------------------------------------------------------|----------------------------------| | Source code | Parsed in-memory via TreeSitter; never transmitted | Memory only during analysis | | Code graph (AST/CFG/DFG) | Held in memory during the scan | Memory only | | Dependency manifests | Parsed for ecosystem/name/version of declared packages | Memory; coordinates sent to API on `trust --ecosystem`, `trust deps`, `packages`, `decide` | | Dockerfile / GHA / MCP entries | Parsed for image refs, action refs, MCP server identities | Memory; coordinates sent to API when supply-chain features are active | | Configuration files | Read for framework detection | Memory only | | Custom security rules | Loaded from `.shoulder/rules/` if present | Project directory (user-managed) | | Local metrics | Aggregate scan counts/durations/severity tallies | Local SQLite (see § 7) | | False-positive history | User-dismissed findings | `.shoulder/fp_history.json` | ### Does Data Leave the Machine? | Scenario | Data Transmitted? | Destination | |---------------------------------------|-------------------|---------------------------------| | `scan` (SAST) | No | — | | `trust` *without* supply-chain inputs | No | — (verified `trust-offline`) | | `trust --ecosystem` (any lockfile/Dockerfile/GHA present) | Yes — package metadata only | Shoulder API / Intel API | | `trust deps ` | Yes — package metadata only | Shoulder API / Intel API | | `trust-diff` | Yes — coordinates for added/changed packages | Shoulder API / Intel API | | `packages` / `decide` | Yes — package metadata only | Shoulder Intel API | | Update check | Yes — version + OS only | Shoulder API | | MCP server (stdio JSON-RPC) | No | local process | | gRPC serve mode | No | localhost only | ### Local Storage | Location | Purpose | Retention | |--------------------------------------------------|--------------------------------------------------|----------------------------------------| | `~/.shoulder/logs/` | Per-session debug logs | Most recent 10 files | | `~/.shoulder/sessions.json` | Session ID ↔ project mapping | Persists | | `~/.shoulder/servers.json` | Local server registry | Server lifetime | | `~/.shoulder/` lock files | Autostart/serve coordination | Released after operation | | `.shoulder/fp_history.json` (project-local) | False-positive dismissals | 12 months, max 10,000 records | | `.shoulder/metrics.db` or `~/.local/share/shouldersec/metrics/project-.db` | Local-only scan metrics | Until user deletes; disabled with env var | ### What Shoulder Does NOT Collect - **No usage analytics or telemetry transmitted.** A local SQLite metrics database tracks scan counts and durations on the user's machine; it is never uploaded. - **No user tracking** — no user IDs, no session correlation across machines. - **No code transmission** — source content, AST, code graph, and findings stay local. - **No advertising identifiers, no behavioral fingerprinting.** - **No external crash reporting** — no Sentry, Bugsnag, Datadog, or similar. - **No clipboard, keystroke, or screen capture.** --- ## 4) Network Behavior | Purpose | When | Destination | Data Sent | Data Received | Disable? | Security | Verified via | |------------------------------------|-----------------------------------------------|------------------------------------------------------------------------|-----------------------------------------------------------------|-----------------------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------|--------------| | Update check | At CLI startup (throttled) | `https://api.shoulder.dev/v1/cli/releases/{os}/latest` | OS identifier; `User-Agent` containing the current version | Latest version, download URL, SHA256, changelog, enforcement | `SHOULDER_DISABLE_UPDATES=1` | HTTPS, system CA, short timeout | Update calls are not exercised by the captured scenarios (`SHOULDER_DISABLE_UPDATES=1` is set during capture); confirmed absent in `evidence/74797ae9-linux/trust-offline/summary.md` (0 outbound connects). | | API health probe | On `health_check` MCP tool / readiness check | `https://api.shoulder.dev/v1/health` | None (GET) | Status payload | Don't invoke | HTTPS, system CA | Not exercised by traced scenarios. | | Package vulnerability + license scan | `trust --ecosystem`, `trust deps`, `packages`, MCP `scan_packages` | `https://api.shoulder.dev/v1/packages/scan` (legacy: `/v1/packages/batch/vulnerabilities`, `/v1/packages/{ecosystem}/{name}/vulnerabilities`) | Ecosystem, package name, version, dev/prod flag, license policy | CVE list, CVSS, license findings, deprecation, fix versions | Don't invoke `trust --ecosystem` / `trust deps` / `packages` | HTTPS, optional Bearer (`SHOULDER_API_KEY`), timeout | `evidence/74797ae9-linux/trust-ecosystem-pkg/summary.md` — `api.shoulder.dev` appears in DNS queries when a `package-lock.json` is present. | | Ecosystem version intelligence | Trust scans, Dockerfile / Kubernetes / GHA analysis | `https://intel.shoulder.dev/api/v1/versions/{ecosystem}/{name}[?version=…]` | Ecosystem, package or image name, optional version | Latest version, EOL, version-distance metrics | Don't invoke trust / Dockerfile / GHA paths | HTTPS, optional Bearer, timeout | `evidence/74797ae9-linux/trust-ecosystem-gha/summary.md` and `trust-ecosystem-pkg/summary.md` — `intel.shoulder.dev` appears in DNS queries only when GHA refs or a lockfile are present. | | Trust decision (single) | `decide` / IDE extension trust UI / GHA action-ref resolution | `https://intel.shoulder.dev/api/v1/decide` (and `/decide/{owner}/{repo}/{ref}` for GitHub Actions) | Package coordinates | Trust verdict + rationale | Don't invoke `decide` / avoid `.github/workflows/` | HTTPS, optional Bearer | `evidence/74797ae9-linux/trust-ecosystem-gha/summary.md` — `intel.shoulder.dev` queried when GHA workflow file is present. | | Trust decision (batch) | `decide` (multi-package), trust scans | `https://intel.shoulder.dev/api/v1/decide/batch` | Ecosystem + array of `{name, version}` | Per-package trust verdicts | Don't invoke `decide` | HTTPS, optional Bearer | Covered by the same DNS query observation as single-decide. | | Trust decision with spec | Package-spec resolution | `https://intel.shoulder.dev/api/v1/decide/with-spec` | Package coordinates + manifest spec string | Resolved version + verdict | Don't invoke `decide` | HTTPS, optional Bearer | Same as above. | | Binary update download | Manual update flow only | GitHub release artifact URL returned by `/v1/cli/releases/...` | HTTP GET (no body) | Binary archive (.tar.gz) | N/A (only after explicit update) | HTTPS, SHA256 verified before swap | Not exercised by traced scenarios. | ### Security Controls for Network Calls - All API calls use HTTPS via Go's standard `net/http` client; the system CA bundle is used. - Auth, when configured, is `Authorization: Bearer ${SHOULDER_API_KEY}` — never a query parameter. - Bearer tokens are masked in logs and never echoed to stdout. - Rate limiting (HTTP 429) from the server is handled gracefully by the client. - Both API base URLs are overridable: `SHOULDER_API_URL` (application/CLI API) and `SHOULDER_INTEL_URL` (supply-chain intel API). - External tracing confirms no listen/bind to network families and no privilege-changing syscalls across the traced scenarios. ### Operating Offline The following work fully offline: - All SAST scanning (taint analysis, rule matching, framework detection, custom rules) - `trust` against a project with no Dockerfile, no `.github/workflows/`, no lockfile, and no `--ecosystem` flag (verified — `trust-offline` scenario shows 0 application connects) - Report generation (console, JSON, SARIF) - LSP and gRPC localhost integrations - Local metrics The following require network: - `trust --ecosystem`, `trust deps`, `trust-diff`, `packages`, `decide` - Dockerfile / Kubernetes / GitHub Actions analysis under `trust` (these inputs cause `intel.shoulder.dev` calls automatically) - Update checks and binary updates --- ## 5) Filesystem Behavior ### Read Operations | Location | Purpose | |-------------------------------------------|------------------------------------------------------------------| | Project directory (recursive) | Source code; respects user-supplied excludes and `exclude_directories` forwarded to the capability scanner | | Embedded rules + `.shoulder/rules/` | Built-in and project-local YAML rules | | `~/.shoulder/` | User configuration, sessions, server registry | | `.shoulder/` (project-local) | Project configuration, custom rules, FP history, optional metrics DB | | `.git/` (read-only, enclosing repo) | Used by `trust-diff` for diff/baseline ref resolution | Shoulder does not read SSH keys, GPG keyrings, browser cookies, system credential stores, or arbitrary `~/` files. External tracing buckets all `openat` reads into five categories. Counts from `evidence/74797ae9-linux/` (Linux, commit `74797ae9`): | Read bucket | `trust-offline` | `trust-ecosystem` | `trust-ecosystem-gha` | `trust-ecosystem-pkg` | Notes | | --- | ---: | ---: | ---: | ---: | --- | | `system` | 79 | 238 | 237 | 238 | OS libraries, `/etc`, `/usr`, `/lib`, `/proc`, `/sys`, `/dev`, `/run`, `/tmp` | | `repo_git` | 76 | 76 | 76 | 76 | Enclosing repo's `.git/` (read-only context) | | `config` | 6 | 39 | 21 | 21 | `.shoulder/` config + cache directory | | `scan` | 541 | 556 | 545 | 524 | The user's scan target subtree | | `other` | 728 | 728 | 728 | 744 | Flagged for review | The `other` bucket is non-trivial (~728–744 entries per scan) and is currently flagged for review. It includes reads outside the canonical five categories on a Linux host — most plausibly per-thread file-descriptor metadata under `/proc/self/task/...` that the trace sanitiser does not yet bucket. No verbatim paths are published; the raw traces are retained internally for audit. ### Write Operations | Location | What's Written | When | Retention | |------------------------------------------------------------------|------------------------------------------------|---------------------------------------|----------------------------| | `~/.shoulder/logs/{session}_{date}.log` | Per-session debug log (TeeLogger) | Every CLI invocation | Most recent 10 files | | `~/.shoulder/sessions.json` | Session ID ↔ project mapping | Session start | Persists | | `~/.shoulder/servers.json` | Local server registry | Server start/stop | Server lifetime | | `~/.shoulder/` lock files | Autostart/serve coordination | During lifecycle operations | Released after operation | | `.shoulder/fp_history.json` (project-local) | False-positive dismissals | On dismissal | 12 months, max 10,000 | | `.shoulder/metrics.db` (or user data dir) | Local SQLite metrics | During scans | Until cleared / disabled | | `--output` user-specified path | Scan/trust/report results (JSON, SARIF, text) | When `--output` provided | User-managed | | `~/.claude/...`, `~/.cursor/...`, `~/.codex/...`, `~/.goose/...` | Hook configs, MCP registration, skill files | On `install claude` / `install cursor` / `install codex` / `install goose` | Until `uninstall` | | `.claude/shoulder-bootstrap.sh`, `.shoulder/.gitignore` (project)| Bootstrap installer (portable mode only) | On `install claude . --portable` | Until removed | | System temp directory | `shoulder-update-*.tar.gz`, `shoulder-new-*` | During binary update | Removed immediately after extraction / atomic swap | Across all four traced scenarios, write-target buckets are: `config=3`, `other=1`, `stdio=5`. Writes are tightly contained: three writes into `.shoulder/`, five into stdio (console output), and a single "other" write that is the per-session log file under `~/.shoulder/logs/`. ### Source Code is Not Modified Shoulder does not write into the scan target's source tree. The only project-directory writes are confined to `.shoulder/` (false-positive history, optional metrics DB, custom-rule directory the user creates) and, in portable IDE-install mode, `.claude/shoulder-bootstrap.sh` and `.shoulder/.gitignore`. `os.Remove` / `os.RemoveAll` are used only for ephemeral temp files and short-lived git worktrees created by `trust-diff`. **External tracing confirms zero destructive operations targeting the scan tree.** Across all four scenarios, destructive syscalls (`unlink`/`unlinkat`, `rename`/`renameat2`, `truncate`/`ftruncate`) hit the scan target or unrecognised paths **0 times**. The single `unlink` observed per scenario targets the safe `config` or `system` bucket (cache atomicity). ### Deletions | What's Deleted | When | Purpose | |-------------------------------|-------------------------------------------------------|--------------------------| | Old log files | When more than 10 logs exist in `~/.shoulder/logs/` | Log rotation | | Aged FP history records | Records older than 12 months (or beyond 10,000 cap) | History pruning | | Update temp files | Immediately after extraction / swap | Cleanup | | Trust-diff git worktrees | Deferred cleanup at end of trust-diff comparison | Workspace tidy-up | --- ## 6) Execution and Safety Boundaries ### Subprocesses | Subprocess | Purpose | Trigger | Notes | |-----------------------------------------|----------------------------------------------------------|----------------------------------------|----------------------------------------------------| | `shoulder serve start` | Spawns the localhost gRPC server | `serve` / autostart | Path obtained from `os.Executable()` | | `git diff` / `git worktree` / `git clone --depth` | Diff/baseline comparison for trust-diff and sandbox | `trust-diff`, sandbox flows | Arguments passed as a slice; no shell concatenation | | `code` / `cursor` (`--install-extension shoulderdev.security`) | Editor extension install/uninstall | `install claude` / `install cursor` / `uninstall` | Hardcoded extension ID; no user input | | `sh -c ` / `cmd /C ` (serve helper) | Launch a configured wrapper command in serve mode | Internal serve-start lifecycle | Command source is the binary's own configuration | External tracing of the four customer-facing scenarios observes `git × 5` and a single `shoulder` re-exec per scenario. No other subprocesses are spawned during a default trust or trust-with-ecosystem scan. Shoulder does not execute pytest/jest or other test runners as part of test-impact analysis — that flow is purely static graph traversal. ### Untrusted Code Is Never Executed - **No project code is run.** Scanning parses files with TreeSitter; nothing is `exec`'d, `eval`'d, or `import`'d from the scan target. - **Custom rules are declarative YAML.** No script body, no embedded code execution. - **No runtime plugin loading.** All language analyzers and rule kinds are compiled into the binary. - **Sandboxed package fetch.** `sandbox.sh` for `npmjs.com` URLs downloads the registry tarball and extracts it inside the sandbox; it does **not** run `npm install` and does not invoke package lifecycle scripts. - **IDE hooks read/write JSON only.** The `install claude` / `install cursor` / `install codex` / `install goose` flows do not execute external scripts. ### Resource Controls | Resource | Control | |--------------------------------|----------------------------------------| | HTTP timeouts (update check) | Short, non-blocking | | HTTP timeouts (API/intel calls)| Context-bounded | | Autostart wait | Fixed maximum | | Lock file TTL | Fixed (prevents stale locks) | | File watch interval (serve) | Polling-bounded | | Concurrency | Worker pool sized at startup | | Capability walk skip | Lightweight trust profiles skip the capability walk entirely (avoids `~/N`-file enumeration on large targets) | ### Privileged Syscalls External tracing confirms **zero** invocations of `setuid`/`setgid`/`setresuid`/`setresgid`/`setgroups`, **zero** `capset` calls, and **zero** `ptrace` calls across all four customer-facing scenarios. --- ## 7) Logging, Diagnostics, and Crash Reporting ### What Gets Logged | Level | Content | Sensitive Data? | |-------|------------------------------------------------------|----------------------------------------| | ERROR | Fatal errors, configuration issues | No | | WARN | Recoverable issues, deprecation notices | No | | INFO | Scan progress, finding counts | File paths (relative to scan root) | | DEBUG | Graph construction, propagation steps, node counts | File paths and structural metadata | Source code content, individual finding details with snippets, and API keys are not logged at any level. Bearer tokens are masked. ### Where Logs Go | Mode | Destination | |------------------|-----------------------------------------------------| | CLI scan | stderr at the configured level | | Serve mode | stderr **and** `~/.shoulder/logs/{session}_{date}.log` (full debug regardless of console level) | | `--json` / `--sarif` | Console logging suppressed; structured output goes to stdout/`--output` | ### Crash Reporting Shoulder has no external crash reporting integration. Panics are recovered for graceful shutdown; stack traces are written to the local log only. There is no Sentry, Bugsnag, Datadog, or similar reporting client. ### Verbosity Controls | Control | Method | |---------------------------------|------------------------------------------------------| | Log level | `--log-level {error\|warn\|info\|debug}` or `-v` | | Force debug | `DEBUG=1` | | Explicit env override | `SHOULDERSEC_LOG_LEVEL` | | Silent (machine output) | `--json` or `--sarif` (auto-suppresses console logs) | ### Local Metrics `internal/metrics/` writes scan-aggregate metrics (counts, durations, severity tallies) to a local SQLite database. The database is never uploaded. Set `SHOULDER_METRICS_DISABLED=1` (or `=true`) to disable metrics collection entirely; this is the recommended setting for CI, benchmarking, and any environment where local writes should be avoided. --- ## 8) Security Measures ### Dependency Integrity - Go modules with `go.sum` checksums for reproducible builds (`go 1.25.10`). - gRPC pinned and security-bumped (see commit `5db256d0`). - TreeSitter via the official `github.com/tree-sitter/go-tree-sitter` bindings. - Built-in security rules and configuration are embedded in the binary at build time. - No runtime dependency download for the scanner itself. ### Update Verification | Check | Implementation | |------------------------|----------------------------------------------------------------------------| | Version comparison | Semantic versioning | | SHA256 checksum | Provided in the update response; verified before binary replacement | | Atomic replacement | Backup created; binary swapped atomically; rollback on failure | | Minimum version gate | Server can signal a minimum supported version and request enforcement | ### TLS and Certificate Validation | Connection | TLS | Certificate Validation | |---------------------------------------|-------------|---------------------------------------| | `api.shoulder.dev` | HTTPS | Go standard library / system CA | | `intel.shoulder.dev` | HTTPS | Go standard library / system CA | | GitHub binary download | HTTPS | Go standard library / system CA | | `registry.npmjs.org` tarball fetch | HTTPS | Go standard library / system CA | | Local gRPC server (serve / MCP) | None | N/A — bound to `localhost` only | ### Secrets Handling | Secret | Storage | Transmission | |-------------------------|------------------------------------|-----------------------------------------------| | `SHOULDER_API_KEY` | Environment variable only | `Authorization: Bearer …` header | | Tokens in logs/output | Masked | Never displayed in console or written to logs | ### Principle of Least Privilege - Source files are read-only to the scanner — verified by external tracing: 0 destructive operations against the scan tree across four scenarios. - Writes are confined to `~/.shoulder/`, `~/.cache` (when applicable), the user-supplied `--output` path, and the project's `.shoulder/` directory. - The localhost gRPC server binds to `127.0.0.1` and is not exposed on external interfaces — verified: 0 `listen()`/`bind()` calls across traced scenarios. - No elevated privileges are required for any operation — verified: 0 `setuid`/`setgid`/`capset`/`ptrace` calls across traced scenarios. --- ## 9) Configuration Controls ### Privacy / Network Controls | Control | Method | |------------------------------------------|-----------------------------------------------------------------------| | Disable update checks | `SHOULDER_DISABLE_UPDATES=1` | | Disable local metrics collection | `SHOULDER_METRICS_DISABLED=1` (or `=true`) | | Override application API base URL | `SHOULDER_API_URL=https://your-host…` | | Override supply-chain intel API base URL | `SHOULDER_INTEL_URL=https://your-host…` | | Provide auth for self-hosted / paid tier | `SHOULDER_API_KEY=…` | | Use development endpoints | `SHOULDER_ENV=development` | | Avoid supply-chain network calls | Do not invoke `trust --ecosystem`, `trust deps`, `trust-diff`, `packages`, or `decide`; avoid scanning a project containing a `Dockerfile`, `.github/workflows/*.yml`, or lockfile with `--ecosystem` set | | Skip capability walk on large targets | Lightweight trust profiles auto-skip; can also be tuned via `exclude_directories` (forwarded to the capability scanner) | ### Output Controls | Control | Method | |------------------------|---------------------------------------------------------------| | Machine output | `--json` or `--sarif` (auto-silent console logs) | | Output destination | `--output ` | | Severity filter | `--severity {critical\|high\|medium\|low}` | | Confidence filter | `--min-confidence 0.0–1.0` | | Exclude remediation | `--no-remediation` | ### Logging Controls | Control | Method | |-------------|--------------------------------------------------------------| | Level | `--log-level …` / `SHOULDERSEC_LOG_LEVEL` / `DEBUG=1` | | Timestamps | `--no-timestamps` | ### IDE / Agent Hook Integration Controls | Control | Method | |----------------------------------|---------------------------------------------------------------------| | Install Claude Code hooks | `shoulder install claude` (`--portable` opt) | | Install Cursor hooks | `shoulder install cursor` | | Install Codex / Goose hooks | `shoulder install codex` / `shoulder install goose` | | Uninstall | `shoulder uninstall claude` / `… cursor` / `… codex` / `… goose` | | Serve port | `--port ` (`0` for auto-assigned localhost) | | Parent-process watch | `--watch-pid ` (exit when parent dies) | | Pre-install dep gate (MCP) | PreToolUse hook denies installs of packages whose verdict is BLOCK before they land | | Post-edit finding gate (MCP) | PostToolUse hook blocks only on **new** findings, not pre-existing residue | --- ## 10) Verification Notes This report was compiled from (a) a read-only review of the codebase at commit `6e508346` and (b) external syscall traces captured at commit `74797ae9` (`transparency-reports/evidence/74797ae9-linux/`). Methodology: 1. **Network call inventory.** Searched for `net/http` clients (`http.Client`, `http.NewRequest`, `http.Get`, `http.Post`) and gRPC dialing across the repository. Each call site was inspected to determine destination, trigger, request body shape, and disable mechanism. 2. **API base URLs.** Reviewed `internal/config/` for default endpoints, `SHOULDER_API_URL`, `SHOULDER_INTEL_URL`, and `SHOULDER_ENV`. Cross-checked against the API client implementation in `internal/api/`. 3. **Update channel.** Reviewed the updater module's request shape, headers, and response handling. Confirmed `SHOULDER_DISABLE_UPDATES=1` is honored in the CLI entry point. 4. **Filesystem operations.** Searched for `os.Create`, `os.WriteFile`, `os.MkdirAll`, `os.Remove`, `os.RemoveAll`. Mapped every write location and confirmed scan-target source files are read-only. 5. **Subprocess execution.** Searched for `exec.Command` / `exec.CommandContext`. Verified no project code is executed and that all subprocess argument lists are slice-based (no shell concatenation of user input). 6. **Logging.** Reviewed `internal/logging/` and the TeeLogger to confirm what is written to stderr and to `~/.shoulder/logs/`, and that source content and bearer tokens are not emitted. 7. **Metrics.** Reviewed `internal/metrics/collector.go` to confirm metrics are stored locally in SQLite and gated by `SHOULDER_METRICS_DISABLED`. 8. **Sandbox tarball flow.** Reviewed `sandbox.sh` for the `npmjs.com` path; confirmed the flow fetches the registry tarball and extracts it without invoking `npm install` or package lifecycle hooks. 9. **MCP / gRPC.** Confirmed both bind to `localhost` only and exchange data with the local CLI process — no external transport. 10. **Independently verified by external OS-level tracing** (`strace` on Linux at this revision; `dtruss`/`fs_usage` on macOS and Process Monitor / ETW on Windows planned). Per-OS evidence is captured by `scripts/transparency/capture.sh`, which exercises four fixed customer-facing scenarios (offline trust scan, ecosystem-enabled trust scan, ecosystem + GHA, ecosystem + npm lockfile) and produces sanitised per-scenario summaries. 11. **The sanitiser strips host-specific paths** and emits only counts and high-level path buckets. Raw traces are retained internally for audit but never published. No source code is reproduced in this report. --- *This transparency report is intended to help security-conscious users understand Shoulder's data handling, network behavior, and privacy posture. It is not a contract; binding terms are governed by Shoulder's published service agreements.* --- **Report generation details:** Generated 2026-05-15 by Anthropic's **Claude Opus 4.7** (`claude-opus-4-7`) running inside the Claude Code CLI. The analysis was performed via read-only inspection of the Shoulder repository at commit `6e508346` and the sanitised external-trace summaries under `transparency-reports/evidence/74797ae9-linux/`. No source code is reproduced in this report.