@node9/proxy 2.13.1 → 2.14.1
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/dist/cli.js +830 -33
- package/dist/cli.mjs +830 -33
- package/dist/dashboard.mjs +814 -31
- package/dist/index.js +787 -28
- package/dist/index.mjs +787 -28
- package/dist/scan-ink.mjs +372 -1
- package/package.json +1 -1
package/dist/scan-ink.mjs
CHANGED
|
@@ -812,12 +812,383 @@ var FS_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
812
812
|
"nl",
|
|
813
813
|
"dd"
|
|
814
814
|
]);
|
|
815
|
+
var GREP_SHAPE = {
|
|
816
|
+
takesValue: /* @__PURE__ */ new Set([
|
|
817
|
+
"-A",
|
|
818
|
+
"-B",
|
|
819
|
+
"-C",
|
|
820
|
+
"-D",
|
|
821
|
+
"-d",
|
|
822
|
+
"-e",
|
|
823
|
+
"-f",
|
|
824
|
+
"-m",
|
|
825
|
+
"--after-context",
|
|
826
|
+
"--before-context",
|
|
827
|
+
"--binary-files",
|
|
828
|
+
"--context",
|
|
829
|
+
"--devices",
|
|
830
|
+
"--directories",
|
|
831
|
+
"--exclude",
|
|
832
|
+
"--exclude-dir",
|
|
833
|
+
"--exclude-from",
|
|
834
|
+
"--file",
|
|
835
|
+
"--include",
|
|
836
|
+
"--label",
|
|
837
|
+
"--max-count",
|
|
838
|
+
"--regexp"
|
|
839
|
+
]),
|
|
840
|
+
noValue: /* @__PURE__ */ new Set([
|
|
841
|
+
"-E",
|
|
842
|
+
"-F",
|
|
843
|
+
"-G",
|
|
844
|
+
"-P",
|
|
845
|
+
"-i",
|
|
846
|
+
"-y",
|
|
847
|
+
"-v",
|
|
848
|
+
"-V",
|
|
849
|
+
"-w",
|
|
850
|
+
"-x",
|
|
851
|
+
"-c",
|
|
852
|
+
"-l",
|
|
853
|
+
"-L",
|
|
854
|
+
"-o",
|
|
855
|
+
"-q",
|
|
856
|
+
"-s",
|
|
857
|
+
"-b",
|
|
858
|
+
"-H",
|
|
859
|
+
"-h",
|
|
860
|
+
"-n",
|
|
861
|
+
"-T",
|
|
862
|
+
"-Z",
|
|
863
|
+
"-z",
|
|
864
|
+
"-R",
|
|
865
|
+
"-r",
|
|
866
|
+
"-U",
|
|
867
|
+
"-u",
|
|
868
|
+
"-I",
|
|
869
|
+
"-a",
|
|
870
|
+
"--basic-regexp",
|
|
871
|
+
"--binary",
|
|
872
|
+
"--byte-offset",
|
|
873
|
+
"--color",
|
|
874
|
+
"--colour",
|
|
875
|
+
"--count",
|
|
876
|
+
"--dereference-recursive",
|
|
877
|
+
"--extended-regexp",
|
|
878
|
+
"--files-with-matches",
|
|
879
|
+
"--files-without-match",
|
|
880
|
+
"--fixed-strings",
|
|
881
|
+
"--help",
|
|
882
|
+
"--ignore-case",
|
|
883
|
+
"--initial-tab",
|
|
884
|
+
"--invert-match",
|
|
885
|
+
"--line-buffered",
|
|
886
|
+
"--line-number",
|
|
887
|
+
"--line-regexp",
|
|
888
|
+
"--no-filename",
|
|
889
|
+
"--no-group-separator",
|
|
890
|
+
"--no-ignore-case",
|
|
891
|
+
"--no-messages",
|
|
892
|
+
"--null",
|
|
893
|
+
"--null-data",
|
|
894
|
+
"--only-matching",
|
|
895
|
+
"--perl-regexp",
|
|
896
|
+
"--quiet",
|
|
897
|
+
"--recursive",
|
|
898
|
+
"--silent",
|
|
899
|
+
"--text",
|
|
900
|
+
"--version",
|
|
901
|
+
"--with-filename",
|
|
902
|
+
"--word-regexp"
|
|
903
|
+
]),
|
|
904
|
+
patternFlags: /* @__PURE__ */ new Set(["-e", "--regexp"]),
|
|
905
|
+
noPatternFlags: /* @__PURE__ */ new Set(["-f", "--file"])
|
|
906
|
+
};
|
|
907
|
+
var PATTERN_VERBS = {
|
|
908
|
+
grep: GREP_SHAPE,
|
|
909
|
+
// /usr/bin/egrep and /usr/bin/fgrep are 41-byte shell wrappers that exec
|
|
910
|
+
// `grep -E` and `grep -F`. Read in full, not assumed.
|
|
911
|
+
egrep: GREP_SHAPE,
|
|
912
|
+
fgrep: GREP_SHAPE,
|
|
913
|
+
// ripgrep 14.1.1, complete from its own --help. An earlier comment here said rg
|
|
914
|
+
// was not installed on the measuring machine; it is, and that stale claim is why
|
|
915
|
+
// this table shipped incomplete for two rounds, blocking ordinary searches like
|
|
916
|
+
// `rg --sort-files .env src` (/code-review round 4).
|
|
917
|
+
rg: {
|
|
918
|
+
takesValue: /* @__PURE__ */ new Set([
|
|
919
|
+
"-A",
|
|
920
|
+
"-B",
|
|
921
|
+
"-C",
|
|
922
|
+
"-d",
|
|
923
|
+
"-E",
|
|
924
|
+
"-e",
|
|
925
|
+
"-f",
|
|
926
|
+
"-g",
|
|
927
|
+
"-j",
|
|
928
|
+
"-M",
|
|
929
|
+
"-m",
|
|
930
|
+
"-r",
|
|
931
|
+
"-t",
|
|
932
|
+
"-T",
|
|
933
|
+
"--after-context",
|
|
934
|
+
"--before-context",
|
|
935
|
+
"--color",
|
|
936
|
+
"--colors",
|
|
937
|
+
"--context",
|
|
938
|
+
"--context-separator",
|
|
939
|
+
"--dfa-size-limit",
|
|
940
|
+
"--encoding",
|
|
941
|
+
"--engine",
|
|
942
|
+
"--field-context-separator",
|
|
943
|
+
"--field-match-separator",
|
|
944
|
+
"--file",
|
|
945
|
+
"--generate",
|
|
946
|
+
"--glob",
|
|
947
|
+
"--hostname-bin",
|
|
948
|
+
"--hyperlink-format",
|
|
949
|
+
"--iglob",
|
|
950
|
+
"--ignore-file",
|
|
951
|
+
"--max-columns",
|
|
952
|
+
"--max-count",
|
|
953
|
+
"--max-depth",
|
|
954
|
+
// An ALIAS of --max-depth, and it takes a value. The round-5 extraction read
|
|
955
|
+
// alias lines as plain switches and swept it into noValue, which hard-blocked
|
|
956
|
+
// `rg --maxdepth 2 .env src` while `--max-depth 2` ran (/code-review round 7).
|
|
957
|
+
"--maxdepth",
|
|
958
|
+
"--max-filesize",
|
|
959
|
+
"--path-separator",
|
|
960
|
+
"--pre",
|
|
961
|
+
"--pre-glob",
|
|
962
|
+
"--regexp",
|
|
963
|
+
"--regex-size-limit",
|
|
964
|
+
"--replace",
|
|
965
|
+
"--sort",
|
|
966
|
+
"--sortr",
|
|
967
|
+
"--threads",
|
|
968
|
+
"--type",
|
|
969
|
+
"--type-add",
|
|
970
|
+
"--type-clear",
|
|
971
|
+
"--type-not"
|
|
972
|
+
]),
|
|
973
|
+
noValue: /* @__PURE__ */ new Set([
|
|
974
|
+
"-.",
|
|
975
|
+
"-0",
|
|
976
|
+
"-a",
|
|
977
|
+
"-b",
|
|
978
|
+
"-c",
|
|
979
|
+
"-F",
|
|
980
|
+
"-h",
|
|
981
|
+
"-H",
|
|
982
|
+
"-i",
|
|
983
|
+
"-I",
|
|
984
|
+
"-l",
|
|
985
|
+
"-L",
|
|
986
|
+
"-n",
|
|
987
|
+
"-N",
|
|
988
|
+
"-o",
|
|
989
|
+
"-p",
|
|
990
|
+
"-P",
|
|
991
|
+
"-q",
|
|
992
|
+
"-s",
|
|
993
|
+
"-S",
|
|
994
|
+
"-u",
|
|
995
|
+
"-U",
|
|
996
|
+
"-v",
|
|
997
|
+
"-V",
|
|
998
|
+
"-w",
|
|
999
|
+
"-x",
|
|
1000
|
+
"-z",
|
|
1001
|
+
"--auto-hybrid-regex",
|
|
1002
|
+
"--binary",
|
|
1003
|
+
"--block-buffered",
|
|
1004
|
+
"--byte-offset",
|
|
1005
|
+
"--case-sensitive",
|
|
1006
|
+
"--column",
|
|
1007
|
+
"--count",
|
|
1008
|
+
"--count-matches",
|
|
1009
|
+
"--crlf",
|
|
1010
|
+
"--debug",
|
|
1011
|
+
"--files",
|
|
1012
|
+
"--files-with-matches",
|
|
1013
|
+
"--files-without-match",
|
|
1014
|
+
"--fixed-strings",
|
|
1015
|
+
"--follow",
|
|
1016
|
+
"--glob-case-insensitive",
|
|
1017
|
+
"--heading",
|
|
1018
|
+
"--help",
|
|
1019
|
+
"--hidden",
|
|
1020
|
+
"--ignore-case",
|
|
1021
|
+
"--ignore-file-case-insensitive",
|
|
1022
|
+
"--include-zero",
|
|
1023
|
+
"--invert-match",
|
|
1024
|
+
"--json",
|
|
1025
|
+
"--line-buffered",
|
|
1026
|
+
"--line-number",
|
|
1027
|
+
"--line-regexp",
|
|
1028
|
+
"--max-columns-preview",
|
|
1029
|
+
"--mmap",
|
|
1030
|
+
"--multiline",
|
|
1031
|
+
"--multiline-dotall",
|
|
1032
|
+
"--no-column",
|
|
1033
|
+
"--no-config",
|
|
1034
|
+
"--no-context-separator",
|
|
1035
|
+
"--no-encoding",
|
|
1036
|
+
"--no-filename",
|
|
1037
|
+
"--no-ignore",
|
|
1038
|
+
"--no-ignore-dot",
|
|
1039
|
+
"--no-ignore-exclude",
|
|
1040
|
+
"--no-ignore-files",
|
|
1041
|
+
"--no-ignore-global",
|
|
1042
|
+
"--no-ignore-messages",
|
|
1043
|
+
"--no-ignore-parent",
|
|
1044
|
+
"--no-ignore-vcs",
|
|
1045
|
+
"--no-line-number",
|
|
1046
|
+
"--no-messages",
|
|
1047
|
+
"--no-pcre2-unicode",
|
|
1048
|
+
"--no-pre",
|
|
1049
|
+
"--no-require-git",
|
|
1050
|
+
"--no-unicode",
|
|
1051
|
+
"--null",
|
|
1052
|
+
"--null-data",
|
|
1053
|
+
"--one-file-system",
|
|
1054
|
+
"--only-matching",
|
|
1055
|
+
"--passthru",
|
|
1056
|
+
"--pcre2",
|
|
1057
|
+
"--pcre2-version",
|
|
1058
|
+
"--pretty",
|
|
1059
|
+
"--print0",
|
|
1060
|
+
"--quiet",
|
|
1061
|
+
"--search-zip",
|
|
1062
|
+
"--smart-case",
|
|
1063
|
+
"--sort-files",
|
|
1064
|
+
"--stats",
|
|
1065
|
+
"--stop-on-nonmatch",
|
|
1066
|
+
"--text",
|
|
1067
|
+
"--trace",
|
|
1068
|
+
"--trim",
|
|
1069
|
+
"--type-list",
|
|
1070
|
+
"--unrestricted",
|
|
1071
|
+
"--version",
|
|
1072
|
+
"--vimgrep",
|
|
1073
|
+
"--with-filename",
|
|
1074
|
+
"--word-regexp",
|
|
1075
|
+
// The COMPLETE remainder of `rg --help`, added after /code-review round 5
|
|
1076
|
+
// found 40 documented switches in neither set. The table is now the whole
|
|
1077
|
+
// option list: `rg --help` yields 149 long options, 35 of them value-taking.
|
|
1078
|
+
"--ignore",
|
|
1079
|
+
"--ignore-dot",
|
|
1080
|
+
"--ignore-exclude",
|
|
1081
|
+
"--ignore-files",
|
|
1082
|
+
"--ignore-global",
|
|
1083
|
+
"--ignore-messages",
|
|
1084
|
+
"--ignore-parent",
|
|
1085
|
+
"--ignore-vcs",
|
|
1086
|
+
"--messages",
|
|
1087
|
+
"--no-auto-hybrid-regex",
|
|
1088
|
+
"--no-binary",
|
|
1089
|
+
"--no-block-buffered",
|
|
1090
|
+
"--no-byte-offset",
|
|
1091
|
+
"--no-crlf",
|
|
1092
|
+
"--no-fixed-strings",
|
|
1093
|
+
"--no-follow",
|
|
1094
|
+
"--no-glob-case-insensitive",
|
|
1095
|
+
"--no-heading",
|
|
1096
|
+
"--no-hidden",
|
|
1097
|
+
"--no-ignore-file-case-insensitive",
|
|
1098
|
+
"--no-include-zero",
|
|
1099
|
+
"--no-invert-match",
|
|
1100
|
+
"--no-json",
|
|
1101
|
+
"--no-line-buffered",
|
|
1102
|
+
"--no-max-columns-preview",
|
|
1103
|
+
"--no-mmap",
|
|
1104
|
+
"--no-multiline",
|
|
1105
|
+
"--no-multiline-dotall",
|
|
1106
|
+
"--no-one-file-system",
|
|
1107
|
+
"--no-pcre2",
|
|
1108
|
+
"--no-search-zip",
|
|
1109
|
+
"--no-sort-files",
|
|
1110
|
+
"--no-stats",
|
|
1111
|
+
"--no-text",
|
|
1112
|
+
"--no-trim",
|
|
1113
|
+
"--passthrough",
|
|
1114
|
+
"--pcre2-unicode",
|
|
1115
|
+
"--require-git",
|
|
1116
|
+
"--unicode"
|
|
1117
|
+
]),
|
|
1118
|
+
patternFlags: /* @__PURE__ */ new Set(["-e", "--regexp"]),
|
|
1119
|
+
// `--files` and `--type-list` list or enumerate without a pattern. Founder
|
|
1120
|
+
// decision 2026-09-13: `rg --files ~/.ssh` stays BLOCKED, which this achieves
|
|
1121
|
+
// by leaving the directory in the judged list.
|
|
1122
|
+
noPatternFlags: /* @__PURE__ */ new Set(["-f", "--file", "--files", "--type-list", "--pcre2-version"])
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
var PATTERN_VERB_NAMES = Object.keys(PATTERN_VERBS);
|
|
1126
|
+
var SCP_VALUE_FLAGS = ["i", "F", "o", "c", "S", "P", "J", "D", "W", "l"];
|
|
1127
|
+
var TAR_VALUE_LETTERS = ["b", "C", "f", "F", "g", "H", "I", "K", "L", "N", "T", "V", "X"];
|
|
1128
|
+
var ZIP_VALUE_LETTERS = ["b", "n", "P", "t", "s", "O", "x", "i"];
|
|
1129
|
+
var RSYNC_VALUE_LETTERS = ["e", "f", "T", "B", "M"];
|
|
1130
|
+
var RSYNC_SKIP = [
|
|
1131
|
+
"e",
|
|
1132
|
+
"--rsh",
|
|
1133
|
+
"--exclude",
|
|
1134
|
+
"--exclude-from",
|
|
1135
|
+
"--include",
|
|
1136
|
+
"--include-from",
|
|
1137
|
+
"--files-from",
|
|
1138
|
+
"f",
|
|
1139
|
+
"--filter"
|
|
1140
|
+
];
|
|
1141
|
+
var CP_VALUE_LETTERS = ["S", "t"];
|
|
1142
|
+
var INSTALL_VALUE_LETTERS = ["S", "t", "g", "m", "o"];
|
|
1143
|
+
var COPY_VERBS = {
|
|
1144
|
+
cp: { source: "allButLast", targetDirFlag: true, valueLetters: CP_VALUE_LETTERS },
|
|
1145
|
+
mv: { source: "allButLast", targetDirFlag: true, valueLetters: CP_VALUE_LETTERS },
|
|
1146
|
+
install: { source: "allButLast", targetDirFlag: true, valueLetters: INSTALL_VALUE_LETTERS },
|
|
1147
|
+
ln: { source: "first", targetDirFlag: true, valueLetters: CP_VALUE_LETTERS },
|
|
1148
|
+
scp: { source: "allButLast", skipFlags: SCP_VALUE_FLAGS, valueLetters: SCP_VALUE_FLAGS },
|
|
1149
|
+
rsync: { source: "allButLast", skipFlags: RSYNC_SKIP, valueLetters: RSYNC_VALUE_LETTERS },
|
|
1150
|
+
tar: {
|
|
1151
|
+
source: "archive",
|
|
1152
|
+
archive: "tar",
|
|
1153
|
+
skipFlags: ["f", "X", "T", "--file", "--exclude", "--exclude-from", "--files-from"],
|
|
1154
|
+
valueLetters: TAR_VALUE_LETTERS
|
|
1155
|
+
},
|
|
1156
|
+
zip: {
|
|
1157
|
+
source: "archive",
|
|
1158
|
+
archive: "zip",
|
|
1159
|
+
skipFlags: ["x", "i", "--exclude", "--include"],
|
|
1160
|
+
valueLetters: ZIP_VALUE_LETTERS
|
|
1161
|
+
},
|
|
1162
|
+
ar: { source: "archive", archive: "ar" },
|
|
1163
|
+
// 7z switches are INLINE only (`-mx9`, `-px`, `-x!pat`), so no following word is
|
|
1164
|
+
// ever a switch's operand -- which is why the short `x` is NOT a skipFlag here
|
|
1165
|
+
// and valueLetters is empty. Keeping the short `x` made `7z a out.7z -mx KEY`
|
|
1166
|
+
// drop the credential as an exclusion operand (/code-review round 8), and the
|
|
1167
|
+
// derived "every skipped letter is a value letter" row in jail-copy.spec.ts is
|
|
1168
|
+
// what keeps the two tables honest about it.
|
|
1169
|
+
"7z": { source: "archive", archive: "7z", skipFlags: ["--exclude"], valueLetters: [] },
|
|
1170
|
+
gzip: { source: "all" },
|
|
1171
|
+
bzip2: { source: "all" },
|
|
1172
|
+
xz: { source: "all" },
|
|
1173
|
+
"docker cp": { source: "allButLast" },
|
|
1174
|
+
"kubectl cp": { source: "allButLast" },
|
|
1175
|
+
"gsutil cp": { source: "allButLast" },
|
|
1176
|
+
"gsutil rsync": { source: "allButLast" },
|
|
1177
|
+
"rclone copy": { source: "allButLast" },
|
|
1178
|
+
"rclone sync": { source: "allButLast" },
|
|
1179
|
+
"aws s3 cp": { source: "allButLast" },
|
|
1180
|
+
"aws s3 mv": { source: "allButLast" },
|
|
1181
|
+
"aws s3 sync": { source: "allButLast" },
|
|
1182
|
+
"gcloud storage cp": { source: "allButLast" },
|
|
1183
|
+
"az storage blob upload": { source: "flagOperand", sourceFlags: ["f", "--file"] }
|
|
1184
|
+
};
|
|
1185
|
+
var COPY_VERB_HEADS = new Set(Object.keys(COPY_VERBS).map((k) => k.split(" ")[0]));
|
|
815
1186
|
var FS_OP_PRESCREEN_RE = new RegExp(
|
|
816
1187
|
// A quote is a separator too: `eval "cat X"` and `sh -c 'cat X'` put the
|
|
817
1188
|
// reader right after `"` / `'`, and without these two characters the
|
|
818
1189
|
// prescreen rejected every string-wrapped read before the parser ran.
|
|
819
1190
|
// Found 2026-09-11 by instrumenting the walk -- no CallExpr was ever visited.
|
|
820
|
-
`(?:^|[\\s|;&("'\`\\n])(?:rm|${[...FS_READ_TOOLS].map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\b|(?<!<)<(?!<)`
|
|
1191
|
+
`(?:^|[\\s|;&("'\`\\n/])(?:rm|${[...FS_READ_TOOLS, ...COPY_VERB_HEADS].map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\b|(?<!<)<(?!<)`
|
|
821
1192
|
);
|
|
822
1193
|
function deriveRedirOp(sample) {
|
|
823
1194
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.1",
|
|
4
4
|
"description": "The Sudo Command for AI Agents. Execution Security for Claude Code, Codex, Gemini, Cursor, Opencode, Pi, and any MCP server.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|