This release adds 2 notable features for engineering teams evaluating rollout.
✓ No known CVEs patched in this version
Topics
Affected surfaces
Summary
AI summarySkills can now reference operator‑provisioned secrets using {{secret.NAME}} syntax.
Full changelog
Upgrade impact: none (additive). New opt-in syntax + two new tier-1 lint rules that fire only on skills using the new syntax. Existing skills don't use {{secret.…}}, so nothing changes for them. Operators who want to provision a secret add a SKILLSCRIPT_SECRET_<NAME> env var.
A skill can now reference an operator-provisioned secret by name — use it at a sink, never read it. This is the durable answer to "my skill needs a bearer token / API key" that doesn't put the credential in the skill source, the transcript, or a trace.
- Declare + place.
# Requires: secret.NAMEin the frontmatter declares the secret (an approver sees exactly which credentials a skill can reach before vouching for it). A{{secret.NAME}}marker places it. The marker is deliberately distinct from${VAR}readable substitution:${VAR}resolves the skill's variable scope and cannot reach a secret, while{{secret.NAME}}resolves only at a sink and is never bound to a variable. - Use-only, enforced at three layers. A
{{secret.NAME}}marker is legal only inside a sink — ashell(...)op or a$ connector.tooldispatch. (1) Lint (tier-1) blocks a marker anywhere else (emit,$set, a condition, an# Output:template, afile_*/notifyop, an op(fallback: ...)) viasecret-use-only, an undeclared marker viasecret-undeclared, and a non-literal/dynamic name ({{secret.${VAR}}}) viasecret-dynamic-name. (2)${VAR}substitution treats a marker as opaque — it can never reach inside to build a secret name at runtime, so the name is always exactly as authored. (3) The runtime resolves only at the sink, only for names declared in# Requires(exact-literal match), the instant before spawn/dispatch — the value never binds to a var, emits, or enters a trace (the trace records the marker). Error messages and traces are redacted so a refused or failing op never renders a resolved value. These survive lint-bypass / source-mode execution — the runtime is the authoritative gate, not just lint. (Hardened against a red-team pass that found and closed a dynamic-name bypass and a refusal-error leak before ship.) - Provisioning (
.env). The bundledEnvSecretProviderresolves{{secret.NAME}}from the env varSKILLSCRIPT_SECRET_NAME. The prefix is intentional — it scopes which environment is secret-reachable, so{{secret.PATH}}looks forSKILLSCRIPT_SECRET_PATH, never$PATH. Secrets are operator-provisioned; a skill author names them but cannot set or read them. Fail-closed: an unprovisioned or undeclared secret aborts the op (it never sends an empty or literal-marker credential to the sink). - Vault-ready by construction. Resolution goes through a
SecretProviderinterface whoseresolve(name, ctx)already carries the requesting skill's identity, so a future vault-backed provider (per-script sealing, central rotation) drops in with no call-site changes — inject it viabootstrap({ secretProvider })orbootstrapFromEnv'soverrides. - Threat model (documented boundary). A secret you authorize a skill to use in a shell, that skill can also exfiltrate — e.g.
shell("echo {{secret.X}}") -> OUTthenemit("${OUT}"), or acurlthat POSTs it anywhere. This is inherent to argv injection and is not prevented by the runtime; the controls are approval review (a human approves the skill before it runs) and preferring a connector sink (the connector holds the credential out of band, so it never round-trips through skill-visible stdout). On the shell path the resolved value is also briefly visible in the host process list (ps); the vault era closes that with sink-aware injection (0600 temp file / piped env). Use a connector sink for credentials whose exposure you can't accept.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About Skillscript
All releases →Related context
Related tools
Earlier breaking changes
- v0.35.0 Editing `# Deadline:` on an approved skill drops it to Draft (signature invalidates).
Beta — feedback welcome: [email protected]