agent-sanitizer 2.56.1 → 2.57.0
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.
|
@@ -713,6 +713,11 @@ export function depLoadHint(
|
|
|
713
713
|
* — redactor daemon down, package not loaded) is the sanitizer being UNAVAILABLE,
|
|
714
714
|
* so it ASKS to keep a human in the loop rather than hard-block on infrastructure.
|
|
715
715
|
*
|
|
716
|
+
* An UNATTENDED host has no human for that ask to reach, so the ask stops the
|
|
717
|
+
* call and buys no review. Such a host passes `unavailableDecision: DENY` and
|
|
718
|
+
* gets a hard refusal on the clean-parse arm too, with the same reason text.
|
|
719
|
+
* The default stays ASK, so a host that wires nothing keeps today's behavior.
|
|
720
|
+
*
|
|
716
721
|
* Deliberately knob-blind: this is the fail-CLOSED posture itself, so it ignores
|
|
717
722
|
* AGENT_SANITIZER_FAIL_OPEN — a host that wires it directly keeps strictness by
|
|
718
723
|
* construction, with no env var to remember. A host that instead wants the
|
|
@@ -720,19 +725,27 @@ export function depLoadHint(
|
|
|
720
725
|
* which delegates here when the posture is closed.
|
|
721
726
|
* @param {boolean} parsedOk whether the input parsed before the failure
|
|
722
727
|
* @param {unknown} err
|
|
723
|
-
* @param {{
|
|
728
|
+
* @param {{
|
|
729
|
+
* messages?: Partial<typeof PRE_TOOL_USE_MESSAGES>,
|
|
730
|
+
* hint?: string,
|
|
731
|
+
* unavailableDecision?: (typeof PermissionDecision)[keyof typeof PermissionDecision],
|
|
732
|
+
* }} [opts]
|
|
724
733
|
* @returns {Record<string, unknown>}
|
|
725
734
|
*/
|
|
726
735
|
export function failClosedFields(parsedOk, err, opts = {}) {
|
|
727
|
-
const { hint = depLoadHint(err) } = opts;
|
|
736
|
+
const { hint = depLoadHint(err), unavailableDecision } = opts;
|
|
728
737
|
// Merged, not substituted — see judgePreToolUseSanitize. This is the call site
|
|
729
738
|
// where a missing field would throw out of the catch and fail OPEN.
|
|
730
739
|
const messages = { ...PRE_TOOL_USE_MESSAGES, ...opts.messages };
|
|
731
740
|
const cause = `${safeErrMessage(err)}${hint}`;
|
|
741
|
+
// An unknown or absent override falls back to ASK rather than being trusted:
|
|
742
|
+
// a typo must not silently widen this arm past the two closed verdicts.
|
|
743
|
+
const unavailable =
|
|
744
|
+
unavailableDecision === PermissionDecision.DENY
|
|
745
|
+
? PermissionDecision.DENY
|
|
746
|
+
: PermissionDecision.ASK;
|
|
732
747
|
return {
|
|
733
|
-
permissionDecision: parsedOk
|
|
734
|
-
? PermissionDecision.ASK
|
|
735
|
-
: PermissionDecision.DENY,
|
|
748
|
+
permissionDecision: parsedOk ? unavailable : PermissionDecision.DENY,
|
|
736
749
|
permissionDecisionReason: parsedOk
|
|
737
750
|
? messages.failed(cause)
|
|
738
751
|
: messages.unparsable(cause),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-sanitizer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.57.0",
|
|
4
4
|
"description": "Defend an agent against hidden-content injection: strip payload-capable invisible Unicode and ANSI, splice out human-invisible HTML, and flag data-exfil URLs in untrusted text before any model sees it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -109,6 +109,11 @@ export function depLoadHint(err: unknown, remedy?: string, failedPackages?: () =
|
|
|
109
109
|
* — redactor daemon down, package not loaded) is the sanitizer being UNAVAILABLE,
|
|
110
110
|
* so it ASKS to keep a human in the loop rather than hard-block on infrastructure.
|
|
111
111
|
*
|
|
112
|
+
* An UNATTENDED host has no human for that ask to reach, so the ask stops the
|
|
113
|
+
* call and buys no review. Such a host passes `unavailableDecision: DENY` and
|
|
114
|
+
* gets a hard refusal on the clean-parse arm too, with the same reason text.
|
|
115
|
+
* The default stays ASK, so a host that wires nothing keeps today's behavior.
|
|
116
|
+
*
|
|
112
117
|
* Deliberately knob-blind: this is the fail-CLOSED posture itself, so it ignores
|
|
113
118
|
* AGENT_SANITIZER_FAIL_OPEN — a host that wires it directly keeps strictness by
|
|
114
119
|
* construction, with no env var to remember. A host that instead wants the
|
|
@@ -116,12 +121,17 @@ export function depLoadHint(err: unknown, remedy?: string, failedPackages?: () =
|
|
|
116
121
|
* which delegates here when the posture is closed.
|
|
117
122
|
* @param {boolean} parsedOk whether the input parsed before the failure
|
|
118
123
|
* @param {unknown} err
|
|
119
|
-
* @param {{
|
|
124
|
+
* @param {{
|
|
125
|
+
* messages?: Partial<typeof PRE_TOOL_USE_MESSAGES>,
|
|
126
|
+
* hint?: string,
|
|
127
|
+
* unavailableDecision?: (typeof PermissionDecision)[keyof typeof PermissionDecision],
|
|
128
|
+
* }} [opts]
|
|
120
129
|
* @returns {Record<string, unknown>}
|
|
121
130
|
*/
|
|
122
131
|
export function failClosedFields(parsedOk: boolean, err: unknown, opts?: {
|
|
123
132
|
messages?: Partial<typeof PRE_TOOL_USE_MESSAGES>;
|
|
124
133
|
hint?: string;
|
|
134
|
+
unavailableDecision?: (typeof PermissionDecision)[keyof typeof PermissionDecision];
|
|
125
135
|
}): Record<string, unknown>;
|
|
126
136
|
/**
|
|
127
137
|
* True when a faulting PreToolUse call is the one case the OPEN posture must
|
|
@@ -225,4 +235,5 @@ export type HostGate = (input: {
|
|
|
225
235
|
permission_mode?: string;
|
|
226
236
|
}) => string | null | undefined;
|
|
227
237
|
declare const rehydrateRedacted: typeof import("agent-sanitizer/rehydrate").rehydrateRedacted;
|
|
238
|
+
import { PermissionDecision } from "./lib/hook-io.mjs";
|
|
228
239
|
export {};
|