{"record":{"id":"6f996c1ac21bb71a","repo":"wavetermdev/waveterm","slug":"access-denied-potentially-sensitive-file-s","errorCode":null,"errorMessage":"access denied: potentially sensitive file: %s","messagePattern":"access denied: potentially sensitive file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/tools_readfile.go","lineNumber":216,"sourceCode":"}\n\nfunc verifyReadTextFileInput(input any, toolUseData *uctypes.UIMessageDataToolUse) error {\n\tparams, err := parseReadTextFileInput(input)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\texpandedPath, err := wavebase.ExpandHomeDir(params.Filename)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to expand path: %w\", err)\n\t}\n\n\tif !filepath.IsAbs(expandedPath) {\n\t\treturn fmt.Errorf(\"path must be absolute, got relative path: %s\", params.Filename)\n\t}\n\n\tif blocked, reason := isBlockedFile(expandedPath); blocked {\n\t\treturn fmt.Errorf(\"access denied: potentially sensitive file: %s\", reason)\n\t}\n\n\tfileInfo, err := os.Stat(expandedPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to stat file: %w\", err)\n\t}\n\n\tif fileInfo.IsDir() {\n\t\treturn 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\")\n\t}\n\n\treturn nil\n}\n\nfunc readTextFileCallback(input any, toolUseData *uctypes.UIMessageDataToolUse) (any, error) {\n\tconst ReadLimit = 1024 * 1024 * 1024\n\n\tparams, err := parseReadTextFileInput(input)","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/tools_readfile.go#L198-L234","documentation":"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.","triggerScenarios":"Requesting files matching sensitive patterns: .ssh keys, ~/.aws/credentials, .env, /etc/shadow, token/secret-named files — whatever isBlockedFile matches in the expanded absolute path.","commonSituations":"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.","solutions":["Read the sensitive file out-of-band (shell, editor) instead of via the AI tool.","Move non-secret data out of blocked paths (e.g. don't keep config with secrets in .env if you need tool access).","If a legitimate path is wrongly matched, review/update the isBlockedFile patterns in the repo — don't bypass validation.","Sanitize the request: extract only non-sensitive portions of the file manually."],"exampleFix":"// before\nread_text_file({\"filename\": \"/home/user/.ssh/id_rsa\"})\n// after\n// read non-sensitive sibling or use shell outside the AI tool\nread_text_file({\"filename\": \"/home/user/.ssh/known_hosts\"})","handlingStrategy":"try-catch","validationCode":"const BLOCKED = [/\\.ssh\\//, /\\.aws\\/credentials/, /\\.env/, /id_rsa/, /\\bsecrets?\\b/i];\nconst isSensitive = p => BLOCKED.some(re => re.test(p));\nif (isSensitive(absPath)) throw new Error(\"path matches sensitive-file policy\");","typeGuard":null,"tryCatchPattern":"if err := verifyReadTextFileInput(params); err != nil {\n    if strings.HasPrefix(err.Error(), \"access denied: potentially sensitive file\") {\n        // do NOT retry; use out-of-band access or pick a non-sensitive file\n    }\n}","preventionTips":["Don't point AI file tools at key/credential/env files","Check the isBlockedFile patterns when unsure a path is allowed","Keep secrets outside files the agent needs to read","Treat this error as a security boundary — never bypass or relax it per-call"],"tags":["security","access-control","tooling"],"backgroundTag":"access-denied-sensitive-file","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}