protect-mcp 0.7.6 → 0.9.2
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/CHANGELOG.md +64 -0
- package/README.md +2 -2
- package/dist/{chunk-6E2DHBAR.mjs → chunk-744JMCY4.mjs} +9 -1
- package/dist/chunk-AYNQIEN7.mjs +10 -0
- package/dist/{chunk-JCMDLN5I.mjs → chunk-CXW2EIRM.mjs} +2 -2
- package/dist/{chunk-LJQOALYR.mjs → chunk-FFVJL3KQ.mjs} +5 -564
- package/dist/{chunk-VTPZ4G5I.mjs → chunk-GHR65WVD.mjs} +1 -1
- package/dist/{chunk-WIPWNWMJ.mjs → chunk-IDUH2O4Q.mjs} +1 -0
- package/dist/chunk-JIDDQUSQ.mjs +568 -0
- package/dist/chunk-KMNXHGGT.mjs +94 -0
- package/dist/{chunk-WV4DKYE4.mjs → chunk-UWB5ALVO.mjs} +10 -12
- package/dist/claim-TUDH2WPB.mjs +201 -0
- package/dist/cli.js +610 -31
- package/dist/cli.mjs +308 -24
- package/dist/{ed25519-BSHMMVNX.mjs → ed25519-SQA3S2RV.mjs} +2 -1
- package/dist/hook-server.js +428 -0
- package/dist/hook-server.mjs +6 -2
- package/dist/{http-transport-JBORN27G.mjs → http-transport-D7C64PIA.mjs} +2 -2
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +107 -18
- package/dist/index.mjs +14 -9
- package/dist/{signing-committed-QXCW24RF.mjs → signing-committed-TGWXSLAO.mjs} +4 -2
- package/package.json +1 -1
- package/policies/agent.cedar +0 -50
package/dist/hook-server.js
CHANGED
|
@@ -320,6 +320,7 @@ function signDecision(entry) {
|
|
|
320
320
|
if (entry.timing) payload.timing = entry.timing;
|
|
321
321
|
if (entry.swarm) payload.swarm = entry.swarm;
|
|
322
322
|
if (entry.payload_digest) payload.payload_digest = entry.payload_digest;
|
|
323
|
+
if (entry.enrichment) payload.enrichment = entry.enrichment;
|
|
323
324
|
if (entry.action_readback) payload.action_readback = entry.action_readback;
|
|
324
325
|
if (entry.deny_iteration) payload.deny_iteration = entry.deny_iteration;
|
|
325
326
|
const result = artifactsModule.createSignedArtifact(
|
|
@@ -703,6 +704,423 @@ function buildActionReadback(tool, input) {
|
|
|
703
704
|
};
|
|
704
705
|
}
|
|
705
706
|
|
|
707
|
+
// node_modules/@noble/hashes/esm/utils.js
|
|
708
|
+
function isBytes(a) {
|
|
709
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
710
|
+
}
|
|
711
|
+
function abytes(b, ...lengths) {
|
|
712
|
+
if (!isBytes(b))
|
|
713
|
+
throw new Error("Uint8Array expected");
|
|
714
|
+
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
715
|
+
throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
|
|
716
|
+
}
|
|
717
|
+
function aexists(instance, checkFinished = true) {
|
|
718
|
+
if (instance.destroyed)
|
|
719
|
+
throw new Error("Hash instance has been destroyed");
|
|
720
|
+
if (checkFinished && instance.finished)
|
|
721
|
+
throw new Error("Hash#digest() has already been called");
|
|
722
|
+
}
|
|
723
|
+
function aoutput(out, instance) {
|
|
724
|
+
abytes(out);
|
|
725
|
+
const min = instance.outputLen;
|
|
726
|
+
if (out.length < min) {
|
|
727
|
+
throw new Error("digestInto() expects output buffer of length at least " + min);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function clean(...arrays) {
|
|
731
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
732
|
+
arrays[i].fill(0);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function createView(arr) {
|
|
736
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
737
|
+
}
|
|
738
|
+
function rotr(word, shift) {
|
|
739
|
+
return word << 32 - shift | word >>> shift;
|
|
740
|
+
}
|
|
741
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
742
|
+
// @ts-ignore
|
|
743
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
744
|
+
))();
|
|
745
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
746
|
+
function bytesToHex(bytes) {
|
|
747
|
+
abytes(bytes);
|
|
748
|
+
if (hasHexBuiltin)
|
|
749
|
+
return bytes.toHex();
|
|
750
|
+
let hex = "";
|
|
751
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
752
|
+
hex += hexes[bytes[i]];
|
|
753
|
+
}
|
|
754
|
+
return hex;
|
|
755
|
+
}
|
|
756
|
+
function utf8ToBytes(str) {
|
|
757
|
+
if (typeof str !== "string")
|
|
758
|
+
throw new Error("string expected");
|
|
759
|
+
return new Uint8Array(new TextEncoder().encode(str));
|
|
760
|
+
}
|
|
761
|
+
function toBytes(data) {
|
|
762
|
+
if (typeof data === "string")
|
|
763
|
+
data = utf8ToBytes(data);
|
|
764
|
+
abytes(data);
|
|
765
|
+
return data;
|
|
766
|
+
}
|
|
767
|
+
var Hash = class {
|
|
768
|
+
};
|
|
769
|
+
function createHasher(hashCons) {
|
|
770
|
+
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
|
|
771
|
+
const tmp = hashCons();
|
|
772
|
+
hashC.outputLen = tmp.outputLen;
|
|
773
|
+
hashC.blockLen = tmp.blockLen;
|
|
774
|
+
hashC.create = () => hashCons();
|
|
775
|
+
return hashC;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// node_modules/@noble/hashes/esm/_md.js
|
|
779
|
+
function setBigUint64(view, byteOffset, value, isLE) {
|
|
780
|
+
if (typeof view.setBigUint64 === "function")
|
|
781
|
+
return view.setBigUint64(byteOffset, value, isLE);
|
|
782
|
+
const _32n = BigInt(32);
|
|
783
|
+
const _u32_max = BigInt(4294967295);
|
|
784
|
+
const wh = Number(value >> _32n & _u32_max);
|
|
785
|
+
const wl = Number(value & _u32_max);
|
|
786
|
+
const h = isLE ? 4 : 0;
|
|
787
|
+
const l = isLE ? 0 : 4;
|
|
788
|
+
view.setUint32(byteOffset + h, wh, isLE);
|
|
789
|
+
view.setUint32(byteOffset + l, wl, isLE);
|
|
790
|
+
}
|
|
791
|
+
function Chi(a, b, c) {
|
|
792
|
+
return a & b ^ ~a & c;
|
|
793
|
+
}
|
|
794
|
+
function Maj(a, b, c) {
|
|
795
|
+
return a & b ^ a & c ^ b & c;
|
|
796
|
+
}
|
|
797
|
+
var HashMD = class extends Hash {
|
|
798
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
799
|
+
super();
|
|
800
|
+
this.finished = false;
|
|
801
|
+
this.length = 0;
|
|
802
|
+
this.pos = 0;
|
|
803
|
+
this.destroyed = false;
|
|
804
|
+
this.blockLen = blockLen;
|
|
805
|
+
this.outputLen = outputLen;
|
|
806
|
+
this.padOffset = padOffset;
|
|
807
|
+
this.isLE = isLE;
|
|
808
|
+
this.buffer = new Uint8Array(blockLen);
|
|
809
|
+
this.view = createView(this.buffer);
|
|
810
|
+
}
|
|
811
|
+
update(data) {
|
|
812
|
+
aexists(this);
|
|
813
|
+
data = toBytes(data);
|
|
814
|
+
abytes(data);
|
|
815
|
+
const { view, buffer, blockLen } = this;
|
|
816
|
+
const len = data.length;
|
|
817
|
+
for (let pos = 0; pos < len; ) {
|
|
818
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
819
|
+
if (take === blockLen) {
|
|
820
|
+
const dataView = createView(data);
|
|
821
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
822
|
+
this.process(dataView, pos);
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
826
|
+
this.pos += take;
|
|
827
|
+
pos += take;
|
|
828
|
+
if (this.pos === blockLen) {
|
|
829
|
+
this.process(view, 0);
|
|
830
|
+
this.pos = 0;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
this.length += data.length;
|
|
834
|
+
this.roundClean();
|
|
835
|
+
return this;
|
|
836
|
+
}
|
|
837
|
+
digestInto(out) {
|
|
838
|
+
aexists(this);
|
|
839
|
+
aoutput(out, this);
|
|
840
|
+
this.finished = true;
|
|
841
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
842
|
+
let { pos } = this;
|
|
843
|
+
buffer[pos++] = 128;
|
|
844
|
+
clean(this.buffer.subarray(pos));
|
|
845
|
+
if (this.padOffset > blockLen - pos) {
|
|
846
|
+
this.process(view, 0);
|
|
847
|
+
pos = 0;
|
|
848
|
+
}
|
|
849
|
+
for (let i = pos; i < blockLen; i++)
|
|
850
|
+
buffer[i] = 0;
|
|
851
|
+
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
|
|
852
|
+
this.process(view, 0);
|
|
853
|
+
const oview = createView(out);
|
|
854
|
+
const len = this.outputLen;
|
|
855
|
+
if (len % 4)
|
|
856
|
+
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
857
|
+
const outLen = len / 4;
|
|
858
|
+
const state = this.get();
|
|
859
|
+
if (outLen > state.length)
|
|
860
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
861
|
+
for (let i = 0; i < outLen; i++)
|
|
862
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
863
|
+
}
|
|
864
|
+
digest() {
|
|
865
|
+
const { buffer, outputLen } = this;
|
|
866
|
+
this.digestInto(buffer);
|
|
867
|
+
const res = buffer.slice(0, outputLen);
|
|
868
|
+
this.destroy();
|
|
869
|
+
return res;
|
|
870
|
+
}
|
|
871
|
+
_cloneInto(to) {
|
|
872
|
+
to || (to = new this.constructor());
|
|
873
|
+
to.set(...this.get());
|
|
874
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
875
|
+
to.destroyed = destroyed;
|
|
876
|
+
to.finished = finished;
|
|
877
|
+
to.length = length;
|
|
878
|
+
to.pos = pos;
|
|
879
|
+
if (length % blockLen)
|
|
880
|
+
to.buffer.set(buffer);
|
|
881
|
+
return to;
|
|
882
|
+
}
|
|
883
|
+
clone() {
|
|
884
|
+
return this._cloneInto();
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
888
|
+
1779033703,
|
|
889
|
+
3144134277,
|
|
890
|
+
1013904242,
|
|
891
|
+
2773480762,
|
|
892
|
+
1359893119,
|
|
893
|
+
2600822924,
|
|
894
|
+
528734635,
|
|
895
|
+
1541459225
|
|
896
|
+
]);
|
|
897
|
+
|
|
898
|
+
// node_modules/@noble/hashes/esm/sha2.js
|
|
899
|
+
var SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
900
|
+
1116352408,
|
|
901
|
+
1899447441,
|
|
902
|
+
3049323471,
|
|
903
|
+
3921009573,
|
|
904
|
+
961987163,
|
|
905
|
+
1508970993,
|
|
906
|
+
2453635748,
|
|
907
|
+
2870763221,
|
|
908
|
+
3624381080,
|
|
909
|
+
310598401,
|
|
910
|
+
607225278,
|
|
911
|
+
1426881987,
|
|
912
|
+
1925078388,
|
|
913
|
+
2162078206,
|
|
914
|
+
2614888103,
|
|
915
|
+
3248222580,
|
|
916
|
+
3835390401,
|
|
917
|
+
4022224774,
|
|
918
|
+
264347078,
|
|
919
|
+
604807628,
|
|
920
|
+
770255983,
|
|
921
|
+
1249150122,
|
|
922
|
+
1555081692,
|
|
923
|
+
1996064986,
|
|
924
|
+
2554220882,
|
|
925
|
+
2821834349,
|
|
926
|
+
2952996808,
|
|
927
|
+
3210313671,
|
|
928
|
+
3336571891,
|
|
929
|
+
3584528711,
|
|
930
|
+
113926993,
|
|
931
|
+
338241895,
|
|
932
|
+
666307205,
|
|
933
|
+
773529912,
|
|
934
|
+
1294757372,
|
|
935
|
+
1396182291,
|
|
936
|
+
1695183700,
|
|
937
|
+
1986661051,
|
|
938
|
+
2177026350,
|
|
939
|
+
2456956037,
|
|
940
|
+
2730485921,
|
|
941
|
+
2820302411,
|
|
942
|
+
3259730800,
|
|
943
|
+
3345764771,
|
|
944
|
+
3516065817,
|
|
945
|
+
3600352804,
|
|
946
|
+
4094571909,
|
|
947
|
+
275423344,
|
|
948
|
+
430227734,
|
|
949
|
+
506948616,
|
|
950
|
+
659060556,
|
|
951
|
+
883997877,
|
|
952
|
+
958139571,
|
|
953
|
+
1322822218,
|
|
954
|
+
1537002063,
|
|
955
|
+
1747873779,
|
|
956
|
+
1955562222,
|
|
957
|
+
2024104815,
|
|
958
|
+
2227730452,
|
|
959
|
+
2361852424,
|
|
960
|
+
2428436474,
|
|
961
|
+
2756734187,
|
|
962
|
+
3204031479,
|
|
963
|
+
3329325298
|
|
964
|
+
]);
|
|
965
|
+
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
966
|
+
var SHA256 = class extends HashMD {
|
|
967
|
+
constructor(outputLen = 32) {
|
|
968
|
+
super(64, outputLen, 8, false);
|
|
969
|
+
this.A = SHA256_IV[0] | 0;
|
|
970
|
+
this.B = SHA256_IV[1] | 0;
|
|
971
|
+
this.C = SHA256_IV[2] | 0;
|
|
972
|
+
this.D = SHA256_IV[3] | 0;
|
|
973
|
+
this.E = SHA256_IV[4] | 0;
|
|
974
|
+
this.F = SHA256_IV[5] | 0;
|
|
975
|
+
this.G = SHA256_IV[6] | 0;
|
|
976
|
+
this.H = SHA256_IV[7] | 0;
|
|
977
|
+
}
|
|
978
|
+
get() {
|
|
979
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
980
|
+
return [A, B, C, D, E, F, G, H];
|
|
981
|
+
}
|
|
982
|
+
// prettier-ignore
|
|
983
|
+
set(A, B, C, D, E, F, G, H) {
|
|
984
|
+
this.A = A | 0;
|
|
985
|
+
this.B = B | 0;
|
|
986
|
+
this.C = C | 0;
|
|
987
|
+
this.D = D | 0;
|
|
988
|
+
this.E = E | 0;
|
|
989
|
+
this.F = F | 0;
|
|
990
|
+
this.G = G | 0;
|
|
991
|
+
this.H = H | 0;
|
|
992
|
+
}
|
|
993
|
+
process(view, offset) {
|
|
994
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
995
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
996
|
+
for (let i = 16; i < 64; i++) {
|
|
997
|
+
const W15 = SHA256_W[i - 15];
|
|
998
|
+
const W2 = SHA256_W[i - 2];
|
|
999
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
1000
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
1001
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
1002
|
+
}
|
|
1003
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
1004
|
+
for (let i = 0; i < 64; i++) {
|
|
1005
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
1006
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
1007
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
1008
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
1009
|
+
H = G;
|
|
1010
|
+
G = F;
|
|
1011
|
+
F = E;
|
|
1012
|
+
E = D + T1 | 0;
|
|
1013
|
+
D = C;
|
|
1014
|
+
C = B;
|
|
1015
|
+
B = A;
|
|
1016
|
+
A = T1 + T2 | 0;
|
|
1017
|
+
}
|
|
1018
|
+
A = A + this.A | 0;
|
|
1019
|
+
B = B + this.B | 0;
|
|
1020
|
+
C = C + this.C | 0;
|
|
1021
|
+
D = D + this.D | 0;
|
|
1022
|
+
E = E + this.E | 0;
|
|
1023
|
+
F = F + this.F | 0;
|
|
1024
|
+
G = G + this.G | 0;
|
|
1025
|
+
H = H + this.H | 0;
|
|
1026
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
1027
|
+
}
|
|
1028
|
+
roundClean() {
|
|
1029
|
+
clean(SHA256_W);
|
|
1030
|
+
}
|
|
1031
|
+
destroy() {
|
|
1032
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
1033
|
+
clean(this.buffer);
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
var sha256 = /* @__PURE__ */ createHasher(() => new SHA256());
|
|
1037
|
+
|
|
1038
|
+
// node_modules/@noble/hashes/esm/sha256.js
|
|
1039
|
+
var sha2562 = sha256;
|
|
1040
|
+
|
|
1041
|
+
// src/receipt-enrichment.ts
|
|
1042
|
+
var ENRICHMENT_VERSION = 1;
|
|
1043
|
+
function canonicalJson(value) {
|
|
1044
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1045
|
+
const enc = (v) => {
|
|
1046
|
+
if (v === null || v === void 0) return "null";
|
|
1047
|
+
const t = typeof v;
|
|
1048
|
+
if (t === "number") return Number.isFinite(v) ? JSON.stringify(v) : "null";
|
|
1049
|
+
if (t === "boolean" || t === "string") return JSON.stringify(v);
|
|
1050
|
+
if (t === "bigint") return JSON.stringify(v.toString());
|
|
1051
|
+
if (t === "function" || t === "symbol") return "null";
|
|
1052
|
+
if (Array.isArray(v)) return "[" + v.map(enc).join(",") + "]";
|
|
1053
|
+
if (t === "object") {
|
|
1054
|
+
const o = v;
|
|
1055
|
+
if (seen.has(o)) return '"[circular]"';
|
|
1056
|
+
seen.add(o);
|
|
1057
|
+
const body = Object.keys(o).sort().map((k) => JSON.stringify(k) + ":" + enc(o[k])).join(",");
|
|
1058
|
+
seen.delete(o);
|
|
1059
|
+
return "{" + body + "}";
|
|
1060
|
+
}
|
|
1061
|
+
return "null";
|
|
1062
|
+
};
|
|
1063
|
+
return enc(value);
|
|
1064
|
+
}
|
|
1065
|
+
function sha256Hex(s) {
|
|
1066
|
+
return bytesToHex(sha2562(new TextEncoder().encode(s)));
|
|
1067
|
+
}
|
|
1068
|
+
var RULES = [
|
|
1069
|
+
{ cap: "exec.shell", tool: /bash|shell|exec|terminal|run_command|command/ },
|
|
1070
|
+
{ cap: "fs.read", tool: /(^|[_.])(read|cat|glob|grep|search|ls|view|list_files|open)/ },
|
|
1071
|
+
{ cap: "fs.write", tool: /write|create_file|save|append|edit|patch|replace|update_file|multiedit|notebook/ },
|
|
1072
|
+
{ cap: "fs.delete", tool: /delete|remove|unlink|trash|(^|[_.])rm/ },
|
|
1073
|
+
{ cap: "net.egress", tool: /fetch|http|curl|wget|request|download|browse|navigate|webfetch|web_search|scrape/ },
|
|
1074
|
+
{ cap: "vcs", tool: /(^|[_.])git/, text: /\bgit\s+(commit|push|pull|clone|reset|checkout|branch|rebase|merge|tag)\b/ },
|
|
1075
|
+
{ cap: "package.install", text: /\b(npm|pnpm|yarn)\s+(i|install|add)\b|\bpip3?\s+install\b|\bgo\s+get\b|\bcargo\s+add\b|\bbrew\s+install\b|\bapt(-get)?\s+install\b|\bgem\s+install\b/ },
|
|
1076
|
+
{ cap: "secret.adjacent", text: /\.env\b|secret|credential|passwd|password|api[_-]?key|private[_-]?key|\.pem\b|\.key\b|id_rsa|bearer\s|aws_(access|secret)|authorization/ },
|
|
1077
|
+
{ cap: "destructive", text: /rm\s+-[a-z]*[rf]|\brmdir\b|drop\s+table|truncate\s+table|delete\s+from|reset\s+--hard|--force\b|\bmkfs\b|\bdd\s+if=|shutdown|reboot|kill\s+-9|>\s*\/dev\/sd/ },
|
|
1078
|
+
{ cap: "financial", text: /\b(order|trade|buy|sell|transfer|wire|payment|withdraw|deposit|swap|invoice|charge|refund|settle)\b/ },
|
|
1079
|
+
{ cap: "data.query", text: /\bselect\s+[\s\S]+\bfrom\b|\binsert\s+into\b|\bupdate\s+[\s\S]+\bset\b|\bdelete\s+from\b/ }
|
|
1080
|
+
];
|
|
1081
|
+
function deriveCapabilities(tool, input) {
|
|
1082
|
+
const t = String(tool || "").toLowerCase();
|
|
1083
|
+
let text = "";
|
|
1084
|
+
try {
|
|
1085
|
+
text = canonicalJson(input).toLowerCase();
|
|
1086
|
+
} catch {
|
|
1087
|
+
}
|
|
1088
|
+
const caps = /* @__PURE__ */ new Set();
|
|
1089
|
+
for (const r of RULES) {
|
|
1090
|
+
if (r.tool && r.tool.test(t)) caps.add(r.cap);
|
|
1091
|
+
if (r.text && r.text.test(text)) caps.add(r.cap);
|
|
1092
|
+
}
|
|
1093
|
+
return Array.from(caps).sort();
|
|
1094
|
+
}
|
|
1095
|
+
function deriveResource(input) {
|
|
1096
|
+
const o = input && typeof input === "object" ? input : {};
|
|
1097
|
+
const path = o.file_path ?? o.path ?? o.filePath ?? o.notebook_path ?? o.filename;
|
|
1098
|
+
if (typeof path === "string" && path.trim()) return { kind: "path", digest: sha256Hex(path.replace(/\\/g, "/")) };
|
|
1099
|
+
const url = o.url ?? o.uri ?? o.endpoint ?? o.href;
|
|
1100
|
+
if (typeof url === "string" && url.trim()) {
|
|
1101
|
+
try {
|
|
1102
|
+
return { kind: "host", digest: sha256Hex(new URL(url).host.toLowerCase()) };
|
|
1103
|
+
} catch {
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
const cmd = o.command ?? o.cmd ?? o.script;
|
|
1107
|
+
if (typeof cmd === "string" && cmd.trim()) {
|
|
1108
|
+
const first = cmd.trim().split(/\s+/)[0];
|
|
1109
|
+
if (first) return { kind: "command", digest: sha256Hex(first) };
|
|
1110
|
+
}
|
|
1111
|
+
return void 0;
|
|
1112
|
+
}
|
|
1113
|
+
function buildEnrichment(tool, input) {
|
|
1114
|
+
const e = {
|
|
1115
|
+
v: ENRICHMENT_VERSION,
|
|
1116
|
+
input_digest: sha256Hex(canonicalJson(input ?? {})),
|
|
1117
|
+
capabilities: deriveCapabilities(tool, input)
|
|
1118
|
+
};
|
|
1119
|
+
const resource = deriveResource(input);
|
|
1120
|
+
if (resource) e.resource = resource;
|
|
1121
|
+
return e;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
706
1124
|
// src/hook-server.ts
|
|
707
1125
|
var DEFAULT_PORT = 9377;
|
|
708
1126
|
var LOG_FILE = ".protect-mcp-log.jsonl";
|
|
@@ -775,6 +1193,9 @@ async function handlePreToolUse(input, state) {
|
|
|
775
1193
|
});
|
|
776
1194
|
const payloadDigest = computePayloadDigest(input.toolInput);
|
|
777
1195
|
const actionReadback = buildActionReadback(toolName, input.toolInput || {});
|
|
1196
|
+
const enrichment = buildEnrichment(toolName, input.toolInput || {});
|
|
1197
|
+
const inflightRec = state.inflightTools.get(requestId);
|
|
1198
|
+
if (inflightRec) inflightRec.enrichment = enrichment;
|
|
778
1199
|
const swarm = {
|
|
779
1200
|
...state.swarmContext,
|
|
780
1201
|
...input.agentId && { agent_id: input.agentId },
|
|
@@ -1194,6 +1615,8 @@ function emitDecisionLog(state, entry) {
|
|
|
1194
1615
|
...entry.sandbox_state && { sandbox_state: entry.sandbox_state },
|
|
1195
1616
|
...entry.plan_receipt_id && { plan_receipt_id: entry.plan_receipt_id }
|
|
1196
1617
|
};
|
|
1618
|
+
const enr = state.inflightTools.get(log.request_id)?.enrichment;
|
|
1619
|
+
if (enr) log.enrichment = enr;
|
|
1197
1620
|
process.stderr.write(`[PROTECT_MCP] ${JSON.stringify(log)}
|
|
1198
1621
|
`);
|
|
1199
1622
|
try {
|
|
@@ -1615,3 +2038,8 @@ function normalizeHookInput(raw) {
|
|
|
1615
2038
|
*
|
|
1616
2039
|
* @license MIT
|
|
1617
2040
|
*/
|
|
2041
|
+
/*! Bundled license information:
|
|
2042
|
+
|
|
2043
|
+
@noble/hashes/esm/utils.js:
|
|
2044
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
2045
|
+
*/
|
package/dist/hook-server.mjs
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startHookServer
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-744JMCY4.mjs";
|
|
4
|
+
import "./chunk-KMNXHGGT.mjs";
|
|
5
|
+
import "./chunk-AYNQIEN7.mjs";
|
|
6
|
+
import "./chunk-IDUH2O4Q.mjs";
|
|
7
|
+
import "./chunk-JIDDQUSQ.mjs";
|
|
8
|
+
import "./chunk-D733KAPG.mjs";
|
|
5
9
|
import "./chunk-PQJP2ZCI.mjs";
|
|
6
10
|
export {
|
|
7
11
|
startHookServer
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,20 @@ export { BUILTIN_PATTERNS, HookPattern, generateHookSettings, generateSampleCeda
|
|
|
3
3
|
export { createSandboxServer } from './demo-server.mjs';
|
|
4
4
|
import 'node:http';
|
|
5
5
|
|
|
6
|
+
interface ReceiptEnrichment {
|
|
7
|
+
/** Rule/schema version, so derivations stay reproducible as rules evolve. */
|
|
8
|
+
v: number;
|
|
9
|
+
/** SHA-256 (hex) of the canonical tool input. */
|
|
10
|
+
input_digest: string;
|
|
11
|
+
/** Sorted, deterministic capability tags (heuristic organisation labels). */
|
|
12
|
+
capabilities: string[];
|
|
13
|
+
/** Hashed coarse resource for clustering, when one is derivable. */
|
|
14
|
+
resource?: {
|
|
15
|
+
kind: 'path' | 'host' | 'command';
|
|
16
|
+
digest: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
interface ProtectPolicy {
|
|
7
21
|
tools: Record<string, ToolPolicy>;
|
|
8
22
|
/** Default trust tier for unidentified agents (default: "unknown") */
|
|
@@ -188,6 +202,8 @@ interface DecisionLog {
|
|
|
188
202
|
sandbox_state?: 'enabled' | 'disabled' | 'unavailable';
|
|
189
203
|
/** Plan receipt reference — links tool calls back to the approved plan */
|
|
190
204
|
plan_receipt_id?: string;
|
|
205
|
+
/** Deterministic enrichment (input digest, capability tags, hashed resource) */
|
|
206
|
+
enrichment?: ReceiptEnrichment;
|
|
191
207
|
/** Hook event that triggered this log entry */
|
|
192
208
|
hook_event?: HookEventName;
|
|
193
209
|
/** Redacted exact-action readback shown to humans before approving */
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,20 @@ export { BUILTIN_PATTERNS, HookPattern, generateHookSettings, generateSampleCeda
|
|
|
3
3
|
export { createSandboxServer } from './demo-server.js';
|
|
4
4
|
import 'node:http';
|
|
5
5
|
|
|
6
|
+
interface ReceiptEnrichment {
|
|
7
|
+
/** Rule/schema version, so derivations stay reproducible as rules evolve. */
|
|
8
|
+
v: number;
|
|
9
|
+
/** SHA-256 (hex) of the canonical tool input. */
|
|
10
|
+
input_digest: string;
|
|
11
|
+
/** Sorted, deterministic capability tags (heuristic organisation labels). */
|
|
12
|
+
capabilities: string[];
|
|
13
|
+
/** Hashed coarse resource for clustering, when one is derivable. */
|
|
14
|
+
resource?: {
|
|
15
|
+
kind: 'path' | 'host' | 'command';
|
|
16
|
+
digest: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
interface ProtectPolicy {
|
|
7
21
|
tools: Record<string, ToolPolicy>;
|
|
8
22
|
/** Default trust tier for unidentified agents (default: "unknown") */
|
|
@@ -188,6 +202,8 @@ interface DecisionLog {
|
|
|
188
202
|
sandbox_state?: 'enabled' | 'disabled' | 'unavailable';
|
|
189
203
|
/** Plan receipt reference — links tool calls back to the approved plan */
|
|
190
204
|
plan_receipt_id?: string;
|
|
205
|
+
/** Deterministic enrichment (input digest, capability tags, hashed resource) */
|
|
206
|
+
enrichment?: ReceiptEnrichment;
|
|
191
207
|
/** Hook event that triggered this log entry */
|
|
192
208
|
hook_event?: HookEventName;
|
|
193
209
|
/** Redacted exact-action readback shown to humans before approving */
|