mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-18 22:13:45 +02:00
fix(gateguard): validate the denial cap as a whole integer
Review findings on the rebased branch. Number.parseInt accepted partial values, so GATEGUARD_FACT_FORCE_MAX_DENIALS set to '3.5', '3oops', or '0x3' silently became a finite cap of 3 and weakened the gate on a typo. The value is now matched whole and anything that is not a complete non-negative decimal integer leaves the gate uncapped, which is the stricter outcome. Also names the setting in the condensed denial's recovery text, so a capped session can discover the control that is dampening it, and documents that malformed values fall back to uncapped. Tests: adds a Write pass-through case, an exact-boundary case where the denial that reaches the cap still denies and the next path passes, one case per malformed value, and an assertion that the condensed denial names the cap. Pass-through assertions now require a parsed output object rather than accepting a missing one. 207 hook tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bvrwu6iCpKP3C2rh8tBsdJ
This commit is contained in:
co-authored by
Claude Opus 5
parent
241b4b535b
commit
ef0a487edd
@@ -953,15 +953,28 @@ function getFullDenialBudget() {
|
||||
return DEFAULT_FULL_DENIALS;
|
||||
}
|
||||
|
||||
// Edit/Write fact forcing can be capped per session instead of denying every
|
||||
// new path forever. Keep the existing behavior when unset; hosts can opt in
|
||||
// to a session-wide ceiling without weakening the destructive-Bash gate.
|
||||
const MAX_DENIALS_PATTERN = /^\d+$/;
|
||||
|
||||
/**
|
||||
* Session-wide ceiling on Edit/Write fact-force denials, from
|
||||
* GATEGUARD_FACT_FORCE_MAX_DENIALS. Opt-in: unset keeps the existing behavior
|
||||
* of denying every new path, and the destructive-Bash gate is unaffected
|
||||
* either way.
|
||||
*
|
||||
* The value is validated whole rather than with Number.parseInt, because a
|
||||
* prefix parse turns '3.5', '3oops', and '0x3' into finite caps and would
|
||||
* quietly weaken the gate on a typo. Anything that is not a complete
|
||||
* non-negative decimal integer leaves the gate uncapped.
|
||||
*
|
||||
* @returns {number} the denial ceiling, or Number.POSITIVE_INFINITY when uncapped
|
||||
*/
|
||||
function getMaxDenialBudget() {
|
||||
const raw = Number.parseInt(process.env.GATEGUARD_FACT_FORCE_MAX_DENIALS || '', 10);
|
||||
if (Number.isInteger(raw) && raw >= 0) {
|
||||
return raw;
|
||||
const raw = (process.env.GATEGUARD_FACT_FORCE_MAX_DENIALS || '').trim();
|
||||
if (!MAX_DENIALS_PATTERN.test(raw)) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
return Number.POSITIVE_INFINITY;
|
||||
const parsed = Number(raw);
|
||||
return Number.isSafeInteger(parsed) ? parsed : Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
function getDenialCount(state) {
|
||||
@@ -1154,7 +1167,7 @@ function condensedGateMsg(action, filePath, ordinal) {
|
||||
return (
|
||||
`[Fact-Forcing Gate] (denial #${ordinal} this session) First ${action} of ${safe}: ` +
|
||||
"briefly state importers/callers, affected API, data schemas if any, and the user's verbatim instruction, then retry. " +
|
||||
'(Use GATEGUARD_EXEMPT_GLOBS for path-scoped exemptions; ECC_GATEGUARD=off disables this gate.)'
|
||||
'(Use GATEGUARD_EXEMPT_GLOBS for path-scoped exemptions; GATEGUARD_FACT_FORCE_MAX_DENIALS caps denials per session; ECC_GATEGUARD=off disables this gate.)'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user