@bman654/clodex 2.7.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -156,14 +156,62 @@ helper delete clodex <account>
156
156
 
157
157
  The service and account arguments are identifiers, not secrets. Credential
158
158
  contents are never passed in arguments or environment variables. Helper
159
- standard error is not copied into Clodex diagnostics, and output and runtime
160
- are bounded.
159
+ standard error is drained and discarded rather than copied into Clodex
160
+ diagnostics. Captured standard output is capped at 1 MiB; exceeding it fails
161
+ the operation. Runtime is bounded for the process Clodex starts: at ten seconds
162
+ it is sent `SIGKILL` and the operation fails. Processes that helper starts are
163
+ outside both bounds, so a helper that forks has to bound them itself. See
164
+ [Process lifetime](#process-lifetime).
161
165
 
162
166
  The helper protocol transports credential bytes without interpreting them.
163
167
  For non-OAuth provider references, Clodex preserves valid opaque JSON secrets.
164
168
  OAuth references accept only complete OAuth records or well-known token
165
169
  records; malformed or unknown JSON is never used as a bearer token.
166
170
 
171
+ ## Process lifetime
172
+
173
+ Clodex starts the helper directly, waits at most ten seconds, and enforces that
174
+ limit with `SIGKILL`. That is the only signal Clodex ever sends a helper, and it
175
+ reaches only the process Clodex started. A process that one forked may keep
176
+ running after the credential operation has already failed, usually reparented to
177
+ PID 1, still holding the standard output and standard error it inherited.
178
+
179
+ A wrapper script around `pass`, `gpg`, or `secret-tool` is the common shape for
180
+ a helper, and it is the shape that forks. Nothing Clodex can send will reach
181
+ what it leaves behind, so the wrapper has to take care of its own descendants:
182
+
183
+ - **Prefer `exec`.** `exec gpg --decrypt "$path"` replaces the wrapper, so the
184
+ process Clodex kills is the one doing the work. This removes the wrapper as a
185
+ layer; it does not constrain the program you exec, whose own children are
186
+ still outside Clodex's bound.
187
+ - **Give anything you fork a hard deadline.** GNU coreutils `timeout` needs
188
+ `--kill-after` to be a real bound: plain `timeout 5 cmd` sends `SIGTERM` and
189
+ then waits forever if `cmd` ignores it, while `timeout --kill-after=1 5 cmd`
190
+ escalates to `SIGKILL`. Note `timeout` ships with GNU coreutils and is absent
191
+ from stock macOS and from minimal container images.
192
+ - **Clean up on interrupt by pid, never with `kill 0`.** Ctrl-C does reach the
193
+ helper: Clodex does not detach it, so it shares Clodex's process group. A
194
+ handler that
195
+ signals the whole group also re-signals the wrapper and re-enters itself,
196
+ which has been observed looping over a thousand times in five seconds. Track
197
+ what you start and signal that:
198
+
199
+ ```sh
200
+ child=""
201
+ trap 'kill "$child" 2>/dev/null; exit 143' INT TERM HUP
202
+ gpg --decrypt "$path" & child=$!
203
+ wait "$child"
204
+ ```
205
+
206
+ This is worth having, but it is not a substitute for the two points above:
207
+ `SIGKILL` cannot be trapped, so no handler runs at the ten-second limit.
208
+
209
+ Prefer a non-interactive credential path. Clodex gives the helper pipes for
210
+ standard input, output, and error, but the controlling terminal is still
211
+ reachable through `/dev/tty`, so a program like `gpg` can still prompt through
212
+ `pinentry`. A helper waiting on a passphrase is a helper waiting out the ten
213
+ seconds.
214
+
167
215
  ## Security responsibilities
168
216
 
169
217
  Clodex owns OAuth parsing, refresh decisions, replacement-token serialization,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bman654/clodex",
3
- "version": "2.7.0",
3
+ "version": "2.8.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },