Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions engine/agentfiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (afb *AgentFileBridge) Export(rules []AgentRule, fileType AgentFileType) er
path := filepath.Join(afb.projectDir, string(fileType))

// Read existing content
existing, _ := os.ReadFile(path)
existing, _ := os.ReadFile(path) // #nosec G304 -- path is one of a fixed set of agent instruction filenames (CLAUDE.md, .cursorrules, etc.) joined under the bridge's configured projectDir
existingStr := string(existing)

// Build new content from rules
Expand Down Expand Up @@ -119,10 +119,10 @@ func (afb *AgentFileBridge) Export(rules []AgentRule, fileType AgentFileType) er
}

// Write file
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil {
return err
}
return os.WriteFile(path, []byte(content), 0o644)
return os.WriteFile(path, []byte(content), 0o644) // #nosec G306 -- agent rule files (CLAUDE.md/AGENTS.md/etc.) must remain readable/editable by other tools and users
}

// Sync performs bidirectional sync between yaad and agent files.
Expand Down Expand Up @@ -175,7 +175,7 @@ func (afb *AgentFileBridge) Watch() []string {

// importFile reads a single agent file and extracts rules.
func (afb *AgentFileBridge) importFile(path string, fileType AgentFileType) ([]AgentRule, error) {
f, err := os.Open(path)
f, err := os.Open(path) // #nosec G304 -- path is one of a fixed set of agent instruction filenames (CLAUDE.md, .cursorrules, etc.) joined under the bridge's configured projectDir
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion engine/bloom.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (bf *BloomFilter) positions(term string) []uint64 {

positions := make([]uint64, bf.numHash)
for i := 0; i < bf.numHash; i++ {
positions[i] = (h1 + uint64(i)*h2) % bf.numBits
positions[i] = (h1 + uint64(i)*h2) % bf.numBits // #nosec G115 -- i is a bounded non-negative loop index; hash-mixing conversion
}
return positions
}
Expand Down
2 changes: 1 addition & 1 deletion engine/engine_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ func (e *Engine) renderMemoryFile(ctx context.Context) error {
fmt.Fprintf(&sb, "- **%s** [%s] (tier %d, conf %.1f)\n", label, n.Type, n.Tier, n.Confidence)
}

return os.WriteFile(e.memoryFile, []byte(sb.String()), 0o644)
return os.WriteFile(e.memoryFile, []byte(sb.String()), 0o600)
}

// Close shuts down the engine and its background workers.
Expand Down
8 changes: 4 additions & 4 deletions engine/git_learn.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (gl *GitLearner) LearnFromHistory(ctx context.Context, limit int, since tim
args = append(args, fmt.Sprintf("--since=%s", since.Format("2006-01-02")))
}

out, err := exec.CommandContext(ctx, "git", args...).Output()
out, err := exec.CommandContext(ctx, "git", args...).Output() // #nosec G204 -- fixed "git" binary; args built internally from gl.dir/limit/since, not shell-interpreted
if err != nil {
return result, fmt.Errorf("git log failed: %w", err)
}
Expand Down Expand Up @@ -83,7 +83,7 @@ func (gl *GitLearner) LearnFromHistory(ctx context.Context, limit int, since tim
// LearnFromBlame extracts file-level knowledge from git blame.
// Discovers who owns what and when major changes happened.
func (gl *GitLearner) LearnFromBlame(ctx context.Context, filePath string) error {
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--oneline", "-1", "--diff-filter=A", "--", filePath).Output()
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--oneline", "-1", "--diff-filter=A", "--", filePath).Output() // #nosec G204 -- fixed "git" binary; gl.dir/filePath are caller-supplied paths, not shell-interpreted, and "--" ends flag parsing
if err != nil || len(out) == 0 {
return nil
}
Expand All @@ -104,7 +104,7 @@ func (gl *GitLearner) Suggest(ctx context.Context) ([]MemorySuggestion, error) {
var suggestions []MemorySuggestion

// 1. Find repeated patterns in recent commits
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--oneline", "-50").Output()
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--oneline", "-50").Output() // #nosec G204 -- fixed "git" binary; gl.dir is the configured project directory, not shell-interpreted
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -196,7 +196,7 @@ func (gl *GitLearner) remember(ctx context.Context, content, nodeType string) er
}

func (gl *GitLearner) frequentlyChangedFiles(ctx context.Context) []string {
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--name-only", "--format=", "-30").Output()
out, err := exec.CommandContext(ctx, "git", "-C", gl.dir, "log", "--name-only", "--format=", "-30").Output() // #nosec G204 -- fixed "git" binary; gl.dir is the configured project directory, not shell-interpreted
if err != nil {
return nil
}
Expand Down
5 changes: 3 additions & 2 deletions engine/hnsw.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func (h *HNSW) Save(path string) error {

// saveLocked writes the index without acquiring the lock. Caller must hold h.mu.
func (h *HNSW) saveLocked(path string) (err error) {
f, err := os.Create(path)
f, err := os.Create(path) // #nosec G304 -- path is the index file location computed/configured by the caller (e.g. under the yaad data dir), not externally supplied
if err != nil {
return err
}
Expand All @@ -287,7 +287,7 @@ func (h *HNSW) saveLocked(path string) (err error) {

// LoadHNSW restores an HNSW index from a gob-encoded file at path.
func LoadHNSW(path string) (*HNSW, error) {
f, err := os.Open(path)
f, err := os.Open(path) // #nosec G304 -- path is the index file location computed/configured by the caller (e.g. under the yaad data dir), not externally supplied
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -409,6 +409,7 @@ func (h *HNSW) Compact() {

func (h *HNSW) randomLevel() int {
level := 0
// #nosec G404 -- non-cryptographic use (HNSW level sampling)
for rand.Float64() < h.mL && level < 16 {
level++
}
Expand Down
10 changes: 6 additions & 4 deletions engine/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (ing *Ingester) IngestMarkdown(ctx context.Context, content, source string)

// IngestFile parses a markdown file from disk.
func (ing *Ingester) IngestFile(ctx context.Context, path string) (*IngestResult, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a project file path passed in by the caller (e.g. CLI/agent-driven ingestion), not raw user network input
if err != nil {
return nil, fmt.Errorf("read %s: %w", path, err)
}
Expand All @@ -137,7 +137,7 @@ func (ing *Ingester) IngestFile(ctx context.Context, path string) (*IngestResult

// IngestClaudeMD imports from a CLAUDE.md file (conventions, rules, patterns).
func (ing *Ingester) IngestClaudeMD(ctx context.Context, path string) (*IngestResult, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a project file path passed in by the caller (e.g. CLI/agent-driven ingestion), not raw user network input
if err != nil {
return nil, err
}
Expand All @@ -157,7 +157,7 @@ func (ing *Ingester) IngestClaudeMD(ctx context.Context, path string) (*IngestRe

// IngestCursorRules imports from a .cursorrules file.
func (ing *Ingester) IngestCursorRules(ctx context.Context, path string) (*IngestResult, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a project file path passed in by the caller (e.g. CLI/agent-driven ingestion), not raw user network input
if err != nil {
return nil, err
}
Expand All @@ -178,7 +178,7 @@ func (ing *Ingester) IngestCursorRules(ctx context.Context, path string) (*Inges

// IngestCodeFile extracts specs from source code (functions, types, package purpose).
func (ing *Ingester) IngestCodeFile(ctx context.Context, path string) (*IngestResult, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a project file path passed in by the caller (e.g. CLI/agent-driven ingestion), not raw user network input
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -250,6 +250,7 @@ func (ing *Ingester) DetectStack(ctx context.Context, projectDir string) (*Inges

// Detect from package.json dependencies
pkgJSON := filepath.Join(projectDir, "package.json")
// #nosec G304 -- pkgJSON is a fixed filename joined under the caller-supplied projectDir for stack detection
if data, err := os.ReadFile(pkgJSON); err == nil {
content := string(data)
npmDetect := map[string]string{
Expand All @@ -270,6 +271,7 @@ func (ing *Ingester) DetectStack(ctx context.Context, projectDir string) (*Inges

// Detect from go.mod dependencies
goMod := filepath.Join(projectDir, "go.mod")
// #nosec G304 -- goMod is a fixed filename joined under the caller-supplied projectDir for stack detection
if data, err := os.ReadFile(goMod); err == nil {
content := string(data)
goDetect := map[string]string{
Expand Down
2 changes: 1 addition & 1 deletion engine/integrity.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewMemoryIntegrity(yaadDir string) (*MemoryIntegrity, error) {
mi := &MemoryIntegrity{}

keyPath := filepath.Join(yaadDir, "integrity.key")
rawKey, err := os.ReadFile(keyPath)
rawKey, err := os.ReadFile(keyPath) // #nosec G304 -- keyPath is joined from the caller-supplied yaadDir (the .yaad project data directory), a trusted internal path
if err != nil {
// Generate new key
rawKey = make([]byte, 32)
Expand Down
8 changes: 4 additions & 4 deletions engine/lsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (lsh *MinHashLSH) minHashSignature(terms map[string]bool) []uint64 {
func (lsh *MinHashLSH) hashTerm(term string, perm int) uint64 {
h := fnv.New64a()
// Write permutation seed as 8 bytes
seed := uint64(perm) * 0x9e3779b97f4a7c15
seed := uint64(perm) * 0x9e3779b97f4a7c15 // #nosec G115 -- perm is a bounded non-negative loop index; hash-mixing conversion
var buf [8]byte
buf[0] = byte(seed)
buf[1] = byte(seed >> 8)
Expand All @@ -118,8 +118,8 @@ func (lsh *MinHashLSH) hashTerm(term string, perm int) uint64 {
buf[5] = byte(seed >> 40)
buf[6] = byte(seed >> 48)
buf[7] = byte(seed >> 56)
h.Write(buf[:])
h.Write([]byte(term))
_, _ = h.Write(buf[:]) // #nosec G104 -- hash.Hash.Write never returns an error
_, _ = h.Write([]byte(term)) // #nosec G104 -- hash.Hash.Write never returns an error
return h.Sum64()
}

Expand All @@ -138,7 +138,7 @@ func (lsh *MinHashLSH) bandHash(sig []uint64, band int) uint64 {
buf[5] = byte(v >> 40)
buf[6] = byte(v >> 48)
buf[7] = byte(v >> 56)
h.Write(buf[:])
_, _ = h.Write(buf[:]) // #nosec G104 -- hash.Hash.Write never returns an error
}
return h.Sum64()
}
Expand Down
4 changes: 2 additions & 2 deletions exportimport/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func ExportObsidian(ctx context.Context, store storage.Storage, project, vaultDi
if strings.Contains(cleaned, "..") {
return 0, fmt.Errorf("vault_dir must not contain path traversal components")
}
if err := os.MkdirAll(cleaned, 0o755); err != nil {
if err := os.MkdirAll(cleaned, 0o750); err != nil {
return 0, fmt.Errorf("create vault dir: %w", err)
}
vaultDir = cleaned
Expand Down Expand Up @@ -156,7 +156,7 @@ func ExportObsidian(ctx context.Context, store storage.Storage, project, vaultDi
}

fname := sanitizeFilename(obsidianTitle(n)) + ".md"
if err := os.WriteFile(filepath.Join(vaultDir, fname), []byte(sb.String()), 0o644); err == nil {
if err := os.WriteFile(filepath.Join(vaultDir, fname), []byte(sb.String()), 0o600); err == nil {
written++
}
}
Expand Down
2 changes: 1 addition & 1 deletion exportimport/langgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func ImportLangGraph(ctx context.Context, store storage.Storage, jsonData []byte
Type: "parent",
CreatedAt: time.Now(),
}
store.CreateEdge(ctx, edge) //nolint:errcheck // best-effort
_ = store.CreateEdge(ctx, edge) // best-effort; parent edge creation failure shouldn't abort the import
}
}

Expand Down
2 changes: 1 addition & 1 deletion git/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (w *Watcher) changedFiles(since time.Time) ([]string, error) {
sinceStr := since.UTC().Format("2006-01-02T15:04:05")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
out, err := exec.CommandContext(ctx, "git", "-C", w.dir, "log",
out, err := exec.CommandContext(ctx, "git", "-C", w.dir, "log", // #nosec G204 -- fixed "git" binary; w.dir is the configured project directory, sinceStr is an internally formatted timestamp
"--since="+sinceStr, "--name-only", "--pretty=format:").Output()
if err != nil {
return nil, fmt.Errorf("git log: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion hooks/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (r *Runner) SessionStart(ctx context.Context, in *HookInput) error {

// Write session ID to a temp file for other hooks to pick up
sf := sessionFile(r.project)
if err := os.MkdirAll(filepath.Dir(sf), 0o755); err != nil {
if err := os.MkdirAll(filepath.Dir(sf), 0o750); err != nil {
fmt.Fprintf(os.Stderr, "yaad: warning: could not create session dir: %v\n", err)
return fmt.Errorf("create session dir: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func WritePID(projectDir string) error {
if err := os.MkdirAll(dir, 0o700); err != nil {
return err
}
return os.WriteFile(PIDFile(projectDir), []byte(strconv.Itoa(os.Getpid())), 0o644)
return os.WriteFile(PIDFile(projectDir), []byte(strconv.Itoa(os.Getpid())), 0o600)
}

// RemovePID removes the PID file.
Expand Down Expand Up @@ -150,7 +150,7 @@ func EnsureRunning(projectDir, addr string) error {
if err != nil {
exe = "yaad"
}
cmd := exec.CommandContext(context.Background(), exe, "serve", "--addr", addr)
cmd := exec.CommandContext(context.Background(), exe, "serve", "--addr", addr) // #nosec G204 -- exe is os.Executable() (own binary path) or a fixed fallback; addr is caller-controlled config
cmd.Dir = projectDir
cmd.Stdout = nil
cmd.Stderr = nil
Expand Down
2 changes: 1 addition & 1 deletion internal/tls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TLSConfig(cfg Config, dataDir string) (*tls.Config, error) {
// needsRegen reports whether the cert file is missing, unreadable/unparseable,
// or within one day of expiry — any of which warrants regenerating it.
func needsRegen(certFile string) bool {
pemBytes, err := os.ReadFile(certFile)
pemBytes, err := os.ReadFile(certFile) // #nosec G304 -- certFile is derived from configured dataDir or CertFile config option, not externally supplied
if err != nil {
return true // missing or unreadable
}
Expand Down
1 change: 1 addition & 0 deletions storage/codeindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ func (s *Store) SearchCodeChunksHybrid(ctx context.Context, query string, queryV
args = append(args, lang)
}
args = append(args, 50)
// #nosec G202 -- IN clause is placeholder tokens only; values parameterized
q := `SELECT c.id, c.path, c.start_line, c.end_line, c.content, c.symbol, c.language, c.tokens, c.file_hash, c.schema_version, c.vector,
rank
FROM code_chunks_fts f
Expand Down
Loading