fix: enforce path traversal protection for actions, rules, hooks, and databases - #1448
Open
ankita10119 wants to merge 3 commits into
Open
fix: enforce path traversal protection for actions, rules, hooks, and databases#1448ankita10119 wants to merge 3 commits into
ankita10119 wants to merge 3 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## beta/v9.0.0 #1448 +/- ##
==============================================
Coverage ? 80.19%
==============================================
Files ? 156
Lines ? 7250
Branches ? 1604
==============================================
Hits ? 5814
Misses ? 776
Partials ? 660 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔧 Changes
Background and motivation
This PR addresses two related problems:
1. Security vulnerability - path traversal
Resource configurations (
actions,rules,hooks,databases) reference external code files by path. A malicious or misconfigured path such as../../etc/sensitive-file.jscould cause the CLI to load a file from outside the intended config directory. This is a path traversal vulnerability reported by the security team.2. False errors on legitimate relative paths (issue #1432)
Users on
v8.xreported that the CLI was incorrectly emitting warnings/errors for valid relative paths such as./actions/action-one/code.js. Investigation revealed that theactionsandactionModuleshandlers were using a fragile regex to pre-process paths before passing them toloadFile(), and thatloadFile()itself had a silent fallback(
isFile(inSubfolder) ? inSubfolder : inRoot) that behaved unpredictably depending on whether the file existed at the expected location.These two problems share the same root cause: inconsistent and fragile path resolution logic across handlers.
Root cause
The
databases.tshandler already had the correct approach from a previous fix - it usedpath.resolve + startsWith(configRoot)directly in the handler, callingloadFileAndReplaceKeywordswithout going throughloadFile().However,
actions.tsandactionModules.tsused a different approach:This regex incorrectly stripped the ./ prefix, causing path resolution in
loadFile()to compute the wrong base path and trigger false errors.rules.tsandhooks.tspassed paths to loadFile() directly:rule.script = context.loadFile(rule.script, constants.RULES_DIRECTORY);These relied on
loadFile()'s isFile fallback, which silently loaded the wrong file if the expected path did not exist, a security concern in itself.Edge cases identified and addressed
action.codecan containactions\\code.json Windows. Fixed by normalizing all backslashes with.replace(/\\/g, '/')before callingpath.resolve../, causing the path to be misresolved. Fixed by resolving directly fromcontext.filePathusingpath.resolve.rules/subfolder (e.g., "somerule.js"), not the config root. Fixed by resolving fromconfigRoot/rules/inrules.tsandconfigRoot/hooks/inhooks.ts.loadFile()- On Unix,path.join(base, absolutePath)silently discards the base. The oldloadFile()was vulnerable to this. Fixed by usingpath.resolve()throughout, which handles absolute paths correctly.loadFile()tried inSubfolder, and if the file didn't exist there, fell back to inRoot with no error or warning. This could silently load the wrong file. Removed entirely, path is now resolved deterministically with no fallback.AUTH0_ALLOW_EXTERNAL_CODE_PATHSescape hatch (see below).What changed
loadFile()delegation with an explicitpath.resolve+startsWithcheck, directly callingloadFileAndReplaceKeywords. Now consistent withdatabases.ts.rules.ts/hooks.ts: ReplacedloadFile()delegation with the same inlinepath.resolve+startsWithcheck.directory/index.ts(loadFile()): Removed theisFilefallback. Throws a hard error when path resolves outside config root.yaml/index.ts(loadFile()): Same fix - throws hard error when path resolves outside config root.databases.ts: Detection logic was already correct; updated to supportAUTH0_ALLOW_EXTERNAL_CODE_PATHSconsistently with other handlers.types.ts: AddedAUTH0_ALLOW_EXTERNAL_CODE_PATHS?: booleanto the Config type.docs/configuring-the-deploy-cli.md: Added documentation forAUTH0_ALLOW_EXTERNAL_CODE_PATHSincluding the monorepo use case, directory structure example, and security notice.AUTH0_ALLOW_EXTERNAL_CODE_PATHSescape hatchIntroduces an explicit opt-in config flag for monorepo setups where code files legitimately reside outside the config root directory. When set to true, the path traversal check is bypassed and a debug log is emitted instead of an error.
AUTH0_ALLOW_EXTERNAL_CODE_PATHSflag.This flag was introduced solely to support the monorepo use case described above. However, it bypasses the path traversal protection that this PR introduces. The security team should confirm whether this escape hatch is acceptable and under what conditions it should be permitted. Full context is documented in
docs/configuring-the-deploy-cli.md📚 References
🔬 Testing
Unit tests have been added or updated for all affected handlers:
test/context/directory/actions.test.js: Added tests for path traversal rejection, valid relative paths, escape hatch (AUTH0_ALLOW_EXTERNAL_CODE_PATHS), and Windows-style backslash paths.test/context/directory/rules.test.js: Added test for path traversal rejection via rejectedWith.test/context/directory/hooks.test.js: Added test for path traversal rejection via rejectedWith.All 27 tests in the above files pass. Test assertions were updated from warnSpy checks to rejectedWith(Error, 'is outside the config directory') to reflect the hard error behavior on this beta branch.
Manual testing:
../../ traversal- verify the deploy fails with a clear error message../actions/action-one/code.js) - verify it deploys without error.AUTH0_ALLOW_EXTERNAL_CODE_PATHS: truewith an external path - verify it loads successfully with a debug log.📝 Checklist