Summary
Togoder Security scanned the Go package github.com/spf13/afero@v1.15.0 on Oct 5, 2026. An AI review of 27 source files produced 2 high, 7 medium, 6 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.
Findings 15
Symlink-based escape of base path restrictions
NPS-C40E55DACEBB
The BasePathFs wrapper does not resolve symlinks and delegates operations (Open, OpenFile, Create, etc.) to the underlying Fs. Because the access boundary is enforced only lexically on the requested path, a pre-existing symlink inside the base directory can redirect file operations outside the intended root, allowing read/write access to arbitrary files on the host filesystem.
Path traversal / prefix matching weakness
NPS-7F950625E717
RealPath uses strings.HasPrefix(path, bpath) to ensure the resolved path stays within the base path. This check is insufficient: a crafted name such as '../basepath_evil' can produce a path like '/base/basepath_evil' that passes the prefix check despite escaping the intended directory. Correct implementations should compare with filepath.Separator boundaries (e.g. path == bpath || strings.HasPrefix(path, bpath+string(filepath.Separator))).
Incomplete validation on Windows
NPS-08F0554B2F0B
validateBasePathName only rejects absolute Windows paths and performs no checks on other Go runtime platforms, while RealPath never revalidates the joined result against the cleaned base path with a separator-aware comparison. This makes containment enforcement fragile across platforms.
Potential Panic
NPS-1E295EB0680C
The RemoveAll method calls m.mu.RLock() and then inside the loop calls m.mu.RUnlock() and m.mu.Lock() without proper synchronization, potentially causing a panic due to unlocking an already unlocked mutex or deadlock. This is a reliability issue rather than a security exploit.
Improper Lock Handling / Potential Deadlocks and Race Conditions
NPS-0F888DF150CE
The Rename method calls m.mu.RUnlock() while holding a read lock, then acquires a write lock, then calls m.mu.RLock() again after unlocking the write lock. However, the deferred m.mu.RUnlock() will also execute, leading to an unlock of an already unlocked mutex (panic) or incorrect lock state. This could cause a panic or data corruption, though not directly malicious.
Resource exhaustion / DoS via unbounded in-memory buffering
NPS-8FE8C5288785
The New() function reads every tar entry fully into memory using bytes.Buffer via buf.ReadFrom(t). A malicious tar archive with extremely large entries (or many entries) can exhaust process memory, causing denial of service. There is no size cap or streaming behavior.
Panic on malformed input
NPS-13776A39E1C5
The constructor panics ('tarfs: reading from tar' or 'tarfs: size mismatch') when reading a malformed tar stream. Because this is a library used by other software, a crafted tar can crash the entire host process (unrecovered panic), which is a denial-of-service concern in server contexts.
Unsafe file permissions
NPS-A4DF4AFF0098
WriteReader, SafeWriteReader, and GetTempDir create directories with mode 0o777, which grants write and execute permissions to all users. This can lead to local privilege escalation or unauthorized file modification.
Potential path traversal
NPS-8FEC7FA160E3
GetTempDir uses UnicodeSanitize to remove some characters but still allows '/' and '\', which could potentially be used for directory traversal if subPath is attacker-controlled, though the sanitization restricts many dangerous characters.
Panic on nil parent
NPS-2E8D2BCEDFC7
In unRegisterWithParent, if findParent returns nil, the code calls log.Panic, which will crash the program. This could be triggered by unusual file paths, leading to denial of service. Not malicious but a robustness concern.
Use of log.Panic
NPS-42696BCEC1FA
Use of log.Panic in unRegisterWithParent can cause abrupt termination, which might be exploited for denial of service if an attacker can trigger it. Again, not malicious intent.
Missing Error Handling
NPS-3EDA086B9433
In RemoveAll, the error from unRegisterWithParent is ignored, which could lead to inconsistent state. This is a correctness issue, not a security vulnerability per se.
Path handling uses filepath.Clean without rejecting traversal
NPS-DB57275D1F8C
splitpath normalizes names with filepath.Clean and filepath.ToSlash but does not reject entries containing '../'. While tarfs is an in-memory FS and afero routes lookups through this map, callers that extract or mirror entries from this FS to the real filesystem could be tricked by traversal-containing names. It is a latent trap for downstream users rather than direct exploitation within this file.
Malformed tar header handling / size mismatch reliance
NPS-C8F3E767D139
The code trusts hdr.Size to equal the number of bytes read; if the underlying reader is not a proper tar.Reader (e.g., custom reader wrongly typed), behavior is undefined. More importantly, symlink/hardlink entries in a tar are stored as regular File entries without resolving targets, which could mislead consumers about link semantics.
Panic on error
NPS-976300837AC1
GetTempDir panics if MkdirAll fails, which can crash the program and may be exploitable in contexts where the temp directory path is influenced by untrusted input.
Files reviewed
| File | Verdict | What the reviewer saw |
|---|---|---|
| basepath.go | medium | The BasePathFs implementation of path confinement relies on a string-prefix comparison that can be bypassed and does not guard against symlink escapes, so it cannot be treated as a reliable sandbox boundary for untrusted filenames. |
| memmap.go | medium | The code appears to be a legitimate in-memory filesystem implementation with no malicious patterns, but contains several synchronization and error handling issues that could lead to panics or data corruption. |
| tarfs/fs.go | medium | No direct exfiltration, backdoor, or code execution is present, but the library can be used to trigger memory-exhaustion DoS and process-crashing panics on crafted tar input, and its path normalization may mislead downstream extraction logic. |
| util.go | medium | No malicious patterns detected, but several insecure coding practices (world-writable permissions, panic on error, potential path traversal) could lead to security issues in certain contexts. |
| afero.go | safe | Cleared by Jev triage; no further analysis needed |
| cacheOnReadFs.go | safe | No malicious patterns detected |
| const_bsds.go | safe | No malicious patterns detected |
| const_win_unix.go | safe | No malicious patterns detected |
| copyOnWriteFs.go | safe | No malicious patterns detected; the code is a standard copy-on-write filesystem implementation with no exfiltration, credential harvesting, obfuscation, or backdoor behavior. |
| httpFs.go | safe | No malicious patterns detected in the httpFs.go file; it implements a standard HTTP file system adapter for afero without any red flags. |
| internal/common/adapters.go | safe | Cleared by Jev triage; no further analysis needed |
| iofs.go | safe | Cleared by Jev triage; no further analysis needed |
| ioutil.go | safe | No malicious patterns detected; this is a legitimate fork of Go's ioutil for the afero filesystem abstraction library. |
| lstater.go | safe | Cleared by Jev triage; no further analysis needed |
| match.go | safe | Cleared by Jev triage; no further analysis needed |
| mem/dir.go | safe | Cleared by Jev triage; no further analysis needed |
| mem/dirmap.go | safe | Cleared by Jev triage; no further analysis needed |
| mem/file.go | safe | Cleared by Jev triage; no further analysis needed |
| os.go | safe | This is a legitimate, well-known Go filesystem abstraction library (afero) that only wraps standard os package functions without any malicious patterns. |
| path.go | safe | Cleared by Jev triage; no further analysis needed |
| readonlyfs.go | safe | No malicious patterns detected; this is a standard read-only filesystem wrapper implementing expected permission checks. |
| regexpfs.go | safe | No malicious patterns detected |
| symlink.go | safe | Cleared by Jev triage; no further analysis needed |
| tarfs/file.go | safe | No malicious patterns detected; the code implements a read-only in-memory tar filesystem with no network, exec, credential harvesting, or obfuscation. |
| unionFile.go | safe | No malicious patterns detected; the code is a legitimate implementation of a union filesystem with no network, credential harvesting, obfuscation, or command execution. |
Show 2 more files
| File | Verdict | What the reviewer saw |
|---|---|---|
| zipfs/file.go | safe | No malicious patterns detected |
| zipfs/fs.go | safe | No malicious patterns detected; the code is a read-only ZIP filesystem implementation using afero with appropriate permission restrictions. |
Frequently asked questions
Is github.com/spf13/afero safe to use?
No confirmed malware was found in github.com/spf13/afero@v1.15.0, but the review flagged 2 high, 7 medium, 6 low severity findings for risky patterns worth checking before you rely on it.
Does github.com/spf13/afero contain malware?
No malware was identified in github.com/spf13/afero@v1.15.0 when Togoder Security scanned it on Oct 5, 2026. A new version can still introduce malicious code, so scan the exact versions in your lockfile.
How was github.com/spf13/afero checked?
Togoder Security downloaded the published Go package and had an AI model read its 27 source files, looking for install scripts, credential access, network exfiltration, obfuscation, backdoors and crypto-wallet theft. The results are cached by file hash and shown here.
How do I scan github.com/spf13/afero together with the rest of my dependencies?
Upload your lockfile at https://security.togoder.click/scan or call the API documented at https://security.togoder.click/api-docs. Files that have already been scanned, like the ones in github.com/spf13/afero@v1.15.0, cost nothing.