Skip to content

Skillscript

v0.25.3 Security

This release includes 1 security fix for security teams reviewing exposed deployments.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 1 known CVE

Topics

agents dsl llm mcp skills workflow

Affected surfaces

auth

Summary

AI summary

Runtime secret markers from data no longer resolve, fixing data‑borne secret injection.

Full changelog

Upgrade impact: none (additive) for the documented usage — a {{secret.NAME}} marker written literally in a skill's shell/$ op still resolves exactly as before. Behavior change for an undocumented edge: a marker that is not in the skill source — one assembled at runtime from ${VAR} data or $set/$append — no longer resolves (it stays inert literal text). That path was never intended and was a leak; see below.

  • Closes data-borne secret injection (adopter finding). Resolution used to run on the post-substitution sink string, so a {{secret.NAME}} marker that arrived via runtime data (a ${VAR} value containing the literal text) got resolved — e.g. an email body containing {{secret.AGENTMAIL_KEY}} would inject the real key into the outbound message. The runtime now resolves author-template-only: it masks markers written literally in the op template before ${VAR} substitution, then splices the values in last. A marker arriving through data is never masked, so it can never resolve — it passes through as inert literal text. (This also refines the var-smuggle edge: a marker built via $set/$append is data-borne and therefore inert, rather than resolving-if-declared.)
  • Sentinel forgery neutralized. The masking uses a NUL-delimited sentinel; ${VAR} substitution now strips NUL bytes from every substituted value, so untrusted data can't forge a sentinel to trigger a splice. (NUL is never valid in skill data — spawn rejects it — so the strip is loss-free.)
  • Unchanged guarantees: values never bind/emit/trace; the binary-allowlist gate runs before resolution; errors/traces render the marker, not the value; declare-before-spend (# Requires) is enforced on author markers; the three tier-1 lint rules stand. Verified end-to-end across shell(argv=…), shell(command=…), and $ connector.tool sinks; the data-borne and forgery paths have regression tests.

Two lint improvements from the same dogfood (both adopter-found):

  • undeclared-var now scans shell(argv=[...]) elements. A ${VAR} reference inside an argv element previously escaped the undeclared-var (and unknown-filter, legacy-$(...)-shape) checks — the lint's op-text collection skipped argv. Now an undeclared ${VAR} in an argv element is caught at compile, like every other op position.
  • New tier-2 space-separated-vars. # Vars: is comma-separated; writing # Vars: A B C silently collapsed into one malformed variable named "A B C" (the rest lost). The new warning flags any # Vars: entry whose name contains whitespace and suggests the comma form.

Breaking Changes

  • Secret markers ({{secret.NAME}}) that are assembled at runtime from ${VAR} values or via $set/$append no longer resolve and remain inert literal text.

Security Fixes

  • Data‑borne secret injection (adopter finding) — markers arriving via runtime data no longer resolve, preventing accidental secret leakage.

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]