wavetermdev/waveterm · error

access denied: potentially sensitive file: %s

Error message

access denied: potentially sensitive file: %s

What it means

read_text_file consults an isBlockedFile allow/deny list and refuses to read paths deemed potentially sensitive (credentials, keys, env files, etc.). The wrapped reason names the matched rule, and the tool deliberately fails closed to avoid exfiltrating secrets via AI tool calls.

Source

Thrown at pkg/aiusechat/tools_readfile.go:216

}

func verifyReadTextFileInput(input any, toolUseData *uctypes.UIMessageDataToolUse) error {
	params, err := parseReadTextFileInput(input)
	if err != nil {
		return err
	}

	expandedPath, err := wavebase.ExpandHomeDir(params.Filename)
	if err != nil {
		return fmt.Errorf("failed to expand path: %w", err)
	}

	if !filepath.IsAbs(expandedPath) {
		return fmt.Errorf("path must be absolute, got relative path: %s", params.Filename)
	}

	if blocked, reason := isBlockedFile(expandedPath); blocked {
		return fmt.Errorf("access denied: potentially sensitive file: %s", reason)
	}

	fileInfo, err := os.Stat(expandedPath)
	if err != nil {
		return fmt.Errorf("failed to stat file: %w", err)
	}

	if fileInfo.IsDir() {
		return fmt.Errorf("path is a directory, cannot be read with the read_text_file tool. use the read_dir tool if available to read directories")
	}

	return nil
}

func readTextFileCallback(input any, toolUseData *uctypes.UIMessageDataToolUse) (any, error) {
	const ReadLimit = 1024 * 1024 * 1024

	params, err := parseReadTextFileInput(input)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Read the sensitive file out-of-band (shell, editor) instead of via the AI tool.
  2. Move non-secret data out of blocked paths (e.g. don't keep config with secrets in .env if you need tool access).
  3. If a legitimate path is wrongly matched, review/update the isBlockedFile patterns in the repo — don't bypass validation.
  4. Sanitize the request: extract only non-sensitive portions of the file manually.

Example fix

// before
read_text_file({"filename": "/home/user/.ssh/id_rsa"})
// after
// read non-sensitive sibling or use shell outside the AI tool
read_text_file({"filename": "/home/user/.ssh/known_hosts"})
Defensive patterns

Strategy: try-catch

Validate before calling

const BLOCKED = [/\.ssh\//, /\.aws\/credentials/, /\.env/, /id_rsa/, /\bsecrets?\b/i];
const isSensitive = p => BLOCKED.some(re => re.test(p));
if (isSensitive(absPath)) throw new Error("path matches sensitive-file policy");

Try / catch

if err := verifyReadTextFileInput(params); err != nil {
    if strings.HasPrefix(err.Error(), "access denied: potentially sensitive file") {
        // do NOT retry; use out-of-band access or pick a non-sensitive file
    }
}

Prevention

When it happens

Trigger: Requesting files matching sensitive patterns: .ssh keys, ~/.aws/credentials, .env, /etc/shadow, token/secret-named files — whatever isBlockedFile matches in the expanded absolute path.

Common situations: Agents asked to "read the .env file" during debugging; CI pipelines storing secrets in files the tool considers sensitive; attempts (accidental or prompt-injected) to read SSH private keys.

Understand the failure class

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/6f996c1ac21bb71a. Report an issue: GitHub.