helm-env-delta 1.15.0 ā 1.15.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/README.md
CHANGED
|
@@ -66,7 +66,7 @@ HelmEnvDelta (`hed`) automates environment synchronization for GitOps workflows
|
|
|
66
66
|
|
|
67
67
|
ā” **High Performance** - Intelligent caching and parallel processing. Formatting rules, compiled regexes, and array normalization are all cached for fast repeated runs.
|
|
68
68
|
|
|
69
|
-
š **Security Hardened** - Regex inputs (stop rules, transforms, pattern files) are validated against ReDoS (catastrophic backtracking). Fixed values are
|
|
69
|
+
š **Security Hardened** - Regex inputs (stop rules, transforms, pattern files) are validated against ReDoS (catastrophic backtracking) ā covers nested quantifiers, optional groups, and alternation patterns. Fixed values and YAML file content are guarded against prototype pollution. HTML report paths are HTML-escaped to prevent XSS from filename transforms.
|
|
70
70
|
|
|
71
71
|
š **Auto Updates** - Notifies when newer versions are available (skips in CI/CD).
|
|
72
72
|
|
|
@@ -428,7 +428,7 @@ requiredVersion: '1.10.0' # Optional: Minimum tool version required to process t
|
|
|
428
428
|
|
|
429
429
|
**Note:** Source and destination paths cannot resolve to the same folder.
|
|
430
430
|
|
|
431
|
-
**`requiredVersion`:** When set, the CLI checks that the installed version of helm-env-delta meets this minimum. If the installed version is older, the CLI exits immediately with a clear upgrade message. This prevents running configs that depend on newer features with an outdated tool version. Supports `"1.2.3"` or `"v1.2.3"` format.
|
|
431
|
+
**`requiredVersion`:** When set, the CLI checks that the installed version of helm-env-delta meets this minimum. If the installed version is older, the CLI exits immediately with a clear upgrade message. This prevents running configs that depend on newer features with an outdated tool version. Supports `"1.2.3"` or `"v1.2.3"` format. Setting `requiredVersion` also suppresses the auto-update notification ā a pinned version requirement signals intentional version targeting.
|
|
432
432
|
|
|
433
433
|
---
|
|
434
434
|
|
|
@@ -680,7 +680,7 @@ stopRules:
|
|
|
680
680
|
|
|
681
681
|
**Override:** Use `--force` to bypass stop rules when needed.
|
|
682
682
|
|
|
683
|
-
**Regex safety:** All `regex` patterns (inline and from files) are validated against catastrophic backtracking (ReDoS).
|
|
683
|
+
**Regex safety:** All `regex` patterns (inline and from files) are validated against catastrophic backtracking (ReDoS). Rejected patterns include: nested quantifiers on groups (e.g., `(a+)+`), optional groups with inner quantifiers (e.g., `(a+)?`), and alternation groups with outer repetition (e.g., `(a|ab)*`).
|
|
684
684
|
|
|
685
685
|
**Visibility:** Stop rule violations appear in console output, JSON reports, and HTML reports (dry-run mode only, as a collapsible table in the header area).
|
|
686
686
|
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,8 @@ const main = async () => {
|
|
|
78
78
|
(0, node_fs_1.writeFileSync)(firstRunMarker, new Date().toISOString());
|
|
79
79
|
}
|
|
80
80
|
const config = (0, config_1.loadConfigFile)(command.config, command.quiet, logger, { formatOnly: command.formatOnly });
|
|
81
|
+
if (config.requiredVersion)
|
|
82
|
+
configHasRequiredVersion = true;
|
|
81
83
|
if (command.showConfig) {
|
|
82
84
|
console.log(chalk_1.default.cyan('\nāļø Resolved Configuration:\n'));
|
|
83
85
|
console.log(YAML.stringify(config, { indent: 2 }));
|
|
@@ -354,6 +356,7 @@ const main = async () => {
|
|
|
354
356
|
if (command.diffJson)
|
|
355
357
|
(0, reporters_1.generateJsonReport)(diffResult, formattedFiles, validationResult, syncConfig, command.dryRun, package_json_1.default.version);
|
|
356
358
|
};
|
|
359
|
+
let configHasRequiredVersion = false;
|
|
357
360
|
(async () => {
|
|
358
361
|
try {
|
|
359
362
|
await main();
|
|
@@ -393,7 +396,7 @@ const main = async () => {
|
|
|
393
396
|
}
|
|
394
397
|
finally {
|
|
395
398
|
const command = (0, commandLine_1.parseCommandLine)();
|
|
396
|
-
if (!command.quiet)
|
|
399
|
+
if (!command.quiet && !configHasRequiredVersion)
|
|
397
400
|
void (0, versionChecker_1.checkForUpdates)(package_json_1.default.version);
|
|
398
401
|
}
|
|
399
402
|
})();
|
|
@@ -115,8 +115,9 @@ const deepMerge = (fullTarget, filteredSource, filteredTarget, currentPath = [],
|
|
|
115
115
|
const fullTargetObject = fullTarget;
|
|
116
116
|
const filteredTargetObject = filteredTarget || {};
|
|
117
117
|
const result = { ...sourceObject };
|
|
118
|
+
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
118
119
|
for (const [key, value] of Object.entries(fullTargetObject))
|
|
119
|
-
if (!(key in filteredTargetObject) && !(key in sourceObject))
|
|
120
|
+
if (!DANGEROUS_KEYS.has(key) && !(key in filteredTargetObject) && !(key in sourceObject))
|
|
120
121
|
result[key] = value;
|
|
121
122
|
for (const [key, value] of Object.entries(sourceObject))
|
|
122
123
|
if (key in fullTargetObject)
|
|
@@ -51,13 +51,13 @@ const countDiffLines = (unifiedDiff) => {
|
|
|
51
51
|
};
|
|
52
52
|
const generateFileSummary = (file) => {
|
|
53
53
|
if (!file.originalPath)
|
|
54
|
-
return file.path;
|
|
55
|
-
return `<span class="filename-transform">${file.originalPath} ā ${file.path}</span>`;
|
|
54
|
+
return (0, treeRenderer_1.escapeHtml)(file.path);
|
|
55
|
+
return `<span class="filename-transform">${(0, treeRenderer_1.escapeHtml)(file.originalPath)} ā ${(0, treeRenderer_1.escapeHtml)(file.path)}</span>`;
|
|
56
56
|
};
|
|
57
57
|
const generateAddedFileSummary = (file) => {
|
|
58
58
|
if (!file.originalPath)
|
|
59
|
-
return file.path;
|
|
60
|
-
return `<span class="filename-transform">${file.originalPath} ā ${file.path}</span>`;
|
|
59
|
+
return (0, treeRenderer_1.escapeHtml)(file.path);
|
|
60
|
+
return `<span class="filename-transform">${(0, treeRenderer_1.escapeHtml)(file.originalPath)} ā ${(0, treeRenderer_1.escapeHtml)(file.path)}</span>`;
|
|
61
61
|
};
|
|
62
62
|
const JUMP_TO_SIDEBAR_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M2 2h3v12H2V2zm0-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H2zm5 4h7v1H7V5zm0 3h7v1H7V8zm0 3h5v1H7v-1z"/></svg>`;
|
|
63
63
|
const generateAddedFileSection = (file, fileId, open) => {
|
package/dist/suggestionEngine.js
CHANGED
|
@@ -548,9 +548,9 @@ const calculateLevenshteinDistance = (string1, string2) => {
|
|
|
548
548
|
matrix[0][col] = col;
|
|
549
549
|
for (let row = 1; row <= string2.length; row++)
|
|
550
550
|
for (let col = 1; col <= string1.length; col++)
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
551
|
+
matrix[row][col] =
|
|
552
|
+
string2.charAt(row - 1) === string1.charAt(col - 1)
|
|
553
|
+
? matrix[row - 1][col - 1]
|
|
554
|
+
: Math.min(matrix[row - 1][col - 1] + 1, matrix[row][col - 1] + 1, matrix[row - 1][col] + 1);
|
|
555
555
|
return matrix[string2.length][string1.length];
|
|
556
556
|
};
|
package/dist/utils/gitFilter.js
CHANGED
|
@@ -63,7 +63,7 @@ const getGitModifiedPaths = async (git, author, days, absoluteSourceDirectory) =
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
const filterFileMapsByGitAuthor = async (sourceFiles, destinationFiles, absoluteSourceDirectory, author, days) => {
|
|
66
|
-
const git = (0, simple_git_1.default)();
|
|
66
|
+
const git = (0, simple_git_1.default)(absoluteSourceDirectory);
|
|
67
67
|
const gitRoot = await getGitRoot(git);
|
|
68
68
|
const gitModifiedPaths = await getGitModifiedPaths(git, author, days, absoluteSourceDirectory);
|
|
69
69
|
const matchingKeys = new Set();
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isSafeRegex = void 0;
|
|
4
4
|
const isSafeRegex = (pattern) => {
|
|
5
|
-
if (/\([^()]*[*+][^()]*\)[
|
|
5
|
+
if (/\([^()]*[*+][^()]*\)[*+?{]/.test(pattern))
|
|
6
|
+
return false;
|
|
7
|
+
if (/\([^()]*\|[^()]*\)[*+{]/.test(pattern))
|
|
6
8
|
return false;
|
|
7
9
|
return true;
|
|
8
10
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helm-env-delta",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.2",
|
|
4
4
|
"description": "HelmEnvDelta ā environment-aware YAML delta and sync for GitOps",
|
|
5
5
|
"author": "BCsabaEngine",
|
|
6
6
|
"license": "ISC",
|
|
@@ -67,27 +67,27 @@
|
|
|
67
67
|
"@eslint/js": "^10.0.1",
|
|
68
68
|
"@types/node": "^25.5.0",
|
|
69
69
|
"@types/picomatch": "^4.0.2",
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "^8.57.
|
|
71
|
-
"@vitest/coverage-v8": "^4.1.
|
|
72
|
-
"eslint": "^10.0
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
|
71
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
72
|
+
"eslint": "^10.1.0",
|
|
73
73
|
"eslint-config-prettier": "^10.1.8",
|
|
74
74
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
75
|
-
"eslint-plugin-unicorn": "^
|
|
75
|
+
"eslint-plugin-unicorn": "^64.0.0",
|
|
76
76
|
"prettier": "^3.8.1",
|
|
77
77
|
"tsx": "^4.21.0",
|
|
78
78
|
"typescript": "^5.9.3",
|
|
79
|
-
"vitest": "^4.1.
|
|
79
|
+
"vitest": "^4.1.2"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"chalk": "^5.6.2",
|
|
83
83
|
"commander": "^14.0.3",
|
|
84
|
-
"diff": "^8.0.
|
|
84
|
+
"diff": "^8.0.4",
|
|
85
85
|
"diff2html": "3.4.56",
|
|
86
86
|
"open": "^11.0.0",
|
|
87
|
-
"picomatch": "^4.0.
|
|
87
|
+
"picomatch": "^4.0.4",
|
|
88
88
|
"simple-git": "^3.33.0",
|
|
89
89
|
"tinyglobby": "^0.2.15",
|
|
90
|
-
"yaml": "^2.8.
|
|
90
|
+
"yaml": "^2.8.3",
|
|
91
91
|
"zod": "^4.3.6"
|
|
92
92
|
}
|
|
93
93
|
}
|