javi-forge 1.21.0 → 1.21.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.
@@ -77,6 +77,35 @@ const RUNNER_FIELDS = new Set([
77
77
  function isRecord(value) {
78
78
  return typeof value === "object" && value !== null && !Array.isArray(value);
79
79
  }
80
+ /**
81
+ * Validate an optional container `image` ref shared by the runner and gate
82
+ * paths (IMG-1). Rejects non-string / empty-after-trim and leading-dash refs
83
+ * (an image like "--privileged" or "-v /:/host" would be parsed by `docker run`
84
+ * as a FLAG, not an image, if it reached argv — JDB-004) with a named error at
85
+ * `fieldPath`. Returns the TRIMMED value to store, so a whitespace-padded ref
86
+ * fails cleanly at validation instead of reaching docker argv untrimmed.
87
+ * Returns undefined when the field is absent or invalid.
88
+ */
89
+ function validateImageRef(value, fieldPath, errors) {
90
+ if (value === undefined)
91
+ return undefined;
92
+ if (typeof value !== "string" || !value.trim()) {
93
+ errors.push({
94
+ path: fieldPath,
95
+ message: "image must be a non-empty string",
96
+ });
97
+ return undefined;
98
+ }
99
+ const trimmed = value.trim();
100
+ if (trimmed.startsWith("-")) {
101
+ errors.push({
102
+ path: fieldPath,
103
+ message: "image must not start with '-' (would be parsed as a docker flag)",
104
+ });
105
+ return undefined;
106
+ }
107
+ return trimmed;
108
+ }
80
109
  function normalizeCommands(value, fieldPath, errors) {
81
110
  if (value === undefined)
82
111
  return [];
@@ -159,18 +188,7 @@ function validateRunner(raw, index, errors) {
159
188
  }
160
189
  }
161
190
  }
162
- let image;
163
- if (raw.image !== undefined) {
164
- if (typeof raw.image !== "string" || !raw.image.trim()) {
165
- errors.push({
166
- path: `${base}.image`,
167
- message: "image must be a non-empty string",
168
- });
169
- }
170
- else {
171
- image = raw.image;
172
- }
173
- }
191
+ const image = validateImageRef(raw.image, `${base}.image`, errors);
174
192
  let buildContext;
175
193
  if (raw["build-context"] !== undefined) {
176
194
  if (typeof raw["build-context"] !== "string" ||
@@ -319,28 +337,7 @@ function validateGate(raw, index, errors) {
319
337
  env = raw.env;
320
338
  }
321
339
  }
322
- let image;
323
- if (raw.image !== undefined) {
324
- if (typeof raw.image !== "string" || !raw.image.trim()) {
325
- errors.push({
326
- path: `${base}.image`,
327
- message: "image must be a non-empty string",
328
- });
329
- }
330
- else if (raw.image.trim().startsWith("-")) {
331
- // Harden against docker-flag injection: an image ref like "--privileged"
332
- // or "-v /:/host" would be parsed by `docker run` as a FLAG, not an
333
- // image argument, if it reached argv. Reject leading-dash refs at
334
- // validation with a named error (JDB-004).
335
- errors.push({
336
- path: `${base}.image`,
337
- message: "image must not start with '-' (would be parsed as a docker flag)",
338
- });
339
- }
340
- else {
341
- image = raw.image;
342
- }
343
- }
340
+ const image = validateImageRef(raw.image, `${base}.image`, errors);
344
341
  let timeout;
345
342
  if (raw.timeout !== undefined) {
346
343
  if (typeof raw.timeout !== "number" ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javi-forge",
3
- "version": "1.21.0",
3
+ "version": "1.21.1",
4
4
  "description": "Project scaffolding and AI-ready CI bootstrap",
5
5
  "type": "module",
6
6
  "bin": {