@jurislm/coolify-plugin 4.0.28 → 4.0.29
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/.codex-plugin/plugin.json +1 -1
- package/dist/client.js +56 -3
- package/package.json +1 -1
- package/plugin.json +1 -1
package/dist/client.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isAlias, isScalar, parseDocument, stringify, visit } from "yaml";
|
|
|
2
2
|
import { CoolifyApiError, redactErrorText } from "./errors.js";
|
|
3
3
|
const sensitiveKey = /(^value$|real_?value|private_?key|api_?key|user_?key|webhook_?url|token|secret|password|authorization|cookie)/iu;
|
|
4
4
|
const composeKey = /^(docker_compose(_pr)?(_raw)?|configuration)$/u;
|
|
5
|
-
const composeSecretName = /(password|passwd|secret|token|private|credential|api_?key|access_?key|authorization|cookie)/iu;
|
|
5
|
+
const composeSecretName = /(password|passwd|secret|token|private|credential|api_?key|access_?key|root_?user|authorization|cookie)/iu;
|
|
6
6
|
const composeSecretSegment = /(^|[_.-])(key|pass|pwd|auth)($|[_.-])/iu;
|
|
7
7
|
const interpolation = /^\$\{?[A-Za-z_][A-Za-z0-9_]*\}?$/u;
|
|
8
8
|
const urlCredential = /([a-z][a-z0-9+.-]{0,31}:\/\/[^\s:/@]{0,256}):([^\s/?#]{1,256})@/giu;
|
|
@@ -26,12 +26,65 @@ function redactUrlCredentials(text) {
|
|
|
26
26
|
function isQuerySecret(name) {
|
|
27
27
|
return querySecretName.test(name) || name.toLowerCase().split(/[_.-]/u).some((segment) => querySecretSegments.has(segment));
|
|
28
28
|
}
|
|
29
|
+
const commandKey = /^(command|entrypoint|test)$/u;
|
|
30
|
+
const secretFlagName = /(requirepass|masterauth)/iu;
|
|
31
|
+
const portValue = /^[\d.:[\]]+(\/(tcp|udp|sctp))?$/iu;
|
|
32
|
+
const envOption = /(^|\s)(-e|--env)(=|\s+)(?:"([A-Za-z_][\w.]{0,127})=([^"\n]{0,4096})"|'([A-Za-z_][\w.]{0,127})=([^'\n]{0,4096})'|([A-Za-z_][\w.]{0,127})=("[^"\n]{0,4096}"|'[^'\n]{0,4096}'|[^\s"']*))/gu;
|
|
33
|
+
const flagEquals = /(^|\s)(--?[A-Za-z][\w-]{0,63})=("[^"\n]{0,4096}"|'[^'\n]{0,4096}'|[^\s"']+)/gu;
|
|
34
|
+
const flagSpace = /(^|\s)(--?[A-Za-z][\w-]{0,63})(\s+)("[^"\n]{0,4096}"|'[^'\n]{0,4096}'|[^\s"'-][^\s"']*)/gu;
|
|
35
|
+
function unquote(value) {
|
|
36
|
+
return value.replace(/^(["'])([\s\S]*)\1$/u, "$2");
|
|
37
|
+
}
|
|
38
|
+
function quoteOf(value) {
|
|
39
|
+
return value.startsWith("\"") || value.startsWith("'") ? value[0] : "";
|
|
40
|
+
}
|
|
41
|
+
function isSecretFlag(flag) {
|
|
42
|
+
if (flag === "-p")
|
|
43
|
+
return true;
|
|
44
|
+
if (!flag.startsWith("--"))
|
|
45
|
+
return false;
|
|
46
|
+
const name = flag.slice(2).replace(/-/gu, "_");
|
|
47
|
+
return composeSecretName.test(name) || composeSecretSegment.test(name) || secretFlagName.test(name);
|
|
48
|
+
}
|
|
49
|
+
function isSecretFlagValue(flag, value) {
|
|
50
|
+
const bare = unquote(value);
|
|
51
|
+
if (bare === "" || bare === "[REDACTED]" || interpolation.test(bare) || flagValue.test(bare))
|
|
52
|
+
return false;
|
|
53
|
+
return flag !== "-p" || !portValue.test(bare);
|
|
54
|
+
}
|
|
55
|
+
function redactCommandLine(text) {
|
|
56
|
+
return text
|
|
57
|
+
.replace(envOption, (match, lead, flag, separator, doubleKey, _doubleValue, singleKey, _singleValue, key, value) => {
|
|
58
|
+
if (doubleKey !== undefined)
|
|
59
|
+
return isComposeSecret(doubleKey, _doubleValue) ? `${lead}${flag}${separator}"${doubleKey}=[REDACTED]"` : match;
|
|
60
|
+
if (singleKey !== undefined)
|
|
61
|
+
return isComposeSecret(singleKey, _singleValue) ? `${lead}${flag}${separator}'${singleKey}=[REDACTED]'` : match;
|
|
62
|
+
if (key === undefined || value === undefined)
|
|
63
|
+
return match;
|
|
64
|
+
const quote = quoteOf(value);
|
|
65
|
+
return isComposeSecret(key, unquote(value)) ? `${lead}${flag}${separator}${key}=${quote}[REDACTED]${quote}` : match;
|
|
66
|
+
})
|
|
67
|
+
.replace(flagEquals, (match, lead, flag, value) => isSecretFlag(flag) && isSecretFlagValue(flag, value) ? `${lead}${flag}=${quoteOf(value)}[REDACTED]${quoteOf(value)}` : match)
|
|
68
|
+
.replace(flagSpace, (match, lead, flag, space, value) => isSecretFlag(flag) && isSecretFlagValue(flag, value) ? `${lead}${flag}${space}${quoteOf(value)}[REDACTED]${quoteOf(value)}` : match);
|
|
69
|
+
}
|
|
70
|
+
function redactCommand(value) {
|
|
71
|
+
if (typeof value === "string")
|
|
72
|
+
return redactCommandLine(value);
|
|
73
|
+
if (!Array.isArray(value))
|
|
74
|
+
return value;
|
|
75
|
+
return value.map((token, index) => {
|
|
76
|
+
if (typeof token !== "string")
|
|
77
|
+
return token;
|
|
78
|
+
const flag = value[index - 1];
|
|
79
|
+
return typeof flag === "string" && !flag.includes("=") && isSecretFlag(flag) && isSecretFlagValue(flag, token) ? "[REDACTED]" : redactCommandLine(token);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
29
82
|
const composeAliasLimit = 100;
|
|
30
83
|
function redactComposeValue(value) {
|
|
31
84
|
if (Array.isArray(value))
|
|
32
85
|
return value.map(redactComposeValue);
|
|
33
86
|
if (value && typeof value === "object") {
|
|
34
|
-
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, isComposeSecret(key, child) ? "[REDACTED]" : redactComposeValue(child)]));
|
|
87
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, isComposeSecret(key, child) ? "[REDACTED]" : redactComposeValue(commandKey.test(key) ? redactCommand(child) : child)]));
|
|
35
88
|
}
|
|
36
89
|
if (typeof value !== "string")
|
|
37
90
|
return value;
|
|
@@ -94,7 +147,7 @@ export function redactSensitive(value) {
|
|
|
94
147
|
const binary = value.encoding === "base64" && typeof value.contentType === "string" && typeof value.value === "string";
|
|
95
148
|
return Object.fromEntries(Object.entries(value).map(([key, child]) => [
|
|
96
149
|
key,
|
|
97
|
-
sensitiveKey.test(key) && !(binary && key === "value") ? "[REDACTED]" : composeKey.test(key) && typeof child === "string" ? redactComposeText(child) : redactSensitive(child),
|
|
150
|
+
sensitiveKey.test(key) && !(binary && key === "value") ? "[REDACTED]" : composeKey.test(key) && typeof child === "string" ? redactComposeText(child) : key === "custom_docker_run_options" && typeof child === "string" ? redactUrlCredentials(redactCommandLine(child)) : redactSensitive(child),
|
|
98
151
|
]));
|
|
99
152
|
}
|
|
100
153
|
function pathValue(value, name) {
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "coolify-plugin",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.29",
|
|
5
5
|
"description": "Portable Coolify MCP plugin with local stdio tools generated from the official OpenAPI contract.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "JurisLM",
|