{"record":{"id":"848cae7a194b881f","repo":"affaan-m/ECC","slug":"capsule-secret-canary","errorCode":"capsule.secret_canary","errorMessage":"payload tripped secret canary ${findings[0].canary} at ${findings[0].path}","messagePattern":"payload tripped secret canary (.+?) at (.+?)","errorType":"error_code","errorClass":"CapsuleError","httpStatus":null,"severity":"critical","filePath":"scripts/lib/eval-harness/capsule.js","lineNumber":191,"sourceCode":"\n  /**\n   * Serialize cooperating appenders and validate current disk state under lock.\n   * A partial I/O failure is preserved for diagnosis, never silently rolled back.\n   */\n  append(lineage, kind, payload = {}, options = {}) {\n    return withAppendLock(this.dir, () => {\n      const state = readCapsule(this.dir);\n      if (!state.ok) throw new CapsuleError(state.code, state.reason, { failed_at: state.failed_at });\n      if (!envelope.LINEAGES.includes(lineage)) {\n        throw new CapsuleError('capsule.bad_lineage', `unknown lineage ${lineage}`);\n      }\n      const effectClass = options.effect_class || 'SE0';\n      const { payload: clean, dropped, findings, errors: payloadErrors } = envelope.redactPayload(payload, options);\n      if (payloadErrors.length > 0) {\n        throw new CapsuleError('capsule.payload_invalid', payloadErrors.join('; '));\n      }\n      if (findings.length > 0) {\n        throw new CapsuleError('capsule.secret_canary', `payload tripped secret canary ${findings[0].canary} at ${findings[0].path}`, { findings });\n      }\n      if (dropped.length > 0 && options.strict !== false) {\n        throw new CapsuleError('capsule.payload_denied', `payload keys not allowlisted: ${dropped.join(', ')}`, { dropped });\n      }\n      const body = {\n        schema: envelope.SCHEMA_VERSION,\n        run_id: state.meta.run_id,\n        capsule_id: state.meta.capsule_id,\n        seq: state.entries.length,\n        ts: nowIso(this.clock),\n        lineage,\n        kind,\n        effect_class: effectClass,\n        harness_version: state.meta.harness_version,\n        task_family: state.meta.task_family,\n        parent_hash: state.root_hash,\n        payload: clean,\n      };","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/eval-harness/capsule.js#L173-L209","documentation":"Before writing anything, append() scans the payload with the envelope's secret canary detector. If any value matches a canary pattern (API keys, tokens, key-like strings), it throws 'capsule.secret_canary' with the offending canary name and payload path in the message and the full findings array as detail. This is a deliberate security gate: the capsule journal is an append-only, potentially shared artifact, so secrets must never enter it.","triggerScenarios":"Calling append() with a payload that contains a secret-shaped value — e.g. embedding an API key, token, or password (or a string that merely looks like one) in a note payload, or redacting that failed to exclude a credential field.","commonSituations":"Copying an error message that includes an Authorization header or key; logging environment-derived values like process.env.OPENAI_API_KEY into a capsule note; test fixtures containing fake-but-realistic keys that trip the pattern matcher.","solutions":["Remove the secret from the payload; reference it by environment variable name or a redacted handle (e.g. 'key from SECRET_VAR') instead of its value.","Inspect the findings detail array to see the exact canary and payload path that matched.","Truncate or mask the offending value (e.g. last4 only) before appending.","If it is a false positive (deliberately fake test value), restructure the string so it does not match the canary pattern rather than bypassing the check.","If a real secret was nearly committed, rotate it — it reached your code path and logs."],"exampleFix":"// before\nawait capsule.append('fix', 'note', { msg: `used key ${process.env.OPENAI_API_KEY}` }); // capsule.secret_canary\n\n// after\nawait capsule.append('fix', 'note', { msg: 'used key from OPENAI_API_KEY env var' });","handlingStrategy":"validation","validationCode":"const scan = envelope.redactPayload(payload, {});\nif (scan.findings.length > 0) throw new Error(`secret-like value at ${scan.findings[0].path} (${scan.findings[0].canary}); remove before appending`);","typeGuard":null,"tryCatchPattern":"try {\n  await capsule.append(lineage, kind, payload);\n} catch (e) {\n  if (e instanceof CapsuleError && e.code === 'capsule.secret_canary') {\n    console.error(`Refusing to journal secret: ${e.message}; scrub payload and rotate if real`);\n    return; // never retry with the same payload\n  }\n  throw e;\n}","preventionTips":["Never interpolate env-var secret values into payload strings; reference the var name instead.","Mask credentials to last4/prefix form before logging or journaling.","Run the canary scan in CI on any code that builds capsule payloads.","Rotate any real secret that tripped the canary, even if it was never written."],"tags":["security","secrets","payload"],"backgroundTag":"secret-detected","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}