TestWorkspacePathTraversal verifies that a module cannot use Workspace to escape the workspace root and access arbitrary host paths.
(ctx context.Context, t *testctx.T)
| 409 | // TestWorkspacePathTraversal verifies that a module cannot use Workspace to |
| 410 | // escape the workspace root and access arbitrary host paths. |
| 411 | func (WorkspaceSuite) TestWorkspacePathTraversal(ctx context.Context, t *testctx.T) { |
| 412 | c := connect(ctx, t) |
| 413 | |
| 414 | base := workspaceBase(t, c). |
| 415 | WithNewFile("legit.txt", "legit") |
| 416 | |
| 417 | t.Run("directory traversal with ..", func(ctx context.Context, t *testctx.T) { |
| 418 | ctr := base.With(initStandaloneDangModule("escape-dir", ` |
| 419 | type EscapeDir { |
| 420 | pub source: Directory! |
| 421 | |
| 422 | new(source: Workspace!) { |
| 423 | self.source = source.directory("../..") |
| 424 | self |
| 425 | } |
| 426 | |
| 427 | pub ls: [String!] { |
| 428 | source.entries |
| 429 | } |
| 430 | } |
| 431 | `)) |
| 432 | _, err := ctr.With(daggerCall("ls")).Stdout(ctx) |
| 433 | require.Error(t, err) |
| 434 | requireErrOut(t, err, "resolves outside root") |
| 435 | }) |
| 436 | |
| 437 | t.Run("file traversal with ..", func(ctx context.Context, t *testctx.T) { |
| 438 | ctr := base.With(initStandaloneDangModule("escape-file", ` |
| 439 | type EscapeFile { |
| 440 | pub content: String! |
| 441 | |
| 442 | new(source: Workspace!) { |
| 443 | self.content = source.file("../../etc/hostname").contents |
| 444 | self |
| 445 | } |
| 446 | |
| 447 | pub read: String! { |
| 448 | content |
| 449 | } |
| 450 | } |
| 451 | `)) |
| 452 | _, err := ctr.With(daggerCall("read")).Stdout(ctx) |
| 453 | require.Error(t, err) |
| 454 | requireErrOut(t, err, "resolves outside root") |
| 455 | }) |
| 456 | |
| 457 | t.Run("absolute path resolves from workspace boundary", func(ctx context.Context, t *testctx.T) { |
| 458 | ctr := base. |
| 459 | WithNewFile("sub/inner.txt", "inner"). |
| 460 | With(initStandaloneDangModule("abs-rel", ` |
| 461 | type AbsRel { |
| 462 | pub source: Directory! |
| 463 | |
| 464 | new(source: Workspace!) { |
| 465 | self.source = source.directory("/sub") |
| 466 | self |
| 467 | } |
| 468 |
nothing calls this directly
no test coverage detected