@biffo/cli 0.246.4 → 0.246.5
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.
- package/_skeletons/plugin-template/scripts/js-dependency-audit.sh +24 -4
- package/_skeletons/plugin-template/scripts/py-dependency-audit.sh +18 -4
- package/_skeletons/sibling-template/scripts/js-dependency-audit.sh +24 -4
- package/_skeletons/sibling-template/scripts/py-dependency-audit.sh +18 -4
- package/package.json +1 -1
|
@@ -105,16 +105,29 @@ audit_dir() {
|
|
|
105
105
|
# trusting it — the workspace audit had silently stopped working.)
|
|
106
106
|
# shellcheck disable=SC2086
|
|
107
107
|
out="$(cd "$dir" 2>/dev/null && pnpm audit --json $extra 2>/dev/null)"
|
|
108
|
+
# Stamped the instant the registry answered, not when the run started.
|
|
109
|
+
# `pnpm audit` asks the LIVE registry, so its verdict is a function of what
|
|
110
|
+
# had been ingested at this moment — two runs of the same tree minutes apart
|
|
111
|
+
# can legitimately disagree (#1269). Without this stamp a green is not
|
|
112
|
+
# falsifiable, and a red appearing hours after a merge reads as "someone
|
|
113
|
+
# broke dev" when nothing in the tree moved.
|
|
114
|
+
seen_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
108
115
|
|
|
109
116
|
if printf '%s' "$out" | jq -e '.metadata.vulnerabilities' >/dev/null 2>&1; then
|
|
110
117
|
high="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.high // 0')"
|
|
111
118
|
crit="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.critical // 0')"
|
|
119
|
+
mod="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.moderate // 0')"
|
|
120
|
+
low="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.low // 0')"
|
|
121
|
+
total="$(printf '%s' "$out" | jq '.metadata.totalDependencies // 0')"
|
|
112
122
|
if [ "$((high + crit))" -gt 0 ]; then
|
|
113
|
-
echo "::error::${label}: ${crit} critical + ${high} high advisory(ies)."
|
|
123
|
+
echo "::error::${label}: ${crit} critical + ${high} high advisory(ies) across ${total} package(s); registry answered ${seen_at}."
|
|
114
124
|
printf '%s' "$out" | jq '.advisories // .metadata.vulnerabilities' 2>/dev/null | head -c 4000
|
|
115
125
|
return 1
|
|
116
126
|
fi
|
|
117
|
-
|
|
127
|
+
# A bare "no advisories" is not falsifiable. State the population, the
|
|
128
|
+
# severities that did NOT block, and when the registry was asked, so a
|
|
129
|
+
# reader can tell a clean tree from a tree nobody looked at properly.
|
|
130
|
+
echo "${label}: 0 critical, 0 high across ${total} package(s) (${mod} moderate, ${low} low — reported, not blocking); registry answered ${seen_at}."
|
|
118
131
|
return 0
|
|
119
132
|
fi
|
|
120
133
|
|
|
@@ -123,7 +136,7 @@ audit_dir() {
|
|
|
123
136
|
[ "$attempt" -lt "$attempts" ] && sleep "$((attempt * 3))"
|
|
124
137
|
done
|
|
125
138
|
|
|
126
|
-
echo "::
|
|
139
|
+
echo "::error::${label}: audit could not run after ${attempts} attempts (the registry returned a non-JSON/error response). Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS — a gate that cannot see its input must not report clean (#1269, #591)."
|
|
127
140
|
inconclusive=$((inconclusive + 1))
|
|
128
141
|
return 0
|
|
129
142
|
}
|
|
@@ -209,7 +222,14 @@ if [ "$failed" -ne 0 ]; then
|
|
|
209
222
|
fi
|
|
210
223
|
|
|
211
224
|
if [ "$inconclusive" -ne 0 ]; then
|
|
212
|
-
|
|
225
|
+
# Exit 2, not 1: "could not determine" is a different fact from "found a real
|
|
226
|
+
# advisory", and conflating them sends whoever reads the red looking for a
|
|
227
|
+
# vulnerability that may not exist. Same three-valued contract as
|
|
228
|
+
# scripts/claim.sh (0 free / 1 taken / 2 cannot tell) and the zero-trees exit
|
|
229
|
+
# above. Until #1269 this returned 0 -- biffo-plugin-ideation rode that path
|
|
230
|
+
# on EVERY run, permanently green while scanning nothing.
|
|
231
|
+
echo "::error::${inconclusive} tree(s) could not be audited; see the errors above. Failing closed."
|
|
232
|
+
exit 2
|
|
213
233
|
fi
|
|
214
234
|
|
|
215
235
|
echo "js-dependency-audit: audited ${tree_count} tree(s), 0 blocking findings."
|
|
@@ -91,6 +91,11 @@ audit_deps() {
|
|
|
91
91
|
for attempt in $(seq 1 "$attempts"); do
|
|
92
92
|
# shellcheck disable=SC2086
|
|
93
93
|
out="$(uv run pip-audit -f json $extra 2>/dev/null)"
|
|
94
|
+
# Stamped when the advisory source answered, not when the run started —
|
|
95
|
+
# pip-audit queries PyPI/OSV live, so its verdict is time-dependent in the
|
|
96
|
+
# same way pnpm audit's is (#1269). Without the stamp a pass cannot be
|
|
97
|
+
# distinguished from a pass taken before an advisory was published.
|
|
98
|
+
seen_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
94
99
|
|
|
95
100
|
# printf, never echo: the CI step runs `sh scripts/...` i.e. dash, whose
|
|
96
101
|
# `echo` interprets backslash escapes. Advisory payloads contain them, so
|
|
@@ -101,12 +106,16 @@ audit_deps() {
|
|
|
101
106
|
# had been doing exactly that on every run.
|
|
102
107
|
if printf '%s' "$out" | jq -e '.dependencies' >/dev/null 2>&1; then
|
|
103
108
|
vuln_count="$(printf '%s' "$out" | jq '[.dependencies[].vulns[]?] | length')"
|
|
109
|
+
pkg_count="$(printf '%s' "$out" | jq '.dependencies | length')"
|
|
104
110
|
if [ "$vuln_count" -gt 0 ]; then
|
|
105
111
|
echo "::error::${label}: ${vuln_count} vulnerability(ies)."
|
|
106
112
|
printf '%s' "$out" | jq '[.dependencies[] | select(.vulns | length > 0)]' 2>/dev/null | head -c 4000
|
|
107
113
|
return 1
|
|
108
114
|
fi
|
|
109
|
-
|
|
115
|
+
# State the population and the moment, so the green is falsifiable: a
|
|
116
|
+
# pass over 0 packages and a pass over 92 look identical otherwise, and
|
|
117
|
+
# the first is the failure this whole file exists to prevent.
|
|
118
|
+
echo "${label}: 0 vulnerabilities across ${pkg_count} package(s); advisory source answered ${seen_at}."
|
|
110
119
|
return 0
|
|
111
120
|
fi
|
|
112
121
|
|
|
@@ -114,7 +123,7 @@ audit_deps() {
|
|
|
114
123
|
[ "$attempt" -lt "$attempts" ] && sleep "$((attempt * 3))"
|
|
115
124
|
done
|
|
116
125
|
|
|
117
|
-
echo "::
|
|
126
|
+
echo "::error::${label}: could not produce parseable output after ${attempts} attempts. Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS — a gate that cannot see its input must not report clean (#1269, #591). If this is a missing tool rather than a network fault, the fix is to declare it: biffo-plugin-ideation rode this path on every run, permanently green while scanning nothing."
|
|
118
127
|
inconclusive=$((inconclusive + 1))
|
|
119
128
|
return 0
|
|
120
129
|
}
|
|
@@ -201,7 +210,7 @@ for lock in $ALL_LOCKS; do
|
|
|
201
210
|
else
|
|
202
211
|
# An export failure is "couldn't run", not "clean" — same discipline as a
|
|
203
212
|
# transient pip-audit error, and it must never read as a pass.
|
|
204
|
-
echo "::
|
|
213
|
+
echo "::error::pip-audit (${rel}): could not export requirements from ${lock}. Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS (#1269, #719)."
|
|
205
214
|
inconclusive=$((inconclusive + 1))
|
|
206
215
|
fi
|
|
207
216
|
|
|
@@ -213,7 +222,12 @@ if [ "$failed" -ne 0 ]; then
|
|
|
213
222
|
fi
|
|
214
223
|
|
|
215
224
|
if [ "$inconclusive" -ne 0 ]; then
|
|
216
|
-
|
|
225
|
+
# Exit 2, not 1: "could not determine" is a different fact from "found a real
|
|
226
|
+
# advisory". Conflating them sends whoever reads the red hunting a
|
|
227
|
+
# vulnerability that may not exist. Same three-valued contract as
|
|
228
|
+
# scripts/claim.sh (0 free / 1 taken / 2 cannot tell).
|
|
229
|
+
echo "::error::${inconclusive} tree(s) could not be audited; see the errors above. Failing closed."
|
|
230
|
+
exit 2
|
|
217
231
|
fi
|
|
218
232
|
|
|
219
233
|
echo "py-dependency-audit: audited ${tree_count} tree(s), 0 blocking findings."
|
|
@@ -105,16 +105,29 @@ audit_dir() {
|
|
|
105
105
|
# trusting it — the workspace audit had silently stopped working.)
|
|
106
106
|
# shellcheck disable=SC2086
|
|
107
107
|
out="$(cd "$dir" 2>/dev/null && pnpm audit --json $extra 2>/dev/null)"
|
|
108
|
+
# Stamped the instant the registry answered, not when the run started.
|
|
109
|
+
# `pnpm audit` asks the LIVE registry, so its verdict is a function of what
|
|
110
|
+
# had been ingested at this moment — two runs of the same tree minutes apart
|
|
111
|
+
# can legitimately disagree (#1269). Without this stamp a green is not
|
|
112
|
+
# falsifiable, and a red appearing hours after a merge reads as "someone
|
|
113
|
+
# broke dev" when nothing in the tree moved.
|
|
114
|
+
seen_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
108
115
|
|
|
109
116
|
if printf '%s' "$out" | jq -e '.metadata.vulnerabilities' >/dev/null 2>&1; then
|
|
110
117
|
high="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.high // 0')"
|
|
111
118
|
crit="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.critical // 0')"
|
|
119
|
+
mod="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.moderate // 0')"
|
|
120
|
+
low="$(printf '%s' "$out" | jq '.metadata.vulnerabilities.low // 0')"
|
|
121
|
+
total="$(printf '%s' "$out" | jq '.metadata.totalDependencies // 0')"
|
|
112
122
|
if [ "$((high + crit))" -gt 0 ]; then
|
|
113
|
-
echo "::error::${label}: ${crit} critical + ${high} high advisory(ies)."
|
|
123
|
+
echo "::error::${label}: ${crit} critical + ${high} high advisory(ies) across ${total} package(s); registry answered ${seen_at}."
|
|
114
124
|
printf '%s' "$out" | jq '.advisories // .metadata.vulnerabilities' 2>/dev/null | head -c 4000
|
|
115
125
|
return 1
|
|
116
126
|
fi
|
|
117
|
-
|
|
127
|
+
# A bare "no advisories" is not falsifiable. State the population, the
|
|
128
|
+
# severities that did NOT block, and when the registry was asked, so a
|
|
129
|
+
# reader can tell a clean tree from a tree nobody looked at properly.
|
|
130
|
+
echo "${label}: 0 critical, 0 high across ${total} package(s) (${mod} moderate, ${low} low — reported, not blocking); registry answered ${seen_at}."
|
|
118
131
|
return 0
|
|
119
132
|
fi
|
|
120
133
|
|
|
@@ -123,7 +136,7 @@ audit_dir() {
|
|
|
123
136
|
[ "$attempt" -lt "$attempts" ] && sleep "$((attempt * 3))"
|
|
124
137
|
done
|
|
125
138
|
|
|
126
|
-
echo "::
|
|
139
|
+
echo "::error::${label}: audit could not run after ${attempts} attempts (the registry returned a non-JSON/error response). Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS — a gate that cannot see its input must not report clean (#1269, #591)."
|
|
127
140
|
inconclusive=$((inconclusive + 1))
|
|
128
141
|
return 0
|
|
129
142
|
}
|
|
@@ -209,7 +222,14 @@ if [ "$failed" -ne 0 ]; then
|
|
|
209
222
|
fi
|
|
210
223
|
|
|
211
224
|
if [ "$inconclusive" -ne 0 ]; then
|
|
212
|
-
|
|
225
|
+
# Exit 2, not 1: "could not determine" is a different fact from "found a real
|
|
226
|
+
# advisory", and conflating them sends whoever reads the red looking for a
|
|
227
|
+
# vulnerability that may not exist. Same three-valued contract as
|
|
228
|
+
# scripts/claim.sh (0 free / 1 taken / 2 cannot tell) and the zero-trees exit
|
|
229
|
+
# above. Until #1269 this returned 0 -- biffo-plugin-ideation rode that path
|
|
230
|
+
# on EVERY run, permanently green while scanning nothing.
|
|
231
|
+
echo "::error::${inconclusive} tree(s) could not be audited; see the errors above. Failing closed."
|
|
232
|
+
exit 2
|
|
213
233
|
fi
|
|
214
234
|
|
|
215
235
|
echo "js-dependency-audit: audited ${tree_count} tree(s), 0 blocking findings."
|
|
@@ -91,6 +91,11 @@ audit_deps() {
|
|
|
91
91
|
for attempt in $(seq 1 "$attempts"); do
|
|
92
92
|
# shellcheck disable=SC2086
|
|
93
93
|
out="$(uv run pip-audit -f json $extra 2>/dev/null)"
|
|
94
|
+
# Stamped when the advisory source answered, not when the run started —
|
|
95
|
+
# pip-audit queries PyPI/OSV live, so its verdict is time-dependent in the
|
|
96
|
+
# same way pnpm audit's is (#1269). Without the stamp a pass cannot be
|
|
97
|
+
# distinguished from a pass taken before an advisory was published.
|
|
98
|
+
seen_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
94
99
|
|
|
95
100
|
# printf, never echo: the CI step runs `sh scripts/...` i.e. dash, whose
|
|
96
101
|
# `echo` interprets backslash escapes. Advisory payloads contain them, so
|
|
@@ -101,12 +106,16 @@ audit_deps() {
|
|
|
101
106
|
# had been doing exactly that on every run.
|
|
102
107
|
if printf '%s' "$out" | jq -e '.dependencies' >/dev/null 2>&1; then
|
|
103
108
|
vuln_count="$(printf '%s' "$out" | jq '[.dependencies[].vulns[]?] | length')"
|
|
109
|
+
pkg_count="$(printf '%s' "$out" | jq '.dependencies | length')"
|
|
104
110
|
if [ "$vuln_count" -gt 0 ]; then
|
|
105
111
|
echo "::error::${label}: ${vuln_count} vulnerability(ies)."
|
|
106
112
|
printf '%s' "$out" | jq '[.dependencies[] | select(.vulns | length > 0)]' 2>/dev/null | head -c 4000
|
|
107
113
|
return 1
|
|
108
114
|
fi
|
|
109
|
-
|
|
115
|
+
# State the population and the moment, so the green is falsifiable: a
|
|
116
|
+
# pass over 0 packages and a pass over 92 look identical otherwise, and
|
|
117
|
+
# the first is the failure this whole file exists to prevent.
|
|
118
|
+
echo "${label}: 0 vulnerabilities across ${pkg_count} package(s); advisory source answered ${seen_at}."
|
|
110
119
|
return 0
|
|
111
120
|
fi
|
|
112
121
|
|
|
@@ -114,7 +123,7 @@ audit_deps() {
|
|
|
114
123
|
[ "$attempt" -lt "$attempts" ] && sleep "$((attempt * 3))"
|
|
115
124
|
done
|
|
116
125
|
|
|
117
|
-
echo "::
|
|
126
|
+
echo "::error::${label}: could not produce parseable output after ${attempts} attempts. Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS — a gate that cannot see its input must not report clean (#1269, #591). If this is a missing tool rather than a network fault, the fix is to declare it: biffo-plugin-ideation rode this path on every run, permanently green while scanning nothing."
|
|
118
127
|
inconclusive=$((inconclusive + 1))
|
|
119
128
|
return 0
|
|
120
129
|
}
|
|
@@ -201,7 +210,7 @@ for lock in $ALL_LOCKS; do
|
|
|
201
210
|
else
|
|
202
211
|
# An export failure is "couldn't run", not "clean" — same discipline as a
|
|
203
212
|
# transient pip-audit error, and it must never read as a pass.
|
|
204
|
-
echo "::
|
|
213
|
+
echo "::error::pip-audit (${rel}): could not export requirements from ${lock}. Advisory scanning was NOT performed for this tree, so this is INCONCLUSIVE and BLOCKS (#1269, #719)."
|
|
205
214
|
inconclusive=$((inconclusive + 1))
|
|
206
215
|
fi
|
|
207
216
|
|
|
@@ -213,7 +222,12 @@ if [ "$failed" -ne 0 ]; then
|
|
|
213
222
|
fi
|
|
214
223
|
|
|
215
224
|
if [ "$inconclusive" -ne 0 ]; then
|
|
216
|
-
|
|
225
|
+
# Exit 2, not 1: "could not determine" is a different fact from "found a real
|
|
226
|
+
# advisory". Conflating them sends whoever reads the red hunting a
|
|
227
|
+
# vulnerability that may not exist. Same three-valued contract as
|
|
228
|
+
# scripts/claim.sh (0 free / 1 taken / 2 cannot tell).
|
|
229
|
+
echo "::error::${inconclusive} tree(s) could not be audited; see the errors above. Failing closed."
|
|
230
|
+
exit 2
|
|
217
231
|
fi
|
|
218
232
|
|
|
219
233
|
echo "py-dependency-audit: audited ${tree_count} tree(s), 0 blocking findings."
|