@aegis-scan/core 0.16.6 → 0.17.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.
Files changed (125) hide show
  1. package/README.md +37 -0
  2. package/dist/index.d.ts +5 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +5 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/manipulation-resistance/ai-io-boundary.d.ts +84 -0
  7. package/dist/manipulation-resistance/ai-io-boundary.d.ts.map +1 -0
  8. package/dist/manipulation-resistance/ai-io-boundary.js +216 -0
  9. package/dist/manipulation-resistance/ai-io-boundary.js.map +1 -0
  10. package/dist/manipulation-resistance/config-integrity.d.ts +28 -0
  11. package/dist/manipulation-resistance/config-integrity.d.ts.map +1 -0
  12. package/dist/manipulation-resistance/config-integrity.js +53 -0
  13. package/dist/manipulation-resistance/config-integrity.js.map +1 -0
  14. package/dist/manipulation-resistance/index.d.ts +16 -0
  15. package/dist/manipulation-resistance/index.d.ts.map +1 -0
  16. package/dist/manipulation-resistance/index.js +16 -0
  17. package/dist/manipulation-resistance/index.js.map +1 -0
  18. package/dist/manipulation-resistance/instruction-boundary.d.ts +50 -0
  19. package/dist/manipulation-resistance/instruction-boundary.d.ts.map +1 -0
  20. package/dist/manipulation-resistance/instruction-boundary.js +114 -0
  21. package/dist/manipulation-resistance/instruction-boundary.js.map +1 -0
  22. package/dist/manipulation-resistance/oob-blocker.d.ts +58 -0
  23. package/dist/manipulation-resistance/oob-blocker.d.ts.map +1 -0
  24. package/dist/manipulation-resistance/oob-blocker.js +55 -0
  25. package/dist/manipulation-resistance/oob-blocker.js.map +1 -0
  26. package/dist/manipulation-resistance/redirect-policy.d.ts +43 -0
  27. package/dist/manipulation-resistance/redirect-policy.d.ts.map +1 -0
  28. package/dist/manipulation-resistance/redirect-policy.js +197 -0
  29. package/dist/manipulation-resistance/redirect-policy.js.map +1 -0
  30. package/dist/manipulation-resistance/response-validator.d.ts +33 -0
  31. package/dist/manipulation-resistance/response-validator.d.ts.map +1 -0
  32. package/dist/manipulation-resistance/response-validator.js +186 -0
  33. package/dist/manipulation-resistance/response-validator.js.map +1 -0
  34. package/dist/manipulation-resistance/scope-expansion-detector.d.ts +33 -0
  35. package/dist/manipulation-resistance/scope-expansion-detector.d.ts.map +1 -0
  36. package/dist/manipulation-resistance/scope-expansion-detector.js +68 -0
  37. package/dist/manipulation-resistance/scope-expansion-detector.js.map +1 -0
  38. package/dist/oversight/approval-gates.d.ts +77 -0
  39. package/dist/oversight/approval-gates.d.ts.map +1 -0
  40. package/dist/oversight/approval-gates.js +133 -0
  41. package/dist/oversight/approval-gates.js.map +1 -0
  42. package/dist/oversight/authority-matrix.d.ts +39 -0
  43. package/dist/oversight/authority-matrix.d.ts.map +1 -0
  44. package/dist/oversight/authority-matrix.js +75 -0
  45. package/dist/oversight/authority-matrix.js.map +1 -0
  46. package/dist/oversight/cia-scoring.d.ts +56 -0
  47. package/dist/oversight/cia-scoring.d.ts.map +1 -0
  48. package/dist/oversight/cia-scoring.js +98 -0
  49. package/dist/oversight/cia-scoring.js.map +1 -0
  50. package/dist/oversight/escalation.d.ts +58 -0
  51. package/dist/oversight/escalation.d.ts.map +1 -0
  52. package/dist/oversight/escalation.js +97 -0
  53. package/dist/oversight/escalation.js.map +1 -0
  54. package/dist/oversight/index.d.ts +15 -0
  55. package/dist/oversight/index.d.ts.map +1 -0
  56. package/dist/oversight/index.js +15 -0
  57. package/dist/oversight/index.js.map +1 -0
  58. package/dist/roe/index.d.ts +3 -0
  59. package/dist/roe/index.d.ts.map +1 -0
  60. package/dist/roe/index.js +3 -0
  61. package/dist/roe/index.js.map +1 -0
  62. package/dist/roe/loader.d.ts +15 -0
  63. package/dist/roe/loader.d.ts.map +1 -0
  64. package/dist/roe/loader.js +56 -0
  65. package/dist/roe/loader.js.map +1 -0
  66. package/dist/roe/types.d.ts +738 -0
  67. package/dist/roe/types.d.ts.map +1 -0
  68. package/dist/roe/types.js +525 -0
  69. package/dist/roe/types.js.map +1 -0
  70. package/dist/runtime/chain.d.ts +60 -0
  71. package/dist/runtime/chain.d.ts.map +1 -0
  72. package/dist/runtime/chain.js +156 -0
  73. package/dist/runtime/chain.js.map +1 -0
  74. package/dist/runtime/events.d.ts +104 -0
  75. package/dist/runtime/events.d.ts.map +1 -0
  76. package/dist/runtime/events.js +68 -0
  77. package/dist/runtime/events.js.map +1 -0
  78. package/dist/runtime/hash.d.ts +16 -0
  79. package/dist/runtime/hash.d.ts.map +1 -0
  80. package/dist/runtime/hash.js +70 -0
  81. package/dist/runtime/hash.js.map +1 -0
  82. package/dist/runtime/index.d.ts +7 -0
  83. package/dist/runtime/index.d.ts.map +1 -0
  84. package/dist/runtime/index.js +7 -0
  85. package/dist/runtime/index.js.map +1 -0
  86. package/dist/runtime/notifications.d.ts +24 -0
  87. package/dist/runtime/notifications.d.ts.map +1 -0
  88. package/dist/runtime/notifications.js +41 -0
  89. package/dist/runtime/notifications.js.map +1 -0
  90. package/dist/runtime/signals.d.ts +56 -0
  91. package/dist/runtime/signals.d.ts.map +1 -0
  92. package/dist/runtime/signals.js +72 -0
  93. package/dist/runtime/signals.js.map +1 -0
  94. package/dist/runtime/state.d.ts +88 -0
  95. package/dist/runtime/state.d.ts.map +1 -0
  96. package/dist/runtime/state.js +172 -0
  97. package/dist/runtime/state.js.map +1 -0
  98. package/dist/safety-controls/boundary-monitor.d.ts +45 -0
  99. package/dist/safety-controls/boundary-monitor.d.ts.map +1 -0
  100. package/dist/safety-controls/boundary-monitor.js +77 -0
  101. package/dist/safety-controls/boundary-monitor.js.map +1 -0
  102. package/dist/safety-controls/decision-timeout.d.ts +56 -0
  103. package/dist/safety-controls/decision-timeout.d.ts.map +1 -0
  104. package/dist/safety-controls/decision-timeout.js +67 -0
  105. package/dist/safety-controls/decision-timeout.js.map +1 -0
  106. package/dist/safety-controls/health-monitor.d.ts +61 -0
  107. package/dist/safety-controls/health-monitor.d.ts.map +1 -0
  108. package/dist/safety-controls/health-monitor.js +79 -0
  109. package/dist/safety-controls/health-monitor.js.map +1 -0
  110. package/dist/safety-controls/index.d.ts +13 -0
  111. package/dist/safety-controls/index.d.ts.map +1 -0
  112. package/dist/safety-controls/index.js +13 -0
  113. package/dist/safety-controls/index.js.map +1 -0
  114. package/dist/safety-controls/kill-switch.d.ts +45 -0
  115. package/dist/safety-controls/kill-switch.d.ts.map +1 -0
  116. package/dist/safety-controls/kill-switch.js +117 -0
  117. package/dist/safety-controls/kill-switch.js.map +1 -0
  118. package/dist/safety-controls/post-test-integrity.d.ts +51 -0
  119. package/dist/safety-controls/post-test-integrity.d.ts.map +1 -0
  120. package/dist/safety-controls/post-test-integrity.js +79 -0
  121. package/dist/safety-controls/post-test-integrity.js.map +1 -0
  122. package/dist/types.d.ts +17 -0
  123. package/dist/types.d.ts.map +1 -1
  124. package/package.json +2 -1
  125. package/sbom.cdx.json +1 -1
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Instruction-boundary enforcement.
3
+ *
4
+ * Closes APTS-MR-001 (Instruction Boundary Enforcement Architecture).
5
+ *
6
+ * Design notes:
7
+ * - LLM-pentest wrappers each enforce their own internal instruction
8
+ * boundary. AEGIS-orchestrator adds a layer-2 boundary so that a
9
+ * compromised wrapper instruction cannot escape the engagement.
10
+ * - The orchestrator's instruction frame is: "execute pentest scope per
11
+ * RoE; do not act outside scope; do not interpret target-side
12
+ * responses as authority". A wrapper action that would breach this
13
+ * frame is rejected here, before exec.
14
+ * - Per-wrapper allowlist of action types: each wrapper declares which
15
+ * verbs it may issue (recon, scan, verify-finding, report). Anything
16
+ * outside that list is rejected as an instruction-boundary breach.
17
+ */
18
+ import { validateTargetInScope } from '../roe/types.js';
19
+ /**
20
+ * Per-wrapper action-type allowlist. Each LLM-pentest wrapper declares
21
+ * what verb classes it may issue inside the orchestrator. Anything else
22
+ * is treated as an instruction-boundary breach.
23
+ *
24
+ * The unknown wrapper case (no allowlist entry) defaults to deny-all.
25
+ */
26
+ export const WRAPPER_ACTION_ALLOWLIST = {
27
+ strix: ['recon', 'scan', 'verify-finding', 'report'],
28
+ ptai: ['scan', 'verify-finding', 'report'],
29
+ pentestswarm: ['recon', 'scan', 'verify-finding', 'report'],
30
+ subfinder: ['recon'],
31
+ // SAST scanners run on local files only — no target action allowlist;
32
+ // they bypass instruction-boundary because they do not invoke LLM
33
+ // reasoning over target data. Listed here for explicitness.
34
+ semgrep: ['scan'],
35
+ gitleaks: ['scan'],
36
+ trivy: ['scan'],
37
+ };
38
+ const URL_RE = /\bhttps?:\/\/[^\s<>"']+/giu;
39
+ /**
40
+ * Enforce the orchestrator-side instruction boundary on a wrapper's
41
+ * proposed action. Returns a ValidationDecision that the caller logs into
42
+ * the audit channel and gates the action on.
43
+ *
44
+ * Checks (in order):
45
+ * 1. Action type is in the per-wrapper allowlist (unknown wrapper → deny-all).
46
+ * 2. Action target is in RoE in_scope and not in out_of_scope.
47
+ * 3. Any URL embedded in payload is in RoE scope.
48
+ */
49
+ export function enforceInstructionBoundary(wrapperName, action, roe) {
50
+ const allowedTypes = WRAPPER_ACTION_ALLOWLIST[wrapperName];
51
+ if (!allowedTypes) {
52
+ return {
53
+ allowed: false,
54
+ reason: `wrapper "${wrapperName}" has no action allowlist registered — instruction-boundary deny-all by default`,
55
+ apts_refs: ['APTS-MR-001'],
56
+ };
57
+ }
58
+ if (!allowedTypes.includes(action.type)) {
59
+ return {
60
+ allowed: false,
61
+ reason: `wrapper "${wrapperName}" attempted action type "${action.type}" outside its allowlist (${allowedTypes.join(', ')})`,
62
+ apts_refs: ['APTS-MR-001'],
63
+ };
64
+ }
65
+ const targetCheck = validateTargetInScope(action.target, roe);
66
+ if (!targetCheck.allowed) {
67
+ return {
68
+ allowed: false,
69
+ reason: `wrapper "${wrapperName}" instruction-boundary breach: ${targetCheck.reason}`,
70
+ apts_refs: ['APTS-MR-001', ...(targetCheck.apts_refs ?? [])],
71
+ };
72
+ }
73
+ const payloadUrls = extractUrls(action.payload);
74
+ for (const url of payloadUrls) {
75
+ const urlCheck = validateTargetInScope(url, roe);
76
+ if (!urlCheck.allowed) {
77
+ return {
78
+ allowed: false,
79
+ reason: `wrapper "${wrapperName}" payload includes out-of-scope URL "${url}": ${urlCheck.reason}`,
80
+ apts_refs: ['APTS-MR-001', ...(urlCheck.apts_refs ?? [])],
81
+ };
82
+ }
83
+ }
84
+ return {
85
+ allowed: true,
86
+ reason: `wrapper "${wrapperName}" action "${action.type}" on ${action.target} within instruction boundary`,
87
+ apts_refs: ['APTS-MR-001'],
88
+ };
89
+ }
90
+ /**
91
+ * Recursively walk a JSON-shaped value and pull every http(s) URL out of
92
+ * any string leaf. Used to scope-validate URLs embedded in wrapper
93
+ * payloads (e.g., a callback URL inside a structured action payload).
94
+ */
95
+ function extractUrls(value, acc = []) {
96
+ if (typeof value === 'string') {
97
+ const matches = value.match(URL_RE);
98
+ if (matches)
99
+ acc.push(...matches);
100
+ return acc;
101
+ }
102
+ if (Array.isArray(value)) {
103
+ for (const v of value)
104
+ extractUrls(v, acc);
105
+ return acc;
106
+ }
107
+ if (value !== null && typeof value === 'object') {
108
+ for (const v of Object.values(value)) {
109
+ extractUrls(v, acc);
110
+ }
111
+ }
112
+ return acc;
113
+ }
114
+ //# sourceMappingURL=instruction-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-boundary.js","sourceRoot":"","sources":["../../src/manipulation-resistance/instruction-boundary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Out-of-Band communication egress allowlist composition.
3
+ *
4
+ * Closes APTS-MR-011 (Out-of-Band Communication Prevention).
5
+ *
6
+ * Design notes:
7
+ * - LLM-pentest wrappers spawn as child processes with full network
8
+ * access by default. AEGIS composes a per-engagement egress
9
+ * allowlist from RoE in_scope hosts plus a fixed orchestrator
10
+ * essentials list (LLM provider APIs, wrapper update endpoints).
11
+ * - Allowlist is propagated to wrappers via the AEGIS_EGRESS_ALLOWLIST
12
+ * environment variable. Wrappers running in `--sandbox-mode docker`
13
+ * have it hard-enforced via `docker run --network=<name>`; in
14
+ * `--sandbox-mode none` the allowlist is a soft signal that
15
+ * cooperative wrappers consume.
16
+ * - The fixed orchestrator essentials list is intentionally short —
17
+ * anything not strictly required for the wrapper to function is
18
+ * omitted. Operators extend via RoE in_scope.
19
+ */
20
+ import type { RoE } from '../roe/types.js';
21
+ /**
22
+ * Fixed orchestrator essentials — endpoints that any LLM-pentest
23
+ * wrapper must reach to function (LLM provider APIs). Operators
24
+ * cannot remove these via RoE; they can extend via in_scope. If a
25
+ * wrapper does not need LLM access (subfinder, semgrep), it should
26
+ * be invoked without these in its env.
27
+ */
28
+ export declare const ORCHESTRATOR_ESSENTIALS: readonly string[];
29
+ export interface EgressAllowlist {
30
+ /** Hostnames + IP-literals + bare-domain entries (RoE in_scope.domains, ip_ranges, plus essentials). */
31
+ hosts: string[];
32
+ /** Comma-joined form for AEGIS_EGRESS_ALLOWLIST env var. */
33
+ envValue: string;
34
+ /** Whether LLM-provider essentials are included. False for non-LLM wrappers. */
35
+ includes_llm_essentials: boolean;
36
+ }
37
+ export interface ComposeEgressAllowlistOptions {
38
+ /** Whether the wrapper needs LLM provider access. False for subfinder/SAST. */
39
+ includeLlmEssentials?: boolean;
40
+ /**
41
+ * Operator-defined extra entries — additional CDN / package mirror /
42
+ * artifact registry hosts the wrapper needs that are not in RoE
43
+ * in_scope (RoE in_scope is for *targets*, not infrastructure).
44
+ */
45
+ extras?: readonly string[];
46
+ }
47
+ /**
48
+ * Compose the per-engagement egress allowlist from RoE in_scope plus
49
+ * orchestrator essentials. Returns the structured list and the
50
+ * AEGIS_EGRESS_ALLOWLIST env value.
51
+ */
52
+ export declare function composeEgressAllowlist(roe: RoE, opts?: ComposeEgressAllowlistOptions): EgressAllowlist;
53
+ /**
54
+ * Helper to merge the AEGIS_EGRESS_ALLOWLIST env var into a wrapper's
55
+ * spawn env without clobbering the operator's own env. Returns a copy.
56
+ */
57
+ export declare function withEgressEnv(baseEnv: NodeJS.ProcessEnv, allowlist: EgressAllowlist): NodeJS.ProcessEnv;
58
+ //# sourceMappingURL=oob-blocker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oob-blocker.d.ts","sourceRoot":"","sources":["../../src/manipulation-resistance/oob-blocker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAMnD,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,wGAAwG;IACxG,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,6BAA6B;IAC5C,+EAA+E;IAC/E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,GAAG,EACR,IAAI,GAAE,6BAAkC,GACvC,eAAe,CAwBjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,SAAS,EAAE,eAAe,GACzB,MAAM,CAAC,UAAU,CAKnB"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Fixed orchestrator essentials — endpoints that any LLM-pentest
3
+ * wrapper must reach to function (LLM provider APIs). Operators
4
+ * cannot remove these via RoE; they can extend via in_scope. If a
5
+ * wrapper does not need LLM access (subfinder, semgrep), it should
6
+ * be invoked without these in its env.
7
+ */
8
+ export const ORCHESTRATOR_ESSENTIALS = Object.freeze([
9
+ 'api.openai.com',
10
+ 'api.anthropic.com',
11
+ 'generativelanguage.googleapis.com',
12
+ 'api.cohere.ai',
13
+ 'api.mistral.ai',
14
+ ]);
15
+ /**
16
+ * Compose the per-engagement egress allowlist from RoE in_scope plus
17
+ * orchestrator essentials. Returns the structured list and the
18
+ * AEGIS_EGRESS_ALLOWLIST env value.
19
+ */
20
+ export function composeEgressAllowlist(roe, opts = {}) {
21
+ const { includeLlmEssentials = true, extras = [] } = opts;
22
+ const hosts = new Set();
23
+ for (const dom of roe.in_scope.domains) {
24
+ hosts.add(dom.pattern.toLowerCase());
25
+ if (dom.includeSubdomains && !dom.pattern.startsWith('*.')) {
26
+ hosts.add(`*.${dom.pattern.toLowerCase()}`);
27
+ }
28
+ }
29
+ for (const cidr of roe.in_scope.ip_ranges) {
30
+ hosts.add(cidr);
31
+ }
32
+ if (includeLlmEssentials) {
33
+ for (const e of ORCHESTRATOR_ESSENTIALS)
34
+ hosts.add(e);
35
+ }
36
+ for (const e of extras)
37
+ hosts.add(e.toLowerCase());
38
+ const sorted = [...hosts].sort();
39
+ return {
40
+ hosts: sorted,
41
+ envValue: sorted.join(','),
42
+ includes_llm_essentials: includeLlmEssentials,
43
+ };
44
+ }
45
+ /**
46
+ * Helper to merge the AEGIS_EGRESS_ALLOWLIST env var into a wrapper's
47
+ * spawn env without clobbering the operator's own env. Returns a copy.
48
+ */
49
+ export function withEgressEnv(baseEnv, allowlist) {
50
+ return {
51
+ ...baseEnv,
52
+ AEGIS_EGRESS_ALLOWLIST: allowlist.envValue,
53
+ };
54
+ }
55
+ //# sourceMappingURL=oob-blocker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oob-blocker.js","sourceRoot":"","sources":["../../src/manipulation-resistance/oob-blocker.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACtE,gBAAgB;IAChB,mBAAmB;IACnB,mCAAmC;IACnC,eAAe;IACf,gBAAgB;CACjB,CAAC,CAAC;AAsBH;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAQ,EACR,OAAsC,EAAE;IAExC,MAAM,EAAE,oBAAoB,GAAG,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACvC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACrC,IAAI,GAAG,CAAC,iBAAiB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QAC1C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,oBAAoB,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,uBAAuB;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACjC,OAAO;QACL,KAAK,EAAE,MAAM;QACb,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAC1B,uBAAuB,EAAE,oBAAoB;KAC9C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,OAA0B,EAC1B,SAA0B;IAE1B,OAAO;QACL,GAAG,OAAO;QACV,sBAAsB,EAAE,SAAS,CAAC,QAAQ;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ export interface SafeFetchOptions extends Omit<RequestInit, 'redirect'> {
2
+ /**
3
+ * Maximum redirect chain length. After this many manual hops, the
4
+ * request is rejected even if every intermediate URL was in policy.
5
+ * Defaults to 5.
6
+ */
7
+ maxRedirects?: number;
8
+ /**
9
+ * Operator opt-in for testing against loopback targets (127.x.x.x, ::1).
10
+ * Default false. When true, loopback resolution is reclassified as
11
+ * 'public' so the fetch succeeds. Used by `aegis siege --allow-loopback`
12
+ * for legitimate local-pentest workflows. Always emits a warning.
13
+ * Does NOT bypass the other rejections (private-ip, link-local, cloud-metadata).
14
+ */
15
+ allowLoopback?: boolean;
16
+ /** Override the DNS lookup for tests. Resolves a hostname to an IPv4. */
17
+ dnsLookup?: (hostname: string) => Promise<string>;
18
+ /** Override the underlying fetch — for tests. */
19
+ fetchImpl?: typeof fetch;
20
+ }
21
+ export interface SafeFetchRejection extends Error {
22
+ reason: SafeFetchRejectReason;
23
+ apts_refs: string[];
24
+ url?: string;
25
+ }
26
+ export type SafeFetchRejectReason = 'non-http-protocol' | 'private-ip' | 'loopback-ip' | 'link-local-ip' | 'cloud-metadata-ip' | 'dns-resolution-failed' | 'redirect-chain-too-long' | 'redirect-target-rejected';
27
+ /**
28
+ * SSRF-hardened HTTP client. Throws SafeFetchRejection on policy
29
+ * violation; otherwise delegates to the underlying fetch with manual
30
+ * redirect handling so each Location is re-validated.
31
+ */
32
+ export declare function safeFetch(url: string, init?: SafeFetchOptions): Promise<Response>;
33
+ type IpClass = 'public' | 'private' | 'loopback' | 'link-local' | 'cloud-metadata';
34
+ /**
35
+ * Classify an IPv4 or IPv6 address. Conservative: anything not
36
+ * recognized as public (RFC 1918, link-local, loopback, multicast,
37
+ * cloud-metadata) is rejected.
38
+ */
39
+ export declare function classifyIp(ip: string): IpClass;
40
+ /** Type guard for use by callers that want to differentiate policy rejections. */
41
+ export declare function isSafeFetchRejection(err: unknown): err is SafeFetchRejection;
42
+ export {};
43
+ //# sourceMappingURL=redirect-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-policy.d.ts","sourceRoot":"","sources":["../../src/manipulation-resistance/redirect-policy.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC;IACrE;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK;IAC/C,MAAM,EAAE,qBAAqB,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,qBAAqB,GAC7B,mBAAmB,GACnB,YAAY,GACZ,aAAa,GACb,eAAe,GACf,mBAAmB,GACnB,uBAAuB,GACvB,yBAAyB,GACzB,0BAA0B,CAAC;AAE/B;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAgCnB;AA6DD,KAAK,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAI9C;AAoED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,kBAAkB,CAE5E"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Safe-fetch — orchestrator-side HTTP client with redirect, DNS-rebind,
3
+ * and SSRF defenses.
4
+ *
5
+ * Closes APTS-MR-007 (Redirect Following Vulnerability Testing) +
6
+ * APTS-MR-008 (DNS Rebinding Attack Resistance) + APTS-MR-009 (SSRF
7
+ * Vulnerability Testing in AI Pentest Framework).
8
+ *
9
+ * Design notes:
10
+ * - safeFetch is the orchestrator's HTTP egress surface for recon +
11
+ * finding-verification. It never follows redirects automatically;
12
+ * each Location header is re-validated against the same policy.
13
+ * - DNS rebinding defense: the resolved IP is pinned at first lookup;
14
+ * subsequent connections to the same host go via the pinned IP. We
15
+ * resolve the host once, validate the IP class, and short-circuit
16
+ * to a private/link-local/cloud-metadata reject if needed.
17
+ * - SSRF defense: requests against private (RFC 1918), link-local
18
+ * (169.254/16), loopback (127/8 + ::1), and cloud-metadata
19
+ * (169.254.169.254 + fd00:ec2::254) are rejected outright.
20
+ * - Non-HTTP(S) protocols are rejected — file://, gopher://,
21
+ * dict://, ftp:// have all been used in SSRF chains.
22
+ * - This is the orchestrator's own HTTP client. SAST-side
23
+ * ssrf-checker scans target source for these same patterns; the
24
+ * two defenses are independent.
25
+ */
26
+ import { lookup } from 'node:dns/promises';
27
+ /**
28
+ * SSRF-hardened HTTP client. Throws SafeFetchRejection on policy
29
+ * violation; otherwise delegates to the underlying fetch with manual
30
+ * redirect handling so each Location is re-validated.
31
+ */
32
+ export async function safeFetch(url, init = {}) {
33
+ const maxRedirects = init.maxRedirects ?? 5;
34
+ const dnsLookup = init.dnsLookup ?? defaultDnsLookup;
35
+ const fetchImpl = init.fetchImpl ?? fetch;
36
+ const allowLoopback = init.allowLoopback === true;
37
+ let currentUrl = url;
38
+ for (let hop = 0; hop <= maxRedirects; hop++) {
39
+ const policyCheck = await urlPolicyCheck(currentUrl, dnsLookup, allowLoopback);
40
+ if (!policyCheck.ok) {
41
+ throw makeRejection(policyCheck.reason, currentUrl);
42
+ }
43
+ const { dnsLookup: _omitDns, fetchImpl: _omitFetch, maxRedirects: _omitMax, ...rest } = init;
44
+ const response = await fetchImpl(currentUrl, { ...rest, redirect: 'manual' });
45
+ if (![301, 302, 303, 307, 308].includes(response.status)) {
46
+ return response;
47
+ }
48
+ const location = response.headers.get('location');
49
+ if (!location) {
50
+ // 3xx without Location header — treat as a final response so the
51
+ // caller observes the unusual shape.
52
+ return response;
53
+ }
54
+ if (hop === maxRedirects) {
55
+ throw makeRejection('redirect-chain-too-long', currentUrl);
56
+ }
57
+ currentUrl = new URL(location, currentUrl).toString();
58
+ }
59
+ // Unreachable — the loop either returns a Response or throws.
60
+ throw makeRejection('redirect-chain-too-long', currentUrl);
61
+ }
62
+ async function urlPolicyCheck(rawUrl, dnsLookup, allowLoopback) {
63
+ let parsed;
64
+ try {
65
+ parsed = new URL(rawUrl);
66
+ }
67
+ catch {
68
+ return { ok: false, reason: 'non-http-protocol' };
69
+ }
70
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
71
+ return { ok: false, reason: 'non-http-protocol' };
72
+ }
73
+ const hostname = parsed.hostname.toLowerCase();
74
+ // Bracketed IPv6 → strip brackets for classification
75
+ const hostKey = hostname.startsWith('[') && hostname.endsWith(']')
76
+ ? hostname.slice(1, -1)
77
+ : hostname;
78
+ // Direct IP literal → classify without DNS lookup
79
+ if (isIpLiteral(hostKey)) {
80
+ const ipClass = classifyIp(hostKey);
81
+ if (ipClass === 'loopback' && allowLoopback) {
82
+ return { ok: true, resolvedIp: hostKey };
83
+ }
84
+ if (ipClass !== 'public')
85
+ return { ok: false, reason: ipReasonOf(ipClass) };
86
+ return { ok: true, resolvedIp: hostKey };
87
+ }
88
+ let resolvedIp;
89
+ try {
90
+ resolvedIp = await dnsLookup(hostKey);
91
+ }
92
+ catch {
93
+ return { ok: false, reason: 'dns-resolution-failed' };
94
+ }
95
+ const ipClass = classifyIp(resolvedIp);
96
+ if (ipClass === 'loopback' && allowLoopback) {
97
+ return { ok: true, resolvedIp };
98
+ }
99
+ if (ipClass !== 'public')
100
+ return { ok: false, reason: ipReasonOf(ipClass) };
101
+ return { ok: true, resolvedIp };
102
+ }
103
+ async function defaultDnsLookup(hostname) {
104
+ const result = await lookup(hostname, { family: 0 });
105
+ return result.address;
106
+ }
107
+ /**
108
+ * Classify an IPv4 or IPv6 address. Conservative: anything not
109
+ * recognized as public (RFC 1918, link-local, loopback, multicast,
110
+ * cloud-metadata) is rejected.
111
+ */
112
+ export function classifyIp(ip) {
113
+ if (isIpv4(ip))
114
+ return classifyIpv4(ip);
115
+ if (isIpv6(ip))
116
+ return classifyIpv6(ip);
117
+ return 'private'; // unparseable → treat as non-public
118
+ }
119
+ function isIpLiteral(s) {
120
+ return isIpv4(s) || isIpv6(s);
121
+ }
122
+ function isIpv4(s) {
123
+ return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(s);
124
+ }
125
+ function isIpv6(s) {
126
+ // Loose match — handles compressed forms; full RFC validation is
127
+ // not required since classifyIpv6 short-circuits to safe defaults
128
+ // on unrecognized shapes.
129
+ return /^[0-9a-fA-F:]+$/.test(s) && s.includes(':');
130
+ }
131
+ function classifyIpv4(ip) {
132
+ if (ip === '169.254.169.254')
133
+ return 'cloud-metadata';
134
+ const parts = ip.split('.').map((p) => Number.parseInt(p, 10));
135
+ if (parts.some((n) => !Number.isFinite(n) || n < 0 || n > 255))
136
+ return 'private';
137
+ const [a, b] = parts;
138
+ if (a === 127)
139
+ return 'loopback';
140
+ if (a === 10)
141
+ return 'private';
142
+ if (a === 172 && b >= 16 && b <= 31)
143
+ return 'private';
144
+ if (a === 192 && b === 168)
145
+ return 'private';
146
+ if (a === 169 && b === 254)
147
+ return 'link-local';
148
+ if (a === 0)
149
+ return 'private';
150
+ if (a >= 224)
151
+ return 'private'; // multicast/reserved
152
+ return 'public';
153
+ }
154
+ function classifyIpv6(raw) {
155
+ const ip = raw.toLowerCase();
156
+ if (ip === '::1')
157
+ return 'loopback';
158
+ if (ip === '::' || ip === '::0')
159
+ return 'private';
160
+ if (ip.startsWith('fe80:'))
161
+ return 'link-local';
162
+ // Unique-local (fc00::/7)
163
+ if (/^f[cd][0-9a-f]{2}:/.test(ip))
164
+ return 'private';
165
+ // Cloud metadata (AWS IMDS over IPv6)
166
+ if (ip === 'fd00:ec2::254')
167
+ return 'cloud-metadata';
168
+ if (ip.startsWith('ff'))
169
+ return 'private'; // multicast
170
+ return 'public';
171
+ }
172
+ function ipReasonOf(c) {
173
+ switch (c) {
174
+ case 'private':
175
+ return 'private-ip';
176
+ case 'loopback':
177
+ return 'loopback-ip';
178
+ case 'link-local':
179
+ return 'link-local-ip';
180
+ case 'cloud-metadata':
181
+ return 'cloud-metadata-ip';
182
+ default:
183
+ return 'private-ip';
184
+ }
185
+ }
186
+ function makeRejection(reason, url) {
187
+ const err = new Error(`safeFetch rejected: ${reason} (${url})`);
188
+ err.reason = reason;
189
+ err.url = url;
190
+ err.apts_refs = ['APTS-MR-007', 'APTS-MR-008', 'APTS-MR-009'];
191
+ return err;
192
+ }
193
+ /** Type guard for use by callers that want to differentiate policy rejections. */
194
+ export function isSafeFetchRejection(err) {
195
+ return err instanceof Error && typeof err.reason === 'string';
196
+ }
197
+ //# sourceMappingURL=redirect-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-policy.js","sourceRoot":"","sources":["../../src/manipulation-resistance/redirect-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface ResponseValidation {
2
+ ok: boolean;
3
+ cleaned?: unknown;
4
+ reason?: string;
5
+ apts_refs?: string[];
6
+ }
7
+ /**
8
+ * Validate + sanitize a wrapper's structured output before propagating
9
+ * to Findings. Returns { ok: true, cleaned } on success or
10
+ * { ok: false, reason } with an APTS reference on rejection.
11
+ */
12
+ export declare function validateWrapperResponse(wrapperName: string, raw: unknown): ResponseValidation;
13
+ export type AuthorityClaim = 'none' | 'admin' | 'root' | 'rce' | 'reverse-shell';
14
+ export interface AuthorityClaimResult {
15
+ claim: AuthorityClaim;
16
+ rationale: string;
17
+ matched_phrase?: string;
18
+ suggested_action: 'pass' | 'verify' | 'reject';
19
+ apts_refs: string[];
20
+ }
21
+ /**
22
+ * Detect authority claims in finding text. Returns the strongest match
23
+ * (RCE > root > admin) or `claim: 'none'` if no pattern fires.
24
+ *
25
+ * Suggested-action policy:
26
+ * - 'reject' for RCE / reverse-shell — these are high-impact assertions
27
+ * that AEGIS must not propagate without operator confirmation.
28
+ * - 'verify' for root/admin — pause for operator confirmation via
29
+ * SIGUSR1 resume, then proceed if confirmed.
30
+ * - 'pass' when no claim detected.
31
+ */
32
+ export declare function detectAuthorityClaim(findingText: string): AuthorityClaimResult;
33
+ //# sourceMappingURL=response-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-validator.d.ts","sourceRoot":"","sources":["../../src/manipulation-resistance/response-validator.ts"],"names":[],"mappings":"AA0FA,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,OAAO,GACX,kBAAkB,CAyBpB;AA2BD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,eAAe,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC/C,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAmB9E"}