rootwrite

package
v0.81.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package rootwrite catches writes whose containment under a root is resolved lexically only: os.WriteFile / os.Create / os.OpenFile(write flag) / os.MkdirAll on a path built with filepath.Join(root, …) where root is a caller-supplied parameter or field — with no filepath.EvalSymlinks anywhere on the path-producing chain — plus the archive twin: zip.Writer entry names assembled from a parameter with no path.Clean in the function.

The bug class: lexical prefix checks cannot see symlinks. Probes TestApplyRefusesSymlinkEscape (framework/contracts report.go containedPath/Apply, fixed in 77fdbaf4: a diagnostic whose path crossed a symlinked directory was written outside the project root even though Join+HasPrefix said "contained") and TestPackZipPrefixCannotEscapeDir (framework/sdk zip.go PackZip, fixed in 1501a555: a "../" prefix placed archive entries above the target directory on extract).

Silent postures, deliberately:

  • any filepath.EvalSymlinks on the chain (writing function, or the same-package helper that produced the path) — the fix posture;
  • roots that are not parameters or root/base/dir-named fields: a constant or computed root has no caller-controlled boundary to defend;
  • joins whose every non-root argument is a literal: nothing caller-controlled is appended under the root;
  • temp roots: a local bound to os.MkdirTemp or t.TempDir is throwaway by construction;
  • zip entry names assembled only from literals or non-parameter values, and any function that calls path.Clean / filepath.Clean;
  • reads (os.Open, os.ReadFile, O_RDONLY) by construction;
  • _test.go files.

Narrowed 2026-09-02 after the whole-repo run: a direct Join must carry a caller-controlled (parameter-derived) component beside the root — formatted timestamps, counters, manifest literals, and generated ids are not escape vectors — and zip entry names must be COMPOSED from a parameter, not forwarded through a wrapper whose own callers compose. Calls to symlink-named guards (EnsureNoSymlinkPath) count as resolution. A same-package containment helper (rooty first parameter joined with the rest) feeding a write still fires when neither side resolves symlinks: that is the containedPath/Apply pair this rule was born from.

Index

Constants

This section is empty.

Variables

View Source
var Analyzer = &analysis.Analyzer{
	Name: "gofastrrootwrite",
	Doc:  "forbids writes under a root whose containment is lexical only: resolve with filepath.EvalSymlinks, and path.Clean zip entry names",
	Run:  run,
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL