This release includes 1 security fix for security teams reviewing exposed deployments.
Topics
Affected surfaces
Summary
AI summaryRuntime 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/$appendis 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 —spawnrejects 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 acrossshell(argv=…),shell(command=…), and$ connector.toolsinks; the data-borne and forgery paths have regression tests.
Two lint improvements from the same dogfood (both adopter-found):
undeclared-varnow scansshell(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 skippedargv. 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 Csilently 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
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]