-
Notifications
You must be signed in to change notification settings - Fork 0
[Aikido] AI Fix for Potential file inclusion attack via reading file #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |||||
| * Graduated from story-32, story-43, and story-54 | ||||||
| */ | ||||||
| import { describe, it, expect } from "vitest"; | ||||||
| import { filterWorkItemDirectories, buildWorkItemList, normalizePath } from "@/scanner/walk"; | ||||||
| import { filterWorkItemDirectories, buildWorkItemList, normalizePath, walkDirectory } from "@/scanner/walk"; | ||||||
| import type { DirectoryEntry } from "@/types"; | ||||||
|
|
||||||
| describe("filterWorkItemDirectories", () => { | ||||||
|
|
@@ -159,3 +159,51 @@ describe("normalizePath", () => { | |||||
| expect(normalized).toBe(unixPath); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| describe("walkDirectory - Path Traversal Security", () => { | ||||||
| /** | ||||||
| * Security tests for path traversal vulnerability mitigation | ||||||
| * Tests various path traversal attack vectors | ||||||
| */ | ||||||
|
|
||||||
| it("GIVEN path with parent directory traversal WHEN walking THEN throws error", async () => { | ||||||
| // Given: Path with .. attempting to traverse up | ||||||
| const maliciousPath = "../../../etc/passwd"; | ||||||
|
|
||||||
| // When/Then: Should reject the path | ||||||
| await expect(walkDirectory(maliciousPath)).rejects.toThrow("Invalid directory path provided"); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the suggested fix in
Suggested change
|
||||||
| }); | ||||||
|
|
||||||
| it("GIVEN path with embedded parent directory WHEN walking THEN throws error", async () => { | ||||||
| // Given: Path with .. in the middle | ||||||
| const maliciousPath = "specs/../../../etc/passwd"; | ||||||
|
|
||||||
| // When/Then: Should reject the path | ||||||
| await expect(walkDirectory(maliciousPath)).rejects.toThrow("Invalid directory path provided"); | ||||||
| }); | ||||||
|
|
||||||
| it("GIVEN absolute path WHEN walking THEN throws error", async () => { | ||||||
| // Given: Absolute path starting with / | ||||||
| const absolutePath = "/etc/passwd"; | ||||||
|
|
||||||
| // When/Then: Should reject absolute paths | ||||||
| await expect(walkDirectory(absolutePath)).rejects.toThrow("Invalid directory path provided"); | ||||||
| }); | ||||||
|
|
||||||
| it("GIVEN path with multiple parent traversals WHEN walking THEN throws error", async () => { | ||||||
| // Given: Path with multiple .. sequences | ||||||
| const maliciousPath = "../../../../../../etc/shadow"; | ||||||
|
|
||||||
| // When/Then: Should reject the path | ||||||
| await expect(walkDirectory(maliciousPath)).rejects.toThrow("Invalid directory path provided"); | ||||||
| }); | ||||||
|
|
||||||
| it("GIVEN valid relative path WHEN walking THEN accepts path", async () => { | ||||||
| // Given: Valid relative path without traversal | ||||||
| const validPath = "specs/doing"; | ||||||
|
|
||||||
| // When/Then: Should accept valid relative paths | ||||||
| // This will fail if directory doesn't exist, but won't fail the security check | ||||||
| await expect(walkDirectory(validPath)).rejects.toThrow(/Failed to walk directory/); | ||||||
| }); | ||||||
| }); | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current security check is flawed and introduces a critical bug. The check
root.startsWith('/')causes the recursive execution ofwalkDirectoryto fail, because subdirectories are passed as absolute paths in recursive calls. This breaks the directory walking functionality beyond the first level.Additionally, the check
root.includes('..')is not robust. It can block valid paths (e.g.,dir/../other_dir) and doesn't cover all path traversal cases.A more robust and correct approach is to resolve the input path and ensure it stays within the current working directory. This check should only be performed on the initial call to avoid breaking recursion. We can detect the initial call by checking if the
visitedset is empty.