Skip to content

Skillscript

v0.25.0 Feature

This release adds 2 notable features for engineering teams evaluating rollout.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

agents dsl llm mcp skills workflow

Affected surfaces

auth

Summary

AI summary

Skills 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.NAME in 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 — a shell(...) op or a $ connector.tool dispatch. (1) Lint (tier-1) blocks a marker anywhere else (emit, $set, a condition, an # Output: template, a file_*/notify op, an op (fallback: ...)) via secret-use-only, an undeclared marker via secret-undeclared, and a non-literal/dynamic name ({{secret.${VAR}}}) via secret-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 bundled EnvSecretProvider resolves {{secret.NAME}} from the env var SKILLSCRIPT_SECRET_NAME. The prefix is intentional — it scopes which environment is secret-reachable, so {{secret.PATH}} looks for SKILLSCRIPT_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 SecretProvider interface whose resolve(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 via bootstrap({ secretProvider }) or bootstrapFromEnv's overrides.
  • 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}}") -> OUT then emit("${OUT}"), or a curl that 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

Track Skillscript

Get notified when new releases ship.

Sign up free

About Skillscript

All releases →

Related context

Earlier breaking changes

  • v0.35.0 Editing `# Deadline:` on an approved skill drops it to Draft (signature invalidates).

Beta — feedback welcome: [email protected]