How can I ensure that only root has write access to the files and directories (including symbolic links) in its $PATH?

We could get roots path and then promise that each path recursively has files that are owned by root and that those files are only writeable by root, not writeable by group and not writeable by others. In this example warning vs fixed is implemented for easy switching by the value of a variable. CFEngine operates on local files, and can promise the permissions regardless if the user is from a directory or a local user. We locate all symlinks that exist in any of the directories that make up roots PATH, resolve those link targets and ensure they are root owned and root writeable as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  bundle agent main
  {
    vars:
        "mode" string => "warn";

      # Policy runs as root, so we execute env and extract PATH
        "PATH"
          string => execresult( "/usr/bin/env | awk -F '=' '/^PATH/ {print $2}'", useshell);

      # Here we split the PATH so that we can operate on each directory
        "PATHs" slist => string_split( "$(PATH)", ":", inf );


     # We need to locate all of the symlinks that reside in PATH and resolve the
     # link target for each.
      "symlinks[$(PATHs)]" string => execresult( "/usr/bin/find $(PATHs) -type l", noshell);
        "m" data => '[]';
        "m" data => mergedata( '[]', m, string_split( "$(symlinks[$(PATHs)])", "\n", inf) );
        "i" slist => getvalues( m );
      "target[$(i)]" string => filestat( $(i), linktarget );

    files:
      # Recursively search each directory in PATH aserting that all files (
      # including directories ) are owned by root, with user write access, without
      # group write access, without other write access. Warn or fix based on
      # $(mode) variable.

        # Here we ensure files in directories that makes up $PATH are owned, and
        # only writeable by root.

        "$(PATHs)/." -> { "CFG-072" }
          perms => mo( "u+w,g-w,o-w", root ),
          comment => "If non root users can modify files in roots PATH, then they
                      can subvert the system",
          depth_search => recurse_with_base( inf ),
          file_select => all,
          action => warn_or_fix( $(mode) );

        # Here we ensure that targets of symlinks found in $PATH are owned and
        # only writable by root

        "$(target[$(i)])" -> { "CFG-072" }
          comment => "If non root users can modify files that are targets of
                      symlinks in roots PATH, then they can subvert the system.",
          perms => mo( "u+w,g-w,o-w", root ),
          action => warn_or_fix( $(mode) );
  }
  body action warn_or_fix( mode )
  {
          action_policy => "$(mode)";
  }
  # From stdlib ...
  body file_select all
  # @brief Select all file system entries
  {
        leaf_name => { ".*" };
        file_result => "leaf_name";
  }
  body perms mo(mode,user)
  # @brief Set the file's mode and owners
  # @param mode The new mode
  # @param user The username of the new owner
  {
        owners => { "$(user)" };
        mode   => "$(mode)";
  }
  body depth_search recurse_with_base(d)
  # @brief Search files and directories recursively up to the specified
  # depth, starting from the base directory and including directories on
  # other devices.
  #
  # @param d The maximum search depth
  {
        depth => "$(d)";
        xdev  => "true";
        include_basedir => "true";
  }