|
74 | 74 | // preventing shell injection when the username is interpolated into sh -c. |
75 | 75 | usernameRe = regexp.MustCompile(`^[A-Za-z0-9._][A-Za-z0-9._-]*$`) |
76 | 76 |
|
| 77 | + // dsclNFSHomeDirRe matches a dscl NFSHomeDirectory output line tolerating |
| 78 | + // any amount of leading whitespace before the key and any whitespace |
| 79 | + // after the colon. It captures the first non-whitespace token which |
| 80 | + // is always the home directory path in well-formed dscl output. |
| 81 | + dsclNFSHomeDirRe = regexp.MustCompile(`^\s*NFSHomeDirectory:\s*(\S+)`) |
| 82 | + |
77 | 83 | // externalCmdTimeout is the maximum time allowed for external subprocess |
78 | 84 | // calls (id, dscl, sh). A conservative default prevents Dir()/Expand() |
79 | 85 | // from hanging indefinitely on slow NSS/LDAP/directory backends. |
@@ -460,18 +466,17 @@ func getDarwinHomeDir(cachedUsername string) (string, error) { |
460 | 466 | } |
461 | 467 |
|
462 | 468 | // parseDsclNFSHomeDir extracts the home directory from dscl output. |
463 | | -// It accepts leading/trailing whitespace around the key and multiple spaces |
464 | | -// after the colon (defensive against dscl output variants). The returned path |
465 | | -// is filepath.Clean'd. Returns ErrBlankOutput when the key is absent or the |
| 469 | +// It uses a compiled regex to tolerate any amount of leading whitespace before |
| 470 | +// the key and multiple spaces/tabs after the colon. The returned path is |
| 471 | +// filepath.Clean'd. Returns ErrBlankOutput when the key is absent or the |
466 | 472 | // parsed value is empty, ".", or a non-absolute path (malformed record). |
467 | 473 | func parseDsclNFSHomeDir(output string) (string, error) { |
468 | 474 | for _, line := range strings.Split(output, "\n") { |
469 | | - trimmed := strings.TrimSpace(line) |
470 | | - after, ok := strings.CutPrefix(trimmed, "NFSHomeDirectory:") |
471 | | - if !ok { |
| 475 | + m := dsclNFSHomeDirRe.FindStringSubmatch(line) |
| 476 | + if m == nil { |
472 | 477 | continue |
473 | 478 | } |
474 | | - home := filepath.Clean(strings.TrimSpace(after)) |
| 479 | + home := filepath.Clean(m[1]) |
475 | 480 | if home == "" || home == "." { |
476 | 481 | continue |
477 | 482 | } |
|
0 commit comments